mirror of
https://github.com/YACReader/yacreader
synced 2025-11-12 21:12:43 -05:00
Update QtWebapp to 1.7.11
This commit is contained in:
290
third_party/QtWebApp/CHANGELOG.txt
vendored
Normal file
290
third_party/QtWebApp/CHANGELOG.txt
vendored
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
Dont forget to update the release number also in
|
||||||
|
QtWebApp.pro and httpserver/httpglobal.cpp.
|
||||||
|
|
||||||
|
1.7.11
|
||||||
|
28.12.2019
|
||||||
|
Fix Http Headers are not properly received if the two characters of
|
||||||
|
a line-break (\r\n) were not received together in the same ethernet
|
||||||
|
package.
|
||||||
|
|
||||||
|
1.7.10
|
||||||
|
04.12.2019
|
||||||
|
Add support for other SSL implementations than OpenSSL (as far Qt supports it).
|
||||||
|
Fix log bufffer was triggered only by severities above minLevel (should be "at least" minLevel).
|
||||||
|
|
||||||
|
1.7.9
|
||||||
|
20.06.2019
|
||||||
|
INFO messages do not trigger writing out buffered log messages anymore when
|
||||||
|
bufferSize>0 and minLevel>0.
|
||||||
|
|
||||||
|
1.7.8
|
||||||
|
05.02.2019
|
||||||
|
HttpConnectionHandler closes the socket now in the thread of the socket.
|
||||||
|
Headers and Body sent to the browser are now separated into individual ethernet packets.
|
||||||
|
|
||||||
|
1.7.7
|
||||||
|
04.02.2019
|
||||||
|
HttpConnectionHandler creates a new Qthread instead of being itself a QThread.
|
||||||
|
Improved formatting of thread ID in logger.
|
||||||
|
|
||||||
|
1.7.6
|
||||||
|
18.01.2019
|
||||||
|
Code cleanup with const keywords and type conversions.
|
||||||
|
Update Documentation.
|
||||||
|
|
||||||
|
1.7.5
|
||||||
|
17.01.2019
|
||||||
|
Added content-types for *.xml and *.json to the StaticFileController.
|
||||||
|
Fixed locking and memory leak in HttpSession.
|
||||||
|
|
||||||
|
1.7.4
|
||||||
|
24.05.2018
|
||||||
|
Fixed two possible null-pointer references in case of broken HTTP requests.
|
||||||
|
|
||||||
|
1.7.3
|
||||||
|
25.04.2017
|
||||||
|
Wait until all data are sent before closing connections.
|
||||||
|
|
||||||
|
1.7.2
|
||||||
|
17.01.2017
|
||||||
|
Fixed compile error with MSVC.
|
||||||
|
|
||||||
|
1.7.1
|
||||||
|
10.11.2016
|
||||||
|
Fixed a possible memory leak in case of broken Multipart HTTP Requests.
|
||||||
|
|
||||||
|
1.7.0
|
||||||
|
08.11.2016
|
||||||
|
Introduced namespace "stefanfrings".
|
||||||
|
Improved performance a little.
|
||||||
|
|
||||||
|
1.6.7
|
||||||
|
10.10.2016
|
||||||
|
Fix type of socketDescriptor in qtservice library.
|
||||||
|
Add support for INFO log messages (new since QT 5.5).
|
||||||
|
Improve indentation of log messages.
|
||||||
|
|
||||||
|
1.6.6
|
||||||
|
25.07.2016
|
||||||
|
Removed useless mutex from TemplateLoader.
|
||||||
|
Add mutex to TemplateCache (which is now needed).
|
||||||
|
|
||||||
|
1.6.5
|
||||||
|
10.06.2016
|
||||||
|
Incoming HTTP request headers are now processed case-insensitive.
|
||||||
|
Add support for the HttpOnly flag of cookies.
|
||||||
|
|
||||||
|
1.6.4
|
||||||
|
27.03.2016
|
||||||
|
Fixed constructor of Template class did not load the source file properly.
|
||||||
|
Template loader and cache were not affected.
|
||||||
|
|
||||||
|
1.6.3
|
||||||
|
11.03.2016
|
||||||
|
Fixed compilation error.
|
||||||
|
Added missing implementation of HttpRequest::getPeerAddress().
|
||||||
|
|
||||||
|
1.6.2
|
||||||
|
06.03.2016
|
||||||
|
Added mime types for some file extensions.
|
||||||
|
|
||||||
|
1.6.1
|
||||||
|
25.01.2016
|
||||||
|
Fixed parser of boundary value in multi-part request, which caused that
|
||||||
|
QHttpMultipart did not work on client side.
|
||||||
|
|
||||||
|
1.6.0
|
||||||
|
29.12.2015
|
||||||
|
Much better output buffering, reduces the number of small IP packages.
|
||||||
|
|
||||||
|
1.5.13
|
||||||
|
29.12.2015
|
||||||
|
Improved performance a little.
|
||||||
|
Add support for old HTTP 1.0 clients.
|
||||||
|
Add HttpResposne::flush() and HttpResponse::isConnected() which are helpful to support
|
||||||
|
SSE from HTML 5 specification.
|
||||||
|
|
||||||
|
1.5.12
|
||||||
|
11.12.2015
|
||||||
|
Fix program crash when using SSL with a variable sized thread pool on Windows.
|
||||||
|
Changed name of HttpSessionStore::timerEvent() to fix compiler warnings since Qt 5.0.
|
||||||
|
Add HttpRequest::getRawPath().
|
||||||
|
HttpSessionStore::sessions is now protected.
|
||||||
|
|
||||||
|
1.5.11
|
||||||
|
21.11.2015
|
||||||
|
Fix project file for Mac OS.
|
||||||
|
Add HttpRequest::getPeerAddress() and HttpResponse::getStatusCode().
|
||||||
|
|
||||||
|
1.5.10
|
||||||
|
01.09.2015
|
||||||
|
Modified StaticFileController to support ressource files (path starting with ":/" or "qrc://").
|
||||||
|
|
||||||
|
1.5.9
|
||||||
|
06.08.2015
|
||||||
|
New HttpListener::listen() method, to restart listening after close.
|
||||||
|
Add missing include for QObject in logger.h.
|
||||||
|
Add a call to flush() before closing connections, which solves an issue with nginx.
|
||||||
|
|
||||||
|
1.5.8
|
||||||
|
26.07.2015
|
||||||
|
Fixed segmentation fault error when closing the application while a HTTP request is in progress.
|
||||||
|
New HttpListener::close() method to simplifly proper shutdown.
|
||||||
|
|
||||||
|
1.5.7
|
||||||
|
20.07.2015
|
||||||
|
Fix Qt 5.5 compatibility issue.
|
||||||
|
|
||||||
|
1.5.6
|
||||||
|
22.06.2015
|
||||||
|
Fixed compilation failes if QT does not support SSL.
|
||||||
|
|
||||||
|
1.5.5
|
||||||
|
16.06.2015
|
||||||
|
Improved performance of SSL connections.
|
||||||
|
|
||||||
|
1.5.4
|
||||||
|
15.06.2015
|
||||||
|
Support for Qt versions without OpenSsl.
|
||||||
|
|
||||||
|
1.5.3
|
||||||
|
22.05.2015
|
||||||
|
Fixed Windows issue: QsslSocket cannot be closed from other threads than it was created in.
|
||||||
|
|
||||||
|
1.5.2
|
||||||
|
12.05.2015
|
||||||
|
Fixed Windows issue: QSslSocket cannot send signals to another thread than it was created in.
|
||||||
|
|
||||||
|
1.5.1
|
||||||
|
14.04.2015
|
||||||
|
Add support for pipelining.
|
||||||
|
|
||||||
|
1.5.0
|
||||||
|
03.04.2015
|
||||||
|
Add support for HTTPS.
|
||||||
|
|
||||||
|
1.4.2
|
||||||
|
03.04.2015
|
||||||
|
Fixed HTTP request did not work if it was split into multipe IP packages.
|
||||||
|
|
||||||
|
1.4.1
|
||||||
|
20.03.2015
|
||||||
|
Fixed session cookie expires while the user is active, expiration time was not prolonged on each request.
|
||||||
|
|
||||||
|
1.4.0
|
||||||
|
14.03.2015
|
||||||
|
This release has a new directory structure and new project files to support the creation of a shared library (*.dll or *.so).
|
||||||
|
|
||||||
|
1.3.8
|
||||||
|
12.03.2015
|
||||||
|
Improved shutdown procedure.
|
||||||
|
New config setting "host" which binds the listener to a specific network interface.
|
||||||
|
|
||||||
|
1.3.7
|
||||||
|
14.01.2015
|
||||||
|
Fixed setting maxMultiPartSize worked only with file-uploads but not with form-data.
|
||||||
|
|
||||||
|
1.3.6
|
||||||
|
16.09.2014
|
||||||
|
Fixed DualFileLogger produces no output.
|
||||||
|
|
||||||
|
1.3.5
|
||||||
|
11.06.2014
|
||||||
|
Fixed a multi-threading issue with race condition in StaticFileController.
|
||||||
|
|
||||||
|
1.3.4
|
||||||
|
04.06.2014
|
||||||
|
Fixed wrong content type when the StaticFileController returns a cached index.html.
|
||||||
|
|
||||||
|
1.3.3
|
||||||
|
17.03.2014
|
||||||
|
Improved security of StaticFileController by denying "/.." in any position of the request path.
|
||||||
|
Improved performance of StaticFileController a little.
|
||||||
|
New convenience method HttpResponse::redirect(url).
|
||||||
|
Fixed a missing return statement in StaticFileController.
|
||||||
|
|
||||||
|
1.3.2
|
||||||
|
08.01.2014
|
||||||
|
Fixed HTTP Server ignoring URL parameters when the request contains POST parameters.
|
||||||
|
|
||||||
|
1.3.1
|
||||||
|
15.08.2013
|
||||||
|
Fixed HTTP server not accepting connections on 64bit OS with QT 5.
|
||||||
|
|
||||||
|
1.3.0
|
||||||
|
20.04.2013
|
||||||
|
Updated for compatibility QT 5. You may still use QT 4.7 or 4.8, if you like.
|
||||||
|
Also added support for logging source file name, line number and function name.
|
||||||
|
|
||||||
|
1.2.13
|
||||||
|
03.03.2013
|
||||||
|
Fixed Logger writing wrong timestamp for buffered messages.
|
||||||
|
Improved shutdown procedure. The webserver now processes all final signals before the destructor finishes.
|
||||||
|
|
||||||
|
1.2.12
|
||||||
|
01.03.2013
|
||||||
|
Fixed HttpResponse sending first part of data repeatedly when the amount of data is larger than the available memory for I/O buffer.
|
||||||
|
|
||||||
|
1.2.11
|
||||||
|
06.01.2013
|
||||||
|
Added clearing the write buffer when accepting a new connection, so that it does not send remaining data from an aborted previous connection (which is possibly a bug in QT).
|
||||||
|
|
||||||
|
1.2.10
|
||||||
|
18.12.2012
|
||||||
|
Reduced memory usage of HttpResponse in case of large response.
|
||||||
|
|
||||||
|
1.2.9
|
||||||
|
29.07.2012
|
||||||
|
Added a mutex to HttpConnectionHandlerPool to fix a concurrency issue when a pooled object gets taken from the cache while it times out.
|
||||||
|
Modified HttpConnectionHandler so that it does not throw an exception anymore when a connection gets closed by the peer in the middle of a read.
|
||||||
|
|
||||||
|
1.2.8
|
||||||
|
22.07.2012
|
||||||
|
Fixed a possible concurrency issue when the file cache is so small that it stores less files than the number of threads.
|
||||||
|
|
||||||
|
1.2.7
|
||||||
|
18.07.2012
|
||||||
|
Fixed HttpRequest ignores additional URL parameters of POST requests.
|
||||||
|
Fixed HttpRequest ignores POST parameters of body if there is no Content-Type header.
|
||||||
|
Removed unused tempdir variable from HttpRequest.
|
||||||
|
Added mutex to cache of StaticFileController to prevent concurrency problems.
|
||||||
|
Removed HTTP response with status 408 after read timeout. Connection gets simply closed now.
|
||||||
|
|
||||||
|
1.2.6
|
||||||
|
29.06.2012
|
||||||
|
Fixed a compilation error on 64 bit if super verbose debugging is enabled.
|
||||||
|
Fixed a typo in static file controller related to the document type header.
|
||||||
|
|
||||||
|
1.2.5
|
||||||
|
27.06.2012
|
||||||
|
Fixed error message "QThread: Destroyed while thread is still running" during program termination.
|
||||||
|
|
||||||
|
1.2.4
|
||||||
|
02.06.2012
|
||||||
|
Fixed template engine skipping variable tokens when a value is shorter than the token.
|
||||||
|
|
||||||
|
1.2.3
|
||||||
|
26.12.2011
|
||||||
|
Fixed null pointer error when the HTTP server aborts a request that is too large.
|
||||||
|
|
||||||
|
1.2.2
|
||||||
|
06.11.2011
|
||||||
|
Fixed compilation error on 64 bit platforms.
|
||||||
|
|
||||||
|
1.2.1
|
||||||
|
22.10.2011
|
||||||
|
Fixed a multi-threading bug in HttpConnectionHandler.
|
||||||
|
|
||||||
|
1.2.0
|
||||||
|
05.12.2010
|
||||||
|
Added a controller that serves static files, with cacheing.
|
||||||
|
|
||||||
|
|
||||||
|
1.1.0
|
||||||
|
19.10.2010
|
||||||
|
Added support for sessions.
|
||||||
|
Separated the base classes into individual libraries.
|
||||||
|
|
||||||
|
1.0.0
|
||||||
|
17.10.2010
|
||||||
|
First release
|
||||||
165
third_party/QtWebApp/LICENSE.txt
vendored
Normal file
165
third_party/QtWebApp/LICENSE.txt
vendored
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
||||||
25
third_party/QtWebApp/README.txt
vendored
Normal file
25
third_party/QtWebApp/README.txt
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
QtWebAppLib is a library to develop server-side web applications in C++.
|
||||||
|
It requires the Qt SDK version 4.7.0 or newer.
|
||||||
|
|
||||||
|
License: LGPL v3.
|
||||||
|
|
||||||
|
Project homepage: http://stefanfrings.de/qtwebapp/index.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.
|
||||||
|
|
||||||
|
Demo1 shows how to use the library by including the source code into your
|
||||||
|
project. This does not depend on the shared library.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
@ -6,8 +6,10 @@
|
|||||||
#include "httpconnectionhandler.h"
|
#include "httpconnectionhandler.h"
|
||||||
#include "httpresponse.h"
|
#include "httpresponse.h"
|
||||||
|
|
||||||
HttpConnectionHandler::HttpConnectionHandler(QSettings* settings, HttpRequestHandler* requestHandler, QSslConfiguration* sslConfiguration)
|
using namespace stefanfrings;
|
||||||
: QThread()
|
|
||||||
|
HttpConnectionHandler::HttpConnectionHandler(const QSettings *settings, HttpRequestHandler *requestHandler, const QSslConfiguration* sslConfiguration)
|
||||||
|
: QObject()
|
||||||
{
|
{
|
||||||
Q_ASSERT(settings!=nullptr);
|
Q_ASSERT(settings!=nullptr);
|
||||||
Q_ASSERT(requestHandler!=nullptr);
|
Q_ASSERT(requestHandler!=nullptr);
|
||||||
@ -17,43 +19,56 @@ HttpConnectionHandler::HttpConnectionHandler(QSettings* settings, HttpRequestHan
|
|||||||
currentRequest=nullptr;
|
currentRequest=nullptr;
|
||||||
busy=false;
|
busy=false;
|
||||||
|
|
||||||
// Create TCP or SSL socket
|
// execute signals in a new thread
|
||||||
createSocket();
|
thread = new QThread();
|
||||||
|
thread->start();
|
||||||
|
qDebug("HttpConnectionHandler (%p): thread started", static_cast<void*>(this));
|
||||||
|
moveToThread(thread);
|
||||||
|
readTimer.moveToThread(thread);
|
||||||
|
readTimer.setSingleShot(true);
|
||||||
|
|
||||||
// execute signals in my own thread
|
// Create TCP or SSL socket
|
||||||
moveToThread(this);
|
createSocket();
|
||||||
socket->moveToThread(this);
|
socket->moveToThread(thread);
|
||||||
readTimer.moveToThread(this);
|
|
||||||
|
|
||||||
// Connect signals
|
// Connect signals
|
||||||
connect(socket, SIGNAL(readyRead()), SLOT(read()));
|
connect(socket, SIGNAL(readyRead()), SLOT(read()));
|
||||||
connect(socket, SIGNAL(disconnected()), SLOT(disconnected()));
|
connect(socket, SIGNAL(disconnected()), SLOT(disconnected()));
|
||||||
connect(&readTimer, SIGNAL(timeout()), SLOT(readTimeout()));
|
connect(&readTimer, SIGNAL(timeout()), SLOT(readTimeout()));
|
||||||
readTimer.setSingleShot(true);
|
connect(thread, SIGNAL(finished()), this, SLOT(thread_done()));
|
||||||
|
|
||||||
qDebug("HttpConnectionHandler (%p): constructed", this);
|
qDebug("HttpConnectionHandler (%p): constructed", static_cast<void*>(this));
|
||||||
this->start();
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void HttpConnectionHandler::thread_done()
|
||||||
|
{
|
||||||
|
readTimer.stop();
|
||||||
|
socket->close();
|
||||||
|
delete socket;
|
||||||
|
qDebug("HttpConnectionHandler (%p): thread stopped", static_cast<void*>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HttpConnectionHandler::~HttpConnectionHandler()
|
HttpConnectionHandler::~HttpConnectionHandler()
|
||||||
{
|
{
|
||||||
quit();
|
thread->quit();
|
||||||
wait();
|
thread->wait();
|
||||||
qDebug("HttpConnectionHandler (%p): destroyed", this);
|
thread->deleteLater();
|
||||||
|
qDebug("HttpConnectionHandler (%p): destroyed", static_cast<void*>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void HttpConnectionHandler::createSocket()
|
void HttpConnectionHandler::createSocket()
|
||||||
{
|
{
|
||||||
// If SSL is supported and configured, then create an instance of QSslSocket
|
// If SSL is supported and configured, then create an instance of QSslSocket
|
||||||
#ifndef QT_NO_OPENSSL
|
#ifndef QT_NO_SSL
|
||||||
if (sslConfiguration)
|
if (sslConfiguration)
|
||||||
{
|
{
|
||||||
QSslSocket* sslSocket=new QSslSocket();
|
QSslSocket* sslSocket=new QSslSocket();
|
||||||
sslSocket->setSslConfiguration(*sslConfiguration);
|
sslSocket->setSslConfiguration(*sslConfiguration);
|
||||||
socket=sslSocket;
|
socket=sslSocket;
|
||||||
qDebug("HttpConnectionHandler (%p): SSL is enabled", this);
|
qDebug("HttpConnectionHandler (%p): SSL is enabled", static_cast<void*>(this));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -62,27 +77,9 @@ void HttpConnectionHandler::createSocket()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void HttpConnectionHandler::run()
|
|
||||||
{
|
|
||||||
qDebug("HttpConnectionHandler (%p): thread started", this);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
exec();
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
qCritical("HttpConnectionHandler (%p): an uncatched exception occured in the thread",this);
|
|
||||||
}
|
|
||||||
socket->close();
|
|
||||||
delete socket;
|
|
||||||
readTimer.stop();
|
|
||||||
qDebug("HttpConnectionHandler (%p): thread stopped", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void HttpConnectionHandler::handleConnection(tSocketDescriptor socketDescriptor)
|
void HttpConnectionHandler::handleConnection(tSocketDescriptor socketDescriptor)
|
||||||
{
|
{
|
||||||
qDebug("HttpConnectionHandler (%p): handle new connection", this);
|
qDebug("HttpConnectionHandler (%p): handle new connection", static_cast<void*>(this));
|
||||||
busy = true;
|
busy = true;
|
||||||
Q_ASSERT(socket->isOpen()==false); // if not, then the handler is already busy
|
Q_ASSERT(socket->isOpen()==false); // if not, then the handler is already busy
|
||||||
|
|
||||||
@ -93,16 +90,17 @@ void HttpConnectionHandler::handleConnection(tSocketDescriptor socketDescriptor)
|
|||||||
|
|
||||||
if (!socket->setSocketDescriptor(socketDescriptor))
|
if (!socket->setSocketDescriptor(socketDescriptor))
|
||||||
{
|
{
|
||||||
qCritical("HttpConnectionHandler (%p): cannot initialize socket: %s", this,qPrintable(socket->errorString()));
|
qCritical("HttpConnectionHandler (%p): cannot initialize socket: %s",
|
||||||
|
static_cast<void*>(this),qPrintable(socket->errorString()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_OPENSSL
|
#ifndef QT_NO_SSL
|
||||||
// Switch on encryption, if SSL is configured
|
// Switch on encryption, if SSL is configured
|
||||||
if (sslConfiguration)
|
if (sslConfiguration)
|
||||||
{
|
{
|
||||||
qDebug("HttpConnectionHandler (%p): Starting encryption", this);
|
qDebug("HttpConnectionHandler (%p): Starting encryption", static_cast<void*>(this));
|
||||||
((QSslSocket*)socket)->startServerEncryption();
|
(static_cast<QSslSocket*>(socket))->startServerEncryption();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -128,12 +126,12 @@ void HttpConnectionHandler::setBusy()
|
|||||||
|
|
||||||
void HttpConnectionHandler::readTimeout()
|
void HttpConnectionHandler::readTimeout()
|
||||||
{
|
{
|
||||||
qDebug("HttpConnectionHandler (%p): read timeout occured",this);
|
qDebug("HttpConnectionHandler (%p): read timeout occured",static_cast<void*>(this));
|
||||||
|
|
||||||
//Commented out because QWebView cannot handle this.
|
//Commented out because QWebView cannot handle this.
|
||||||
//socket->write("HTTP/1.1 408 request timeout\r\nConnection: close\r\n\r\n408 request timeout\r\n");
|
//socket->write("HTTP/1.1 408 request timeout\r\nConnection: close\r\n\r\n408 request timeout\r\n");
|
||||||
|
|
||||||
socket->flush();
|
while(socket->bytesToWrite()) socket->waitForBytesWritten();
|
||||||
socket->disconnectFromHost();
|
socket->disconnectFromHost();
|
||||||
delete currentRequest;
|
delete currentRequest;
|
||||||
currentRequest=nullptr;
|
currentRequest=nullptr;
|
||||||
@ -142,7 +140,7 @@ void HttpConnectionHandler::readTimeout()
|
|||||||
|
|
||||||
void HttpConnectionHandler::disconnected()
|
void HttpConnectionHandler::disconnected()
|
||||||
{
|
{
|
||||||
qDebug("HttpConnectionHandler (%p): disconnected", this);
|
qDebug("HttpConnectionHandler (%p): disconnected", static_cast<void*>(this));
|
||||||
socket->close();
|
socket->close();
|
||||||
readTimer.stop();
|
readTimer.stop();
|
||||||
busy = false;
|
busy = false;
|
||||||
@ -154,7 +152,7 @@ void HttpConnectionHandler::read()
|
|||||||
while (socket->bytesAvailable())
|
while (socket->bytesAvailable())
|
||||||
{
|
{
|
||||||
#ifdef SUPERVERBOSE
|
#ifdef SUPERVERBOSE
|
||||||
qDebug("HttpConnectionHandler (%p): read input",this);
|
qDebug("HttpConnectionHandler (%p): read input",static_cast<void*>(this));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Create new HttpRequest object if necessary
|
// Create new HttpRequest object if necessary
|
||||||
@ -180,7 +178,7 @@ void HttpConnectionHandler::read()
|
|||||||
if (currentRequest->getStatus()==HttpRequest::abort)
|
if (currentRequest->getStatus()==HttpRequest::abort)
|
||||||
{
|
{
|
||||||
socket->write("HTTP/1.1 413 entity too large\r\nConnection: close\r\n\r\n413 Entity too large\r\n");
|
socket->write("HTTP/1.1 413 entity too large\r\nConnection: close\r\n\r\n413 Entity too large\r\n");
|
||||||
socket->flush();
|
while(socket->bytesToWrite()) socket->waitForBytesWritten();
|
||||||
socket->disconnectFromHost();
|
socket->disconnectFromHost();
|
||||||
delete currentRequest;
|
delete currentRequest;
|
||||||
currentRequest=nullptr;
|
currentRequest=nullptr;
|
||||||
@ -191,7 +189,7 @@ void HttpConnectionHandler::read()
|
|||||||
if (currentRequest->getStatus()==HttpRequest::complete)
|
if (currentRequest->getStatus()==HttpRequest::complete)
|
||||||
{
|
{
|
||||||
readTimer.stop();
|
readTimer.stop();
|
||||||
qDebug("HttpConnectionHandler (%p): received request",this);
|
qDebug("HttpConnectionHandler (%p): received request",static_cast<void*>(this));
|
||||||
|
|
||||||
// Copy the Connection:close header to the response
|
// Copy the Connection:close header to the response
|
||||||
HttpResponse response(socket);
|
HttpResponse response(socket);
|
||||||
@ -220,7 +218,8 @@ void HttpConnectionHandler::read()
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
qCritical("HttpConnectionHandler (%p): An uncatched exception occured in the request handler",this);
|
qCritical("HttpConnectionHandler (%p): An uncatched exception occured in the request handler",
|
||||||
|
static_cast<void*>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalize sending the response if not already done
|
// Finalize sending the response if not already done
|
||||||
@ -229,7 +228,7 @@ void HttpConnectionHandler::read()
|
|||||||
response.write(QByteArray(),true);
|
response.write(QByteArray(),true);
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug("HttpConnectionHandler (%p): finished request",this);
|
qDebug("HttpConnectionHandler (%p): finished request",static_cast<void*>(this));
|
||||||
|
|
||||||
// Find out whether the connection must be closed
|
// Find out whether the connection must be closed
|
||||||
if (!closeConnection)
|
if (!closeConnection)
|
||||||
@ -259,7 +258,7 @@ void HttpConnectionHandler::read()
|
|||||||
// Close the connection or prepare for the next request on the same connection.
|
// Close the connection or prepare for the next request on the same connection.
|
||||||
if (closeConnection)
|
if (closeConnection)
|
||||||
{
|
{
|
||||||
socket->flush();
|
while(socket->bytesToWrite()) socket->waitForBytesWritten();
|
||||||
socket->disconnectFromHost();
|
socket->disconnectFromHost();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
#ifndef HTTPCONNECTIONHANDLER_H
|
#ifndef HTTPCONNECTIONHANDLER_H
|
||||||
#define HTTPCONNECTIONHANDLER_H
|
#define HTTPCONNECTIONHANDLER_H
|
||||||
|
|
||||||
#ifndef QT_NO_OPENSSL
|
#ifndef QT_NO_SSL
|
||||||
#include <QSslConfiguration>
|
#include <QSslConfiguration>
|
||||||
#endif
|
#endif
|
||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
@ -17,6 +17,8 @@
|
|||||||
#include "httprequest.h"
|
#include "httprequest.h"
|
||||||
#include "httprequesthandler.h"
|
#include "httprequesthandler.h"
|
||||||
|
|
||||||
|
namespace stefanfrings {
|
||||||
|
|
||||||
/** Alias type definition, for compatibility to different Qt versions */
|
/** Alias type definition, for compatibility to different Qt versions */
|
||||||
#if QT_VERSION >= 0x050000
|
#if QT_VERSION >= 0x050000
|
||||||
typedef qintptr tSocketDescriptor;
|
typedef qintptr tSocketDescriptor;
|
||||||
@ -25,7 +27,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Alias for QSslConfiguration if OpenSSL is not supported */
|
/** Alias for QSslConfiguration if OpenSSL is not supported */
|
||||||
#ifdef QT_NO_OPENSSL
|
#ifdef QT_NO_SSL
|
||||||
#define QSslConfiguration QObject
|
#define QSslConfiguration QObject
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -44,7 +46,7 @@
|
|||||||
The readTimeout value defines the maximum time to wait for a complete HTTP request.
|
The readTimeout value defines the maximum time to wait for a complete HTTP request.
|
||||||
@see HttpRequest for description of config settings maxRequestSize and maxMultiPartSize.
|
@see HttpRequest for description of config settings maxRequestSize and maxMultiPartSize.
|
||||||
*/
|
*/
|
||||||
class DECLSPEC HttpConnectionHandler : public QThread {
|
class DECLSPEC HttpConnectionHandler : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(HttpConnectionHandler)
|
Q_DISABLE_COPY(HttpConnectionHandler)
|
||||||
|
|
||||||
@ -56,7 +58,8 @@ public:
|
|||||||
@param requestHandler Handler that will process each incoming HTTP request
|
@param requestHandler Handler that will process each incoming HTTP request
|
||||||
@param sslConfiguration SSL (HTTPS) will be used if not NULL
|
@param sslConfiguration SSL (HTTPS) will be used if not NULL
|
||||||
*/
|
*/
|
||||||
HttpConnectionHandler(QSettings* settings, HttpRequestHandler* requestHandler, QSslConfiguration* sslConfiguration=nullptr);
|
HttpConnectionHandler(const QSettings* settings, HttpRequestHandler* requestHandler,
|
||||||
|
const QSslConfiguration* sslConfiguration=nullptr);
|
||||||
|
|
||||||
/** Destructor */
|
/** Destructor */
|
||||||
virtual ~HttpConnectionHandler();
|
virtual ~HttpConnectionHandler();
|
||||||
@ -70,11 +73,14 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
/** Configuration settings */
|
/** Configuration settings */
|
||||||
QSettings* settings;
|
const QSettings* settings;
|
||||||
|
|
||||||
/** TCP socket of the current connection */
|
/** TCP socket of the current connection */
|
||||||
QTcpSocket* socket;
|
QTcpSocket* socket;
|
||||||
|
|
||||||
|
/** The thread that processes events of this connection */
|
||||||
|
QThread* thread;
|
||||||
|
|
||||||
/** Time for read timeout detection */
|
/** Time for read timeout detection */
|
||||||
QTimer readTimer;
|
QTimer readTimer;
|
||||||
|
|
||||||
@ -88,10 +94,7 @@ private:
|
|||||||
bool busy;
|
bool busy;
|
||||||
|
|
||||||
/** Configuration for SSL */
|
/** Configuration for SSL */
|
||||||
QSslConfiguration* sslConfiguration;
|
const QSslConfiguration* sslConfiguration;
|
||||||
|
|
||||||
/** Executes the threads own event loop */
|
|
||||||
void run() override;
|
|
||||||
|
|
||||||
/** Create SSL or TCP socket */
|
/** Create SSL or TCP socket */
|
||||||
void createSocket();
|
void createSocket();
|
||||||
@ -102,7 +105,7 @@ public slots:
|
|||||||
Received from from the listener, when the handler shall start processing a new connection.
|
Received from from the listener, when the handler shall start processing a new connection.
|
||||||
@param socketDescriptor references the accepted connection.
|
@param socketDescriptor references the accepted connection.
|
||||||
*/
|
*/
|
||||||
void handleConnection(tSocketDescriptor socketDescriptor);
|
void handleConnection(const tSocketDescriptor socketDescriptor);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
@ -115,6 +118,10 @@ private slots:
|
|||||||
/** Received from the socket when a connection has been closed */
|
/** Received from the socket when a connection has been closed */
|
||||||
void disconnected();
|
void disconnected();
|
||||||
|
|
||||||
|
/** Cleanup after the thread is closed */
|
||||||
|
void thread_done();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end of namespace
|
||||||
|
|
||||||
#endif // HTTPCONNECTIONHANDLER_H
|
#endif // HTTPCONNECTIONHANDLER_H
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#ifndef QT_NO_OPENSSL
|
#ifndef QT_NO_SSL
|
||||||
#include <QSslSocket>
|
#include <QSslSocket>
|
||||||
#include <QSslKey>
|
#include <QSslKey>
|
||||||
#include <QSslCertificate>
|
#include <QSslCertificate>
|
||||||
@ -7,13 +7,15 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include "httpconnectionhandlerpool.h"
|
#include "httpconnectionhandlerpool.h"
|
||||||
|
|
||||||
HttpConnectionHandlerPool::HttpConnectionHandlerPool(QSettings* settings, HttpRequestHandler* requestHandler)
|
using namespace stefanfrings;
|
||||||
|
|
||||||
|
HttpConnectionHandlerPool::HttpConnectionHandlerPool(const QSettings *settings, HttpRequestHandler *requestHandler)
|
||||||
: QObject()
|
: QObject()
|
||||||
{
|
{
|
||||||
Q_ASSERT(settings!=nullptr);
|
Q_ASSERT(settings!=0);
|
||||||
this->settings=settings;
|
this->settings=settings;
|
||||||
this->requestHandler=requestHandler;
|
this->requestHandler=requestHandler;
|
||||||
this->sslConfiguration=nullptr;
|
this->sslConfiguration=NULL;
|
||||||
loadSslConfig();
|
loadSslConfig();
|
||||||
cleanupTimer.start(settings->value("cleanupInterval",1000).toInt());
|
cleanupTimer.start(settings->value("cleanupInterval",1000).toInt());
|
||||||
connect(&cleanupTimer, SIGNAL(timeout()), SLOT(cleanup()));
|
connect(&cleanupTimer, SIGNAL(timeout()), SLOT(cleanup()));
|
||||||
@ -34,7 +36,7 @@ HttpConnectionHandlerPool::~HttpConnectionHandlerPool()
|
|||||||
|
|
||||||
HttpConnectionHandler* HttpConnectionHandlerPool::getConnectionHandler()
|
HttpConnectionHandler* HttpConnectionHandlerPool::getConnectionHandler()
|
||||||
{
|
{
|
||||||
HttpConnectionHandler* freeHandler=nullptr;
|
HttpConnectionHandler* freeHandler=0;
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
// find a free handler in pool
|
// find a free handler in pool
|
||||||
foreach(HttpConnectionHandler* handler, pool)
|
foreach(HttpConnectionHandler* handler, pool)
|
||||||
@ -91,7 +93,7 @@ void HttpConnectionHandlerPool::loadSslConfig()
|
|||||||
QString sslCertFileName=settings->value("sslCertFile","").toString();
|
QString sslCertFileName=settings->value("sslCertFile","").toString();
|
||||||
if (!sslKeyFileName.isEmpty() && !sslCertFileName.isEmpty())
|
if (!sslKeyFileName.isEmpty() && !sslCertFileName.isEmpty())
|
||||||
{
|
{
|
||||||
#ifdef QT_NO_OPENSSL
|
#ifdef QT_NO_SSL
|
||||||
qWarning("HttpConnectionHandlerPool: SSL is not supported");
|
qWarning("HttpConnectionHandlerPool: SSL is not supported");
|
||||||
#else
|
#else
|
||||||
// Convert relative fileNames to absolute, based on the directory of the config file.
|
// Convert relative fileNames to absolute, based on the directory of the config file.
|
||||||
|
|||||||
@ -8,6 +8,8 @@
|
|||||||
#include "httpglobal.h"
|
#include "httpglobal.h"
|
||||||
#include "httpconnectionhandler.h"
|
#include "httpconnectionhandler.h"
|
||||||
|
|
||||||
|
namespace stefanfrings {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Pool of http connection handlers. The size of the pool grows and
|
Pool of http connection handlers. The size of the pool grows and
|
||||||
shrinks on demand.
|
shrinks on demand.
|
||||||
@ -54,7 +56,7 @@ public:
|
|||||||
@param requestHandler The handler that will process each received HTTP request.
|
@param requestHandler The handler that will process each received HTTP request.
|
||||||
@warning The requestMapper gets deleted by the destructor of this pool
|
@warning The requestMapper gets deleted by the destructor of this pool
|
||||||
*/
|
*/
|
||||||
HttpConnectionHandlerPool(QSettings* settings, HttpRequestHandler* requestHandler);
|
HttpConnectionHandlerPool(const QSettings* settings, HttpRequestHandler *requestHandler);
|
||||||
|
|
||||||
/** Destructor */
|
/** Destructor */
|
||||||
virtual ~HttpConnectionHandlerPool();
|
virtual ~HttpConnectionHandlerPool();
|
||||||
@ -65,7 +67,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
/** Settings for this pool */
|
/** Settings for this pool */
|
||||||
QSettings* settings;
|
const QSettings* settings;
|
||||||
|
|
||||||
/** Will be assigned to each Connectionhandler during their creation */
|
/** Will be assigned to each Connectionhandler during their creation */
|
||||||
HttpRequestHandler* requestHandler;
|
HttpRequestHandler* requestHandler;
|
||||||
@ -92,4 +94,6 @@ private slots:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end of namespace
|
||||||
|
|
||||||
#endif // HTTPCONNECTIONHANDLERPOOL_H
|
#endif // HTTPCONNECTIONHANDLERPOOL_H
|
||||||
|
|||||||
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include "httpcookie.h"
|
#include "httpcookie.h"
|
||||||
|
|
||||||
|
using namespace stefanfrings;
|
||||||
|
|
||||||
HttpCookie::HttpCookie()
|
HttpCookie::HttpCookie()
|
||||||
{
|
{
|
||||||
version=1;
|
version=1;
|
||||||
|
|||||||
15
third_party/QtWebApp/httpserver/httpcookie.h
vendored
15
third_party/QtWebApp/httpserver/httpcookie.h
vendored
@ -10,6 +10,8 @@
|
|||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include "httpglobal.h"
|
#include "httpglobal.h"
|
||||||
|
|
||||||
|
namespace stefanfrings {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
HTTP cookie as defined in RFC 2109. This class can also parse
|
HTTP cookie as defined in RFC 2109. This class can also parse
|
||||||
RFC 2965 cookies, but skips fields that are not defined in RFC
|
RFC 2965 cookies, but skips fields that are not defined in RFC
|
||||||
@ -34,7 +36,10 @@ public:
|
|||||||
@param secure If true, the cookie will be sent by the browser to the server only on secure connections
|
@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 httpOnly If true, the browser does not allow client-side scripts to access the cookie
|
||||||
*/
|
*/
|
||||||
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);
|
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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Create a cookie from a string.
|
Create a cookie from a string.
|
||||||
@ -72,7 +77,7 @@ public:
|
|||||||
/** Set secure mode, so that the cookie will be sent by the browser to the server only on secure connections */
|
/** 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);
|
void setSecure(const bool secure);
|
||||||
|
|
||||||
/** Set secure mode, so that he browser does not allow client-side scripts to access the cookie */
|
/** Set HTTP-only mode, so that he browser does not allow client-side scripts to access the cookie */
|
||||||
void setHttpOnly(const bool httpOnly);
|
void setHttpOnly(const bool httpOnly);
|
||||||
|
|
||||||
/** Get the name of this cookie */
|
/** Get the name of this cookie */
|
||||||
@ -87,7 +92,7 @@ public:
|
|||||||
/** Get the domain of this cookie */
|
/** Get the domain of this cookie */
|
||||||
QByteArray getDomain() const;
|
QByteArray getDomain() const;
|
||||||
|
|
||||||
/** Set the maximum age of this cookie in seconds. */
|
/** Get the maximum age of this cookie in seconds. */
|
||||||
int getMaxAge() const;
|
int getMaxAge() const;
|
||||||
|
|
||||||
/** Set the path of this cookie */
|
/** Set the path of this cookie */
|
||||||
@ -96,7 +101,7 @@ public:
|
|||||||
/** Get the secure flag of this cookie */
|
/** Get the secure flag of this cookie */
|
||||||
bool getSecure() const;
|
bool getSecure() const;
|
||||||
|
|
||||||
/** Get the httpOnly of this cookie */
|
/** Get the HTTP-only flag of this cookie */
|
||||||
bool getHttpOnly() const;
|
bool getHttpOnly() const;
|
||||||
|
|
||||||
/** Returns always 1 */
|
/** Returns always 1 */
|
||||||
@ -116,4 +121,6 @@ private:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end of namespace
|
||||||
|
|
||||||
#endif // HTTPCOOKIE_H
|
#endif // HTTPCOOKIE_H
|
||||||
|
|||||||
@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
const char* getQtWebAppLibVersion()
|
const char* getQtWebAppLibVersion()
|
||||||
{
|
{
|
||||||
return "1.6.5";
|
return "1.7.11";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
third_party/QtWebApp/httpserver/httpglobal.h
vendored
1
third_party/QtWebApp/httpserver/httpglobal.h
vendored
@ -23,5 +23,6 @@
|
|||||||
/** Get the library version number */
|
/** Get the library version number */
|
||||||
DECLSPEC const char* getQtWebAppLibVersion();
|
DECLSPEC const char* getQtWebAppLibVersion();
|
||||||
|
|
||||||
|
|
||||||
#endif // HTTPGLOBAL_H
|
#endif // HTTPGLOBAL_H
|
||||||
|
|
||||||
|
|||||||
27
third_party/QtWebApp/httpserver/httplistener.cpp
vendored
27
third_party/QtWebApp/httpserver/httplistener.cpp
vendored
@ -8,7 +8,9 @@
|
|||||||
#include "httpconnectionhandlerpool.h"
|
#include "httpconnectionhandlerpool.h"
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
|
||||||
HttpListener::HttpListener(QSettings* settings, HttpRequestHandler* requestHandler, QObject *parent)
|
using namespace stefanfrings;
|
||||||
|
|
||||||
|
HttpListener::HttpListener(const QSettings* settings, HttpRequestHandler* requestHandler, QObject *parent)
|
||||||
: QTcpServer(parent)
|
: QTcpServer(parent)
|
||||||
{
|
{
|
||||||
Q_ASSERT(settings!=nullptr);
|
Q_ASSERT(settings!=nullptr);
|
||||||
@ -37,21 +39,11 @@ void HttpListener::listen()
|
|||||||
pool=new HttpConnectionHandlerPool(settings,requestHandler);
|
pool=new HttpConnectionHandlerPool(settings,requestHandler);
|
||||||
}
|
}
|
||||||
QString host = settings->value("host").toString();
|
QString host = settings->value("host").toString();
|
||||||
int port=settings->value("port").toInt();
|
quint16 port=settings->value("port").toUInt() & 0xFFFF;
|
||||||
QTcpServer::listen(host.isEmpty() ? QHostAddress::Any : QHostAddress(host), port);
|
QTcpServer::listen(host.isEmpty() ? QHostAddress::Any : QHostAddress(host), port);
|
||||||
|
|
||||||
//YACReader---------------------------------------------
|
|
||||||
//try to listen even if the default port is no available
|
|
||||||
int i = 0;
|
|
||||||
while (!isListening() && i < 1000) {
|
|
||||||
QTcpServer::listen(QHostAddress::Any, (rand() % 45535)+20000);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
//------------------------------------------------------
|
|
||||||
|
|
||||||
if (!isListening())
|
if (!isListening())
|
||||||
{
|
{
|
||||||
qDebug("HttpListener: Cannot bind on port %i: %s",port,qPrintable(errorString()));
|
qCritical("HttpListener: Cannot bind on port %i: %s",port,qPrintable(errorString()));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qDebug("HttpListener: Listening on port %i",port);
|
qDebug("HttpListener: Listening on port %i",port);
|
||||||
@ -82,17 +74,14 @@ void HttpListener::incomingConnection(tSocketDescriptor socketDescriptor) {
|
|||||||
// Let the handler process the new connection.
|
// Let the handler process the new connection.
|
||||||
if (freeHandler)
|
if (freeHandler)
|
||||||
{
|
{
|
||||||
// The descriptor is passed via signal/slot because the handler lives in another
|
// The descriptor is passed via event queue because the handler lives in another thread
|
||||||
// thread and cannot open the socket when directly called by another thread.
|
QMetaObject::invokeMethod(freeHandler, "handleConnection", Qt::QueuedConnection, Q_ARG(tSocketDescriptor, socketDescriptor));
|
||||||
connect(this,SIGNAL(handleConnection(tSocketDescriptor)),freeHandler,SLOT(handleConnection(tSocketDescriptor)));
|
|
||||||
emit handleConnection(socketDescriptor);
|
|
||||||
disconnect(this,SIGNAL(handleConnection(tSocketDescriptor)),freeHandler,SLOT(handleConnection(tSocketDescriptor)));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Reject the connection
|
// Reject the connection
|
||||||
qDebug("HttpListener: Too many incoming connections");
|
qDebug("HttpListener: Too many incoming connections");
|
||||||
auto* socket=new QTcpSocket(this);
|
QTcpSocket* socket=new QTcpSocket(this);
|
||||||
socket->setSocketDescriptor(socketDescriptor);
|
socket->setSocketDescriptor(socketDescriptor);
|
||||||
connect(socket, SIGNAL(disconnected()), socket, SLOT(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->write("HTTP/1.1 503 too many connections\r\nConnection: close\r\n\r\nToo many connections\r\n");
|
||||||
|
|||||||
17
third_party/QtWebApp/httpserver/httplistener.h
vendored
17
third_party/QtWebApp/httpserver/httplistener.h
vendored
@ -14,6 +14,8 @@
|
|||||||
#include "httpconnectionhandlerpool.h"
|
#include "httpconnectionhandlerpool.h"
|
||||||
#include "httprequesthandler.h"
|
#include "httprequesthandler.h"
|
||||||
|
|
||||||
|
namespace stefanfrings {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Listens for incoming TCP connections and and passes all incoming HTTP requests to your implementation of HttpRequestHandler,
|
Listens for incoming TCP connections and and passes all incoming HTTP requests to your implementation of HttpRequestHandler,
|
||||||
which processes the request and generates the response (usually a HTML document).
|
which processes the request and generates the response (usually a HTML document).
|
||||||
@ -47,12 +49,17 @@ public:
|
|||||||
/**
|
/**
|
||||||
Constructor.
|
Constructor.
|
||||||
Creates a connection pool and starts listening on the configured host and port.
|
Creates a connection pool and starts listening on the configured host and port.
|
||||||
@param settings Configuration settings for the HTTP server. Must not be 0.
|
@param settings Configuration settings, usually stored in an INI file. Must not be 0.
|
||||||
|
Settings are read from the current group, so the caller must have called settings->beginGroup().
|
||||||
|
Because the group must not change during runtime, it is recommended to provide a
|
||||||
|
separate QSettings instance that is not used by other parts of the program.
|
||||||
|
The HttpListener does not take over ownership of the QSettings instance, so the
|
||||||
|
caller should destroy it during shutdown.
|
||||||
@param requestHandler Processes each received HTTP request, usually by dispatching to controller classes.
|
@param requestHandler Processes each received HTTP request, usually by dispatching to controller classes.
|
||||||
@param parent Parent object.
|
@param parent Parent object.
|
||||||
@warning Ensure to close or delete the listener before deleting the request handler.
|
@warning Ensure to close or delete the listener before deleting the request handler.
|
||||||
*/
|
*/
|
||||||
HttpListener(QSettings* settings, HttpRequestHandler* requestHandler, QObject* parent = nullptr);
|
HttpListener(const QSettings* settings, HttpRequestHandler* requestHandler, QObject* parent=nullptr);
|
||||||
|
|
||||||
/** Destructor */
|
/** Destructor */
|
||||||
virtual ~HttpListener();
|
virtual ~HttpListener();
|
||||||
@ -71,12 +78,12 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** Serves new incoming connection requests */
|
/** Serves new incoming connection requests */
|
||||||
void incomingConnection(tSocketDescriptor socketDescriptor) override;
|
void incomingConnection(tSocketDescriptor socketDescriptor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** Configuration settings for the HTTP server */
|
/** Configuration settings for the HTTP server */
|
||||||
QSettings* settings;
|
const QSettings* settings;
|
||||||
|
|
||||||
/** Point to the reuqest handler which processes all HTTP requests */
|
/** Point to the reuqest handler which processes all HTTP requests */
|
||||||
HttpRequestHandler* requestHandler;
|
HttpRequestHandler* requestHandler;
|
||||||
@ -95,4 +102,6 @@ signals:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end of namespace
|
||||||
|
|
||||||
#endif // HTTPLISTENER_H
|
#endif // HTTPLISTENER_H
|
||||||
|
|||||||
85
third_party/QtWebApp/httpserver/httprequest.cpp
vendored
85
third_party/QtWebApp/httpserver/httprequest.cpp
vendored
@ -8,24 +8,29 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include "httpcookie.h"
|
#include "httpcookie.h"
|
||||||
|
|
||||||
HttpRequest::HttpRequest(QSettings* settings)
|
using namespace stefanfrings;
|
||||||
|
|
||||||
|
HttpRequest::HttpRequest(const QSettings* settings)
|
||||||
{
|
{
|
||||||
status=waitForRequest;
|
status=waitForRequest;
|
||||||
currentSize=0;
|
currentSize=0;
|
||||||
expectedBodySize=0;
|
expectedBodySize=0;
|
||||||
maxSize=settings->value("maxRequestSize","16000").toInt();
|
maxSize=settings->value("maxRequestSize","16000").toInt();
|
||||||
maxMultiPartSize=settings->value("maxMultiPartSize","1000000").toInt();
|
maxMultiPartSize=settings->value("maxMultiPartSize","1000000").toInt();
|
||||||
|
tempFile=nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void HttpRequest::readRequest(QTcpSocket* socket)
|
void HttpRequest::readRequest(QTcpSocket* socket)
|
||||||
{
|
{
|
||||||
#ifdef SUPERVERBOSE
|
#ifdef SUPERVERBOSE
|
||||||
qDebug("HttpRequest: read request");
|
qDebug("HttpRequest: read request");
|
||||||
#endif
|
#endif
|
||||||
int toRead=maxSize-currentSize+1; // allow one byte more to be able to detect overflow
|
int toRead=maxSize-currentSize+1; // allow one byte more to be able to detect overflow
|
||||||
lineBuffer.append(socket->readLine(toRead));
|
QByteArray dataRead = socket->readLine(toRead);
|
||||||
currentSize+=lineBuffer.size();
|
currentSize += dataRead.size();
|
||||||
if (!lineBuffer.contains('\r') && !lineBuffer.contains('\n'))
|
lineBuffer.append(dataRead);
|
||||||
|
if (!lineBuffer.contains("\r\n"))
|
||||||
{
|
{
|
||||||
#ifdef SUPERVERBOSE
|
#ifdef SUPERVERBOSE
|
||||||
qDebug("HttpRequest: collecting more parts until line break");
|
qDebug("HttpRequest: collecting more parts until line break");
|
||||||
@ -36,13 +41,15 @@ void HttpRequest::readRequest(QTcpSocket* socket)
|
|||||||
lineBuffer.clear();
|
lineBuffer.clear();
|
||||||
if (!newData.isEmpty())
|
if (!newData.isEmpty())
|
||||||
{
|
{
|
||||||
|
qDebug("HttpRequest: from %s: %s",qPrintable(socket->peerAddress().toString()),newData.data());
|
||||||
QList<QByteArray> list=newData.split(' ');
|
QList<QByteArray> list=newData.split(' ');
|
||||||
if (list.count()!=3 || !list.at(2).contains("HTTP"))
|
if (list.count()!=3 || !list.at(2).contains("HTTP"))
|
||||||
{
|
{
|
||||||
qWarning("HttpRequest: received broken HTTP request, invalid first line");
|
qWarning("HttpRequest: received broken HTTP request, invalid first line");
|
||||||
status=abort;
|
status=abort;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
method=list.at(0).trimmed();
|
method=list.at(0).trimmed();
|
||||||
path=list.at(1);
|
path=list.at(1);
|
||||||
version=list.at(2);
|
version=list.at(2);
|
||||||
@ -54,13 +61,11 @@ void HttpRequest::readRequest(QTcpSocket* socket)
|
|||||||
|
|
||||||
void HttpRequest::readHeader(QTcpSocket* socket)
|
void HttpRequest::readHeader(QTcpSocket* socket)
|
||||||
{
|
{
|
||||||
#ifdef SUPERVERBOSE
|
|
||||||
qDebug("HttpRequest: read header");
|
|
||||||
#endif
|
|
||||||
int toRead=maxSize-currentSize+1; // allow one byte more to be able to detect overflow
|
int toRead=maxSize-currentSize+1; // allow one byte more to be able to detect overflow
|
||||||
lineBuffer.append(socket->readLine(toRead));
|
QByteArray dataRead = socket->readLine(toRead);
|
||||||
currentSize+=lineBuffer.size();
|
currentSize += dataRead.size();
|
||||||
if (!lineBuffer.contains('\r') && !lineBuffer.contains('\n'))
|
lineBuffer.append(dataRead);
|
||||||
|
if (!lineBuffer.contains("\r\n"))
|
||||||
{
|
{
|
||||||
#ifdef SUPERVERBOSE
|
#ifdef SUPERVERBOSE
|
||||||
qDebug("HttpRequest: collecting more parts until line break");
|
qDebug("HttpRequest: collecting more parts until line break");
|
||||||
@ -166,18 +171,23 @@ void HttpRequest::readBody(QTcpSocket* socket)
|
|||||||
#ifdef SUPERVERBOSE
|
#ifdef SUPERVERBOSE
|
||||||
qDebug("HttpRequest: receiving multipart body");
|
qDebug("HttpRequest: receiving multipart body");
|
||||||
#endif
|
#endif
|
||||||
if (!tempFile.isOpen())
|
// Create an object for the temporary file, if not already present
|
||||||
|
if (tempFile == nullptr)
|
||||||
{
|
{
|
||||||
tempFile.open();
|
tempFile = new QTemporaryFile;
|
||||||
|
}
|
||||||
|
if (!tempFile->isOpen())
|
||||||
|
{
|
||||||
|
tempFile->open();
|
||||||
}
|
}
|
||||||
// Transfer data in 64kb blocks
|
// Transfer data in 64kb blocks
|
||||||
int fileSize=tempFile.size();
|
qint64 fileSize=tempFile->size();
|
||||||
int toRead=expectedBodySize-fileSize;
|
qint64 toRead=expectedBodySize-fileSize;
|
||||||
if (toRead>65536)
|
if (toRead>65536)
|
||||||
{
|
{
|
||||||
toRead=65536;
|
toRead=65536;
|
||||||
}
|
}
|
||||||
fileSize+=tempFile.write(socket->read(toRead));
|
fileSize+=tempFile->write(socket->read(toRead));
|
||||||
if (fileSize>=maxMultiPartSize)
|
if (fileSize>=maxMultiPartSize)
|
||||||
{
|
{
|
||||||
qWarning("HttpRequest: received too many multipart bytes");
|
qWarning("HttpRequest: received too many multipart bytes");
|
||||||
@ -188,13 +198,13 @@ void HttpRequest::readBody(QTcpSocket* socket)
|
|||||||
#ifdef SUPERVERBOSE
|
#ifdef SUPERVERBOSE
|
||||||
qDebug("HttpRequest: received whole multipart body");
|
qDebug("HttpRequest: received whole multipart body");
|
||||||
#endif
|
#endif
|
||||||
tempFile.flush();
|
tempFile->flush();
|
||||||
if (tempFile.error())
|
if (tempFile->error())
|
||||||
{
|
{
|
||||||
qCritical("HttpRequest: Error writing temp file for multipart body");
|
qCritical("HttpRequest: Error writing temp file for multipart body");
|
||||||
}
|
}
|
||||||
parseMultiPartFile();
|
parseMultiPartFile();
|
||||||
tempFile.close();
|
tempFile->close();
|
||||||
status=complete;
|
status=complete;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -381,10 +391,11 @@ QByteArray HttpRequest::urlDecode(const QByteArray source)
|
|||||||
while (percentChar>=0)
|
while (percentChar>=0)
|
||||||
{
|
{
|
||||||
bool ok;
|
bool ok;
|
||||||
char byte=buffer.mid(percentChar+1,2).toInt(&ok,16);
|
int hexCode=buffer.mid(percentChar+1,2).toInt(&ok,16);
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
buffer.replace(percentChar,3,(char*)&byte,1);
|
char c=char(hexCode);
|
||||||
|
buffer.replace(percentChar,3,&c,1);
|
||||||
}
|
}
|
||||||
percentChar=buffer.indexOf('%',percentChar+1);
|
percentChar=buffer.indexOf('%',percentChar+1);
|
||||||
}
|
}
|
||||||
@ -395,18 +406,18 @@ QByteArray HttpRequest::urlDecode(const QByteArray source)
|
|||||||
void HttpRequest::parseMultiPartFile()
|
void HttpRequest::parseMultiPartFile()
|
||||||
{
|
{
|
||||||
qDebug("HttpRequest: parsing multipart temp file");
|
qDebug("HttpRequest: parsing multipart temp file");
|
||||||
tempFile.seek(0);
|
tempFile->seek(0);
|
||||||
bool finished=false;
|
bool finished=false;
|
||||||
while (!tempFile.atEnd() && !finished && !tempFile.error())
|
while (!tempFile->atEnd() && !finished && !tempFile->error())
|
||||||
{
|
{
|
||||||
#ifdef SUPERVERBOSE
|
#ifdef SUPERVERBOSE
|
||||||
qDebug("HttpRequest: reading multpart headers");
|
qDebug("HttpRequest: reading multpart headers");
|
||||||
#endif
|
#endif
|
||||||
QByteArray fieldName;
|
QByteArray fieldName;
|
||||||
QByteArray fileName;
|
QByteArray fileName;
|
||||||
while (!tempFile.atEnd() && !finished && !tempFile.error())
|
while (!tempFile->atEnd() && !finished && !tempFile->error())
|
||||||
{
|
{
|
||||||
QByteArray line=tempFile.readLine(65536).trimmed();
|
QByteArray line=tempFile->readLine(65536).trimmed();
|
||||||
if (line.startsWith("Content-Disposition:"))
|
if (line.startsWith("Content-Disposition:"))
|
||||||
{
|
{
|
||||||
if (line.contains("form-data"))
|
if (line.contains("form-data"))
|
||||||
@ -443,9 +454,9 @@ void HttpRequest::parseMultiPartFile()
|
|||||||
#endif
|
#endif
|
||||||
QTemporaryFile* uploadedFile=nullptr;
|
QTemporaryFile* uploadedFile=nullptr;
|
||||||
QByteArray fieldValue;
|
QByteArray fieldValue;
|
||||||
while (!tempFile.atEnd() && !finished && !tempFile.error())
|
while (!tempFile->atEnd() && !finished && !tempFile->error())
|
||||||
{
|
{
|
||||||
QByteArray line=tempFile.readLine(65536);
|
QByteArray line=tempFile->readLine(65536);
|
||||||
if (line.startsWith("--"+boundary))
|
if (line.startsWith("--"+boundary))
|
||||||
{
|
{
|
||||||
// Boundary found. Until now we have collected 2 bytes too much,
|
// Boundary found. Until now we have collected 2 bytes too much,
|
||||||
@ -471,7 +482,7 @@ void HttpRequest::parseMultiPartFile()
|
|||||||
parameters.insert(fieldName,fileName);
|
parameters.insert(fieldName,fileName);
|
||||||
qDebug("HttpRequest: set parameter %s=%s",fieldName.data(),fileName.data());
|
qDebug("HttpRequest: set parameter %s=%s",fieldName.data(),fileName.data());
|
||||||
uploadedFiles.insert(fieldName,uploadedFile);
|
uploadedFiles.insert(fieldName,uploadedFile);
|
||||||
qDebug("HttpRequest: uploaded file size is %i",(int) uploadedFile->size());
|
qDebug("HttpRequest: uploaded file size is %lli",uploadedFile->size());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -509,9 +520,9 @@ void HttpRequest::parseMultiPartFile()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tempFile.error())
|
if (tempFile->error())
|
||||||
{
|
{
|
||||||
qCritical("HttpRequest: cannot read temp file, %s",qPrintable(tempFile.errorString()));
|
qCritical("HttpRequest: cannot read temp file, %s",qPrintable(tempFile->errorString()));
|
||||||
}
|
}
|
||||||
#ifdef SUPERVERBOSE
|
#ifdef SUPERVERBOSE
|
||||||
qDebug("HttpRequest: finished parsing multipart temp file");
|
qDebug("HttpRequest: finished parsing multipart temp file");
|
||||||
@ -523,9 +534,20 @@ HttpRequest::~HttpRequest()
|
|||||||
foreach(QByteArray key, uploadedFiles.keys())
|
foreach(QByteArray key, uploadedFiles.keys())
|
||||||
{
|
{
|
||||||
QTemporaryFile* file=uploadedFiles.value(key);
|
QTemporaryFile* file=uploadedFiles.value(key);
|
||||||
file->close();
|
if (file->isOpen())
|
||||||
|
{
|
||||||
|
file->close();
|
||||||
|
}
|
||||||
delete file;
|
delete file;
|
||||||
}
|
}
|
||||||
|
if (tempFile != nullptr)
|
||||||
|
{
|
||||||
|
if (tempFile->isOpen())
|
||||||
|
{
|
||||||
|
tempFile->close();
|
||||||
|
}
|
||||||
|
delete tempFile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QTemporaryFile* HttpRequest::getUploadedFile(const QByteArray fieldName) const
|
QTemporaryFile* HttpRequest::getUploadedFile(const QByteArray fieldName) const
|
||||||
@ -553,3 +575,4 @@ QHostAddress HttpRequest::getPeerAddress() const
|
|||||||
{
|
{
|
||||||
return peerAddress;
|
return peerAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
third_party/QtWebApp/httpserver/httprequest.h
vendored
12
third_party/QtWebApp/httpserver/httprequest.h
vendored
@ -16,6 +16,8 @@
|
|||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
#include "httpglobal.h"
|
#include "httpglobal.h"
|
||||||
|
|
||||||
|
namespace stefanfrings {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This object represents a single HTTP request. It reads the request
|
This object represents a single HTTP request. It reads the request
|
||||||
from a TCP socket and provides getters for the individual parts
|
from a TCP socket and provides getters for the individual parts
|
||||||
@ -46,7 +48,7 @@ public:
|
|||||||
Constructor.
|
Constructor.
|
||||||
@param settings Configuration settings
|
@param settings Configuration settings
|
||||||
*/
|
*/
|
||||||
HttpRequest(QSettings* settings);
|
HttpRequest(const QSettings* settings);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Destructor.
|
Destructor.
|
||||||
@ -59,7 +61,7 @@ public:
|
|||||||
until the status is RequestStatus::complete or RequestStatus::abort.
|
until the status is RequestStatus::complete or RequestStatus::abort.
|
||||||
@param socket Source of the data
|
@param socket Source of the data
|
||||||
*/
|
*/
|
||||||
void readFromSocket(QTcpSocket* socket);
|
void readFromSocket(QTcpSocket *socket);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the status of this reqeust.
|
Get the status of this reqeust.
|
||||||
@ -207,9 +209,9 @@ private:
|
|||||||
QByteArray boundary;
|
QByteArray boundary;
|
||||||
|
|
||||||
/** Temp file, that is used to store the multipart/form-data body */
|
/** Temp file, that is used to store the multipart/form-data body */
|
||||||
QTemporaryFile tempFile;
|
QTemporaryFile* tempFile;
|
||||||
|
|
||||||
/** Parset he multipart body, that has been stored in the temp file. */
|
/** Parse the multipart body, that has been stored in the temp file. */
|
||||||
void parseMultiPartFile();
|
void parseMultiPartFile();
|
||||||
|
|
||||||
/** Sub-procedure of readFromSocket(), read the first line of a request. */
|
/** Sub-procedure of readFromSocket(), read the first line of a request. */
|
||||||
@ -232,4 +234,6 @@ private:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end of namespace
|
||||||
|
|
||||||
#endif // HTTPREQUEST_H
|
#endif // HTTPREQUEST_H
|
||||||
|
|||||||
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include "httprequesthandler.h"
|
#include "httprequesthandler.h"
|
||||||
|
|
||||||
|
using namespace stefanfrings;
|
||||||
|
|
||||||
HttpRequestHandler::HttpRequestHandler(QObject* parent)
|
HttpRequestHandler::HttpRequestHandler(QObject* parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{}
|
{}
|
||||||
|
|||||||
@ -10,6 +10,8 @@
|
|||||||
#include "httprequest.h"
|
#include "httprequest.h"
|
||||||
#include "httpresponse.h"
|
#include "httpresponse.h"
|
||||||
|
|
||||||
|
namespace stefanfrings {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The request handler generates a response for each HTTP request. Web Applications
|
The request handler generates a response for each HTTP request. Web Applications
|
||||||
usually have one central request handler that maps incoming requests to several
|
usually have one central request handler that maps incoming requests to several
|
||||||
@ -46,4 +48,6 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end of namespace
|
||||||
|
|
||||||
#endif // HTTPREQUESTHANDLER_H
|
#endif // HTTPREQUESTHANDLER_H
|
||||||
|
|||||||
@ -5,7 +5,9 @@
|
|||||||
|
|
||||||
#include "httpresponse.h"
|
#include "httpresponse.h"
|
||||||
|
|
||||||
HttpResponse::HttpResponse(QTcpSocket* socket)
|
using namespace stefanfrings;
|
||||||
|
|
||||||
|
HttpResponse::HttpResponse(QTcpSocket *socket)
|
||||||
{
|
{
|
||||||
this->socket=socket;
|
this->socket=socket;
|
||||||
statusCode=200;
|
statusCode=200;
|
||||||
@ -67,6 +69,7 @@ void HttpResponse::writeHeaders()
|
|||||||
}
|
}
|
||||||
buffer.append("\r\n");
|
buffer.append("\r\n");
|
||||||
writeToSocket(buffer);
|
writeToSocket(buffer);
|
||||||
|
socket->flush();
|
||||||
sentHeaders=true;
|
sentHeaders=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +85,7 @@ bool HttpResponse::writeToSocket(QByteArray data)
|
|||||||
socket->waitForBytesWritten(-1);
|
socket->waitForBytesWritten(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int written=socket->write(ptr,remaining);
|
qint64 written=socket->write(ptr,remaining);
|
||||||
if (written==-1)
|
if (written==-1)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
14
third_party/QtWebApp/httpserver/httpresponse.h
vendored
14
third_party/QtWebApp/httpserver/httpresponse.h
vendored
@ -12,6 +12,8 @@
|
|||||||
#include "httpglobal.h"
|
#include "httpglobal.h"
|
||||||
#include "httpcookie.h"
|
#include "httpcookie.h"
|
||||||
|
|
||||||
|
namespace stefanfrings {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This object represents a HTTP response, used to return something to the web client.
|
This object represents a HTTP response, used to return something to the web client.
|
||||||
<p>
|
<p>
|
||||||
@ -39,7 +41,7 @@ public:
|
|||||||
Constructor.
|
Constructor.
|
||||||
@param socket used to write the response
|
@param socket used to write the response
|
||||||
*/
|
*/
|
||||||
HttpResponse(QTcpSocket* socket);
|
HttpResponse(QTcpSocket *socket);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Set a HTTP response header.
|
Set a HTTP response header.
|
||||||
@ -47,7 +49,7 @@ public:
|
|||||||
@param name name of the header
|
@param name name of the header
|
||||||
@param value value of the header
|
@param value value of the header
|
||||||
*/
|
*/
|
||||||
void setHeader(QByteArray name, QByteArray value);
|
void setHeader(const QByteArray name, const QByteArray value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Set a HTTP response header.
|
Set a HTTP response header.
|
||||||
@ -55,7 +57,7 @@ public:
|
|||||||
@param name name of the header
|
@param name name of the header
|
||||||
@param value value of the header
|
@param value value of the header
|
||||||
*/
|
*/
|
||||||
void setHeader(QByteArray name, int value);
|
void setHeader(const QByteArray name, const int value);
|
||||||
|
|
||||||
/** Get the map of HTTP response headers */
|
/** Get the map of HTTP response headers */
|
||||||
QMap<QByteArray,QByteArray>& getHeaders();
|
QMap<QByteArray,QByteArray>& getHeaders();
|
||||||
@ -67,7 +69,7 @@ public:
|
|||||||
Set status code and description. The default is 200,OK.
|
Set status code and description. The default is 200,OK.
|
||||||
You must call this method before the first write().
|
You must call this method before the first write().
|
||||||
*/
|
*/
|
||||||
void setStatus(int statusCode, QByteArray description=QByteArray());
|
void setStatus(const int statusCode, const QByteArray description=QByteArray());
|
||||||
|
|
||||||
/** Return the status code. */
|
/** Return the status code. */
|
||||||
int getStatusCode() const;
|
int getStatusCode() const;
|
||||||
@ -85,7 +87,7 @@ public:
|
|||||||
@param data Data bytes of the body
|
@param data Data bytes of the body
|
||||||
@param lastPart Indicates that this is the last chunk of data and flushes the output buffer.
|
@param lastPart Indicates that this is the last chunk of data and flushes the output buffer.
|
||||||
*/
|
*/
|
||||||
void write(QByteArray data, bool lastPart=false);
|
void write(const QByteArray data, const bool lastPart=false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Indicates whether the body has been sent completely (write() has been called with lastPart=true).
|
Indicates whether the body has been sent completely (write() has been called with lastPart=true).
|
||||||
@ -156,4 +158,6 @@ private:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end of namespace
|
||||||
|
|
||||||
#endif // HTTPRESPONSE_H
|
#endif // HTTPRESPONSE_H
|
||||||
|
|||||||
20
third_party/QtWebApp/httpserver/httpsession.cpp
vendored
20
third_party/QtWebApp/httpserver/httpsession.cpp
vendored
@ -7,6 +7,7 @@
|
|||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
|
using namespace stefanfrings;
|
||||||
|
|
||||||
HttpSession::HttpSession(bool canStore)
|
HttpSession::HttpSession(bool canStore)
|
||||||
{
|
{
|
||||||
@ -17,7 +18,7 @@ HttpSession::HttpSession(bool canStore)
|
|||||||
dataPtr->lastAccess=QDateTime::currentMSecsSinceEpoch();
|
dataPtr->lastAccess=QDateTime::currentMSecsSinceEpoch();
|
||||||
dataPtr->id=QUuid::createUuid().toString().toLocal8Bit();
|
dataPtr->id=QUuid::createUuid().toString().toLocal8Bit();
|
||||||
#ifdef SUPERVERBOSE
|
#ifdef SUPERVERBOSE
|
||||||
qDebug("HttpSession: created new session data with id %s",dataPtr->id.data());
|
qDebug("HttpSession: (constructor) new session %s with refCount=1",dataPtr->id.constData());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -34,7 +35,7 @@ HttpSession::HttpSession(const HttpSession& other)
|
|||||||
dataPtr->lock.lockForWrite();
|
dataPtr->lock.lockForWrite();
|
||||||
dataPtr->refCount++;
|
dataPtr->refCount++;
|
||||||
#ifdef SUPERVERBOSE
|
#ifdef SUPERVERBOSE
|
||||||
qDebug("HttpSession: refCount of %s is %i",dataPtr->id.data(),dataPtr->refCount);
|
qDebug("HttpSession: (constructor) copy session %s refCount=%i",dataPtr->id.constData(),dataPtr->refCount);
|
||||||
#endif
|
#endif
|
||||||
dataPtr->lock.unlock();
|
dataPtr->lock.unlock();
|
||||||
}
|
}
|
||||||
@ -49,7 +50,7 @@ HttpSession& HttpSession::operator= (const HttpSession& other)
|
|||||||
dataPtr->lock.lockForWrite();
|
dataPtr->lock.lockForWrite();
|
||||||
dataPtr->refCount++;
|
dataPtr->refCount++;
|
||||||
#ifdef SUPERVERBOSE
|
#ifdef SUPERVERBOSE
|
||||||
qDebug("HttpSession: refCount of %s is %i",dataPtr->id.data(),dataPtr->refCount);
|
qDebug("HttpSession: (operator=) session %s refCount=%i",dataPtr->id.constData(),dataPtr->refCount);
|
||||||
#endif
|
#endif
|
||||||
dataPtr->lastAccess=QDateTime::currentMSecsSinceEpoch();
|
dataPtr->lastAccess=QDateTime::currentMSecsSinceEpoch();
|
||||||
dataPtr->lock.unlock();
|
dataPtr->lock.unlock();
|
||||||
@ -57,14 +58,15 @@ HttpSession& HttpSession::operator= (const HttpSession& other)
|
|||||||
if (oldPtr)
|
if (oldPtr)
|
||||||
{
|
{
|
||||||
int refCount;
|
int refCount;
|
||||||
oldPtr->lock.lockForRead();
|
oldPtr->lock.lockForWrite();
|
||||||
refCount=oldPtr->refCount--;
|
refCount=--oldPtr->refCount;
|
||||||
#ifdef SUPERVERBOSE
|
#ifdef SUPERVERBOSE
|
||||||
qDebug("HttpSession: refCount of %s is %i",oldPtr->id.data(),oldPtr->refCount);
|
qDebug("HttpSession: (operator=) session %s refCount=%i",oldPtr->id.constData(),oldPtr->refCount);
|
||||||
#endif
|
#endif
|
||||||
oldPtr->lock.unlock();
|
oldPtr->lock.unlock();
|
||||||
if (refCount==0)
|
if (refCount==0)
|
||||||
{
|
{
|
||||||
|
qDebug("HttpSession: deleting old data");
|
||||||
delete oldPtr;
|
delete oldPtr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,10 +77,10 @@ HttpSession::~HttpSession()
|
|||||||
{
|
{
|
||||||
if (dataPtr) {
|
if (dataPtr) {
|
||||||
int refCount;
|
int refCount;
|
||||||
dataPtr->lock.lockForRead();
|
dataPtr->lock.lockForWrite();
|
||||||
refCount=--dataPtr->refCount;
|
refCount=--dataPtr->refCount;
|
||||||
#ifdef SUPERVERBOSE
|
#ifdef SUPERVERBOSE
|
||||||
qDebug("HttpSession: refCount of %s is %i",dataPtr->id.data(),dataPtr->refCount);
|
qDebug("HttpSession: (destructor) session %s refCount=%i",dataPtr->id.constData(),dataPtr->refCount);
|
||||||
#endif
|
#endif
|
||||||
dataPtr->lock.unlock();
|
dataPtr->lock.unlock();
|
||||||
if (refCount==0)
|
if (refCount==0)
|
||||||
@ -179,7 +181,7 @@ void HttpSession::setLastAccess()
|
|||||||
{
|
{
|
||||||
if (dataPtr)
|
if (dataPtr)
|
||||||
{
|
{
|
||||||
dataPtr->lock.lockForRead();
|
dataPtr->lock.lockForWrite();
|
||||||
dataPtr->lastAccess=QDateTime::currentMSecsSinceEpoch();
|
dataPtr->lastAccess=QDateTime::currentMSecsSinceEpoch();
|
||||||
dataPtr->lock.unlock();
|
dataPtr->lock.unlock();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,8 @@
|
|||||||
#include <QReadWriteLock>
|
#include <QReadWriteLock>
|
||||||
#include "httpglobal.h"
|
#include "httpglobal.h"
|
||||||
|
|
||||||
|
namespace stefanfrings {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This class stores data for a single HTTP session.
|
This class stores data for a single HTTP session.
|
||||||
A session can store any number of key/value pairs. This class uses implicit
|
A session can store any number of key/value pairs. This class uses implicit
|
||||||
@ -27,7 +29,7 @@ public:
|
|||||||
@param canStore The session can store data, if this parameter is true.
|
@param canStore The session can store data, if this parameter is true.
|
||||||
Otherwise all calls to set() and remove() do not have any effect.
|
Otherwise all calls to set() and remove() do not have any effect.
|
||||||
*/
|
*/
|
||||||
HttpSession(bool canStore=false);
|
HttpSession(const bool canStore=false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Copy constructor. Creates another HttpSession object that shares the
|
Copy constructor. Creates another HttpSession object that shares the
|
||||||
@ -115,4 +117,6 @@ private:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end of namespace
|
||||||
|
|
||||||
#endif // HTTPSESSION_H
|
#endif // HTTPSESSION_H
|
||||||
|
|||||||
@ -7,7 +7,9 @@
|
|||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
HttpSessionStore::HttpSessionStore(QSettings* settings, QObject* parent)
|
using namespace stefanfrings;
|
||||||
|
|
||||||
|
HttpSessionStore::HttpSessionStore(const QSettings *settings, QObject* parent)
|
||||||
:QObject(parent)
|
:QObject(parent)
|
||||||
{
|
{
|
||||||
this->settings=settings;
|
this->settings=settings;
|
||||||
|
|||||||
@ -15,6 +15,8 @@
|
|||||||
#include "httpresponse.h"
|
#include "httpresponse.h"
|
||||||
#include "httprequest.h"
|
#include "httprequest.h"
|
||||||
|
|
||||||
|
namespace stefanfrings {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Stores HTTP sessions and deletes them when they have expired.
|
Stores HTTP sessions and deletes them when they have expired.
|
||||||
The following configuration settings are required in the config file:
|
The following configuration settings are required in the config file:
|
||||||
@ -35,8 +37,17 @@ class DECLSPEC HttpSessionStore : public QObject {
|
|||||||
Q_DISABLE_COPY(HttpSessionStore)
|
Q_DISABLE_COPY(HttpSessionStore)
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Constructor. */
|
/**
|
||||||
HttpSessionStore(QSettings* settings, QObject* parent=nullptr);
|
Constructor.
|
||||||
|
@param settings Configuration settings, usually stored in an INI file. Must not be 0.
|
||||||
|
Settings are read from the current group, so the caller must have called settings->beginGroup().
|
||||||
|
Because the group must not change during runtime, it is recommended to provide a
|
||||||
|
separate QSettings instance that is not used by other parts of the program.
|
||||||
|
The HttpSessionStore does not take over ownership of the QSettings instance, so the
|
||||||
|
caller should destroy it during shutdown.
|
||||||
|
@param parent Parent object
|
||||||
|
*/
|
||||||
|
HttpSessionStore(const QSettings* settings, QObject* parent=nullptr);
|
||||||
|
|
||||||
/** Destructor */
|
/** Destructor */
|
||||||
virtual ~HttpSessionStore();
|
virtual ~HttpSessionStore();
|
||||||
@ -62,7 +73,7 @@ public:
|
|||||||
@return If autoCreate is disabled, the function returns a null session if there is no session.
|
@return If autoCreate is disabled, the function returns a null session if there is no session.
|
||||||
@see HttpSession::isNull()
|
@see HttpSession::isNull()
|
||||||
*/
|
*/
|
||||||
HttpSession getSession(HttpRequest& request, HttpResponse& response, bool allowCreate=true);
|
HttpSession getSession(HttpRequest& request, HttpResponse& response, const bool allowCreate=true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get a HTTP session by it's ID number.
|
Get a HTTP session by it's ID number.
|
||||||
@ -74,7 +85,7 @@ public:
|
|||||||
HttpSession getSession(const QByteArray id);
|
HttpSession getSession(const QByteArray id);
|
||||||
|
|
||||||
/** Delete a session */
|
/** Delete a session */
|
||||||
void removeSession(HttpSession session);
|
void removeSession(const HttpSession session);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** Storage for the sessions */
|
/** Storage for the sessions */
|
||||||
@ -83,7 +94,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
/** Configuration settings */
|
/** Configuration settings */
|
||||||
QSettings* settings;
|
const QSettings* settings;
|
||||||
|
|
||||||
/** Timer to remove expired sessions */
|
/** Timer to remove expired sessions */
|
||||||
QTimer cleanupTimer;
|
QTimer cleanupTimer;
|
||||||
@ -103,4 +114,6 @@ private slots:
|
|||||||
void sessionTimerEvent();
|
void sessionTimerEvent();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end of namespace
|
||||||
|
|
||||||
#endif // HTTPSESSIONSTORE_H
|
#endif // HTTPSESSIONSTORE_H
|
||||||
|
|||||||
@ -8,13 +8,9 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
//YACReader-----
|
using namespace stefanfrings;
|
||||||
#include "httpsession.h"
|
|
||||||
#include "yacreader_http_session.h"
|
|
||||||
#include "static.h"
|
|
||||||
//--
|
|
||||||
|
|
||||||
StaticFileController::StaticFileController(QSettings* settings, QObject* parent)
|
StaticFileController::StaticFileController(const QSettings *settings, QObject* parent)
|
||||||
:HttpRequestHandler(parent)
|
:HttpRequestHandler(parent)
|
||||||
{
|
{
|
||||||
maxAge=settings->value("maxAge","60000").toInt();
|
maxAge=settings->value("maxAge","60000").toInt();
|
||||||
@ -41,7 +37,7 @@ StaticFileController::StaticFileController(QSettings* settings, QObject* parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void StaticFileController::service(HttpRequest& request, HttpResponse& response)
|
void StaticFileController::service(HttpRequest &request, HttpResponse &response)
|
||||||
{
|
{
|
||||||
QByteArray path=request.getPath();
|
QByteArray path=request.getPath();
|
||||||
// Check if we have the file in cache
|
// Check if we have the file in cache
|
||||||
@ -61,32 +57,6 @@ void StaticFileController::service(HttpRequest& request, HttpResponse& response)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
|
|
||||||
//TODO(DONE) carga sensible al dispositivo y a la localización
|
|
||||||
QString stringPath = path;
|
|
||||||
QStringList paths = QString(path).split('/');
|
|
||||||
QString fileName = paths.last();
|
|
||||||
stringPath.remove(fileName);
|
|
||||||
HttpSession session=Static::sessionStore->getSession(request,response,false);
|
|
||||||
YACReaderHttpSession *ySession = Static::yacreaderSessionStore->getYACReaderSessionHttpSession(session.getId());
|
|
||||||
QString device = "ipad";
|
|
||||||
QString display = "@2x";
|
|
||||||
if (ySession != nullptr) {
|
|
||||||
device = ySession->getDeviceType();
|
|
||||||
display = ySession->getDisplayType();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fileName.endsWith(".png"))
|
|
||||||
fileName = getDeviceAwareFileName(fileName, device, display, request.getHeader("Accept-Language"), stringPath);
|
|
||||||
else
|
|
||||||
fileName = getDeviceAwareFileName(fileName, device, request.getHeader("Accept-Language"), stringPath);
|
|
||||||
QString newPath = stringPath.append(fileName);
|
|
||||||
path = newPath.toLocal8Bit();
|
|
||||||
|
|
||||||
//CAMBIADO
|
|
||||||
//response.setHeader("Connection","close");
|
|
||||||
//END_TODO
|
|
||||||
|
|
||||||
// The file is not in cache.
|
// The file is not in cache.
|
||||||
qDebug("StaticFileController: Cache miss for %s",path.data());
|
qDebug("StaticFileController: Cache miss for %s",path.data());
|
||||||
// Forbid access to files outside the docroot directory
|
// Forbid access to files outside the docroot directory
|
||||||
@ -151,7 +121,7 @@ void StaticFileController::service(HttpRequest& request, HttpResponse& response)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StaticFileController::setContentType(QString fileName, HttpResponse& response) const
|
void StaticFileController::setContentType(const QString fileName, HttpResponse &response) const
|
||||||
{
|
{
|
||||||
if (fileName.endsWith(".png"))
|
if (fileName.endsWith(".png"))
|
||||||
{
|
{
|
||||||
@ -209,85 +179,17 @@ void StaticFileController::setContentType(QString fileName, HttpResponse& respon
|
|||||||
{
|
{
|
||||||
response.setHeader("Content-Type", "application/font-otf");
|
response.setHeader("Content-Type", "application/font-otf");
|
||||||
}
|
}
|
||||||
|
else if (fileName.endsWith(".json"))
|
||||||
|
{
|
||||||
|
response.setHeader("Content-Type", "application/json");
|
||||||
|
}
|
||||||
|
else if (fileName.endsWith(".xml"))
|
||||||
|
{
|
||||||
|
response.setHeader("Content-Type", "text/xml");
|
||||||
|
}
|
||||||
// Todo: add all of your content types
|
// Todo: add all of your content types
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug("StaticFileController: unknown MIME type for filename '%s'", qPrintable(fileName));
|
qDebug("StaticFileController: unknown MIME type for filename '%s'", qPrintable(fileName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//YACReader------------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool StaticFileController::exists(QString localizedName, QString path) const
|
|
||||||
{
|
|
||||||
QString fileName=docroot+"/"+path + localizedName;
|
|
||||||
QFile file(fileName);
|
|
||||||
return file.exists();
|
|
||||||
}
|
|
||||||
|
|
||||||
//retorna fileName si no se encontró alternativa traducida ó fileName-locale.extensión si se encontró
|
|
||||||
QString StaticFileController::getLocalizedFileName(QString fileName, QString locales, QString path) const
|
|
||||||
{
|
|
||||||
QSet<QString> tried; // used to suppress duplicate attempts
|
|
||||||
QStringList locs=locales.split(',',QString::SkipEmptyParts);
|
|
||||||
QStringList fileNameParts = fileName.split('.');
|
|
||||||
QString file = fileNameParts.first();
|
|
||||||
QString extension = fileNameParts.last();
|
|
||||||
// Search for exact match
|
|
||||||
foreach (QString loc,locs) {
|
|
||||||
loc.replace(QRegExp(";.*"),"");
|
|
||||||
loc.replace('-','_');
|
|
||||||
QString localizedName=file+"-"+loc.trimmed()+"."+extension;
|
|
||||||
if (!tried.contains(localizedName)) {
|
|
||||||
if(exists(localizedName, path))
|
|
||||||
return localizedName;
|
|
||||||
tried.insert(localizedName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search for correct language but any country
|
|
||||||
foreach (QString loc,locs) {
|
|
||||||
loc.replace(QRegExp("[;_-].*"),"");
|
|
||||||
QString localizedName=file+"-"+loc.trimmed()+"."+extension;
|
|
||||||
if (!tried.contains(localizedName)) {
|
|
||||||
if(exists(localizedName, path))
|
|
||||||
return localizedName;
|
|
||||||
tried.insert(localizedName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString StaticFileController::getDeviceAwareFileName(QString fileName, QString device, QString locales, QString path) const
|
|
||||||
{
|
|
||||||
QFileInfo fi(fileName);
|
|
||||||
QString baseName = fi.baseName();
|
|
||||||
QString extension = fi.completeSuffix();
|
|
||||||
|
|
||||||
QString completeFileName = getLocalizedFileName(baseName+"_"+device+"."+extension,locales,path);
|
|
||||||
|
|
||||||
if(QFile(docroot+"/"+path+completeFileName).exists())
|
|
||||||
return completeFileName; //existe un archivo específico para este dispositivo y locales
|
|
||||||
else
|
|
||||||
return getLocalizedFileName(fileName,locales,path); //no hay archivo específico para el dispositivo, pero puede haberlo para estas locales
|
|
||||||
}
|
|
||||||
|
|
||||||
QString StaticFileController::getDeviceAwareFileName(QString fileName, QString device, QString display, QString /* locales */, QString path) const
|
|
||||||
{
|
|
||||||
QFileInfo fi(fileName);
|
|
||||||
QString baseName = fi.baseName();
|
|
||||||
QString extension = fi.completeSuffix();
|
|
||||||
|
|
||||||
QString completeFileName = baseName+display+"."+extension;
|
|
||||||
if(QFile(docroot+"/"+path+completeFileName).exists())
|
|
||||||
return completeFileName;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
completeFileName = baseName+"_"+device+display+"."+extension;
|
|
||||||
if((QFile(docroot+"/"+path+completeFileName).exists()))
|
|
||||||
return completeFileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fileName;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -13,6 +13,8 @@
|
|||||||
#include "httpresponse.h"
|
#include "httpresponse.h"
|
||||||
#include "httprequesthandler.h"
|
#include "httprequesthandler.h"
|
||||||
|
|
||||||
|
namespace stefanfrings {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Delivers static files. It is usually called by the applications main request handler when
|
Delivers static files. It is usually called by the applications main request handler when
|
||||||
the caller requests a path that is mapped to static files.
|
the caller requests a path that is mapped to static files.
|
||||||
@ -45,11 +47,20 @@ class DECLSPEC StaticFileController : public HttpRequestHandler {
|
|||||||
Q_DISABLE_COPY(StaticFileController)
|
Q_DISABLE_COPY(StaticFileController)
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Constructor */
|
/**
|
||||||
StaticFileController(QSettings* settings, QObject* parent = nullptr);
|
Constructor.
|
||||||
|
@param settings Configuration settings, usually stored in an INI file. Must not be 0.
|
||||||
|
Settings are read from the current group, so the caller must have called settings->beginGroup().
|
||||||
|
Because the group must not change during runtime, it is recommended to provide a
|
||||||
|
separate QSettings instance that is not used by other parts of the program.
|
||||||
|
The StaticFileController does not take over ownership of the QSettings instance, so the
|
||||||
|
caller should destroy it during shutdown.
|
||||||
|
@param parent Parent object
|
||||||
|
*/
|
||||||
|
StaticFileController(const QSettings* settings, QObject* parent = nullptr);
|
||||||
|
|
||||||
/** Generates the response */
|
/** Generates the response */
|
||||||
void service(HttpRequest& request, HttpResponse& response) override;
|
void service(HttpRequest& request, HttpResponse& response);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -81,14 +92,9 @@ private:
|
|||||||
QMutex mutex;
|
QMutex mutex;
|
||||||
|
|
||||||
/** Set a content-type header in the response depending on the ending of the filename */
|
/** Set a content-type header in the response depending on the ending of the filename */
|
||||||
void setContentType(QString file, HttpResponse& response) const;
|
void setContentType(const QString file, HttpResponse &response) const;
|
||||||
|
|
||||||
//YACReader------------------------------------------------------------------------
|
|
||||||
QString getLocalizedFileName(QString fileName, QString locales, QString path) const;
|
|
||||||
QString getDeviceAwareFileName(QString fileName, QString device, QString locales, QString path) const;
|
|
||||||
QString getDeviceAwareFileName(QString fileName, QString device, QString display, QString locales, QString path) const;
|
|
||||||
|
|
||||||
bool exists(QString localizedName, QString path) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end of namespace
|
||||||
|
|
||||||
#endif // STATICFILECONTROLLER_H
|
#endif // STATICFILECONTROLLER_H
|
||||||
|
|||||||
14
third_party/QtWebApp/templateengine/template.cpp
vendored
14
third_party/QtWebApp/templateengine/template.cpp
vendored
@ -6,14 +6,16 @@
|
|||||||
#include "template.h"
|
#include "template.h"
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
|
||||||
Template::Template(QString source, QString sourceName)
|
using namespace stefanfrings;
|
||||||
|
|
||||||
|
Template::Template(const QString source, const QString sourceName)
|
||||||
: QString(source)
|
: QString(source)
|
||||||
{
|
{
|
||||||
this->sourceName=sourceName;
|
this->sourceName=sourceName;
|
||||||
this->warnings=false;
|
this->warnings=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Template::Template(QFile& file, QTextCodec* textCodec)
|
Template::Template(QFile& file, const QTextCodec* textCodec)
|
||||||
{
|
{
|
||||||
this->warnings=false;
|
this->warnings=false;
|
||||||
sourceName=QFileInfo(file.fileName()).baseName();
|
sourceName=QFileInfo(file.fileName()).baseName();
|
||||||
@ -34,7 +36,7 @@ Template::Template(QFile& file, QTextCodec* textCodec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Template::setVariable(QString name, QString value)
|
int Template::setVariable(const QString name, const QString value)
|
||||||
{
|
{
|
||||||
int count=0;
|
int count=0;
|
||||||
QString variable="{"+name+"}";
|
QString variable="{"+name+"}";
|
||||||
@ -52,7 +54,7 @@ int Template::setVariable(QString name, QString value)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Template::setCondition(QString name, bool value)
|
int Template::setCondition(const QString name, const bool value)
|
||||||
{
|
{
|
||||||
int count=0;
|
int count=0;
|
||||||
QString startTag=QString("{if %1}").arg(name);
|
QString startTag=QString("{if %1}").arg(name);
|
||||||
@ -150,7 +152,7 @@ int Template::setCondition(QString name, bool value)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Template::loop(QString name, int repetitions)
|
int Template::loop(const QString name, const int repetitions)
|
||||||
{
|
{
|
||||||
Q_ASSERT(repetitions>=0);
|
Q_ASSERT(repetitions>=0);
|
||||||
int count=0;
|
int count=0;
|
||||||
@ -234,7 +236,7 @@ int Template::loop(QString name, int repetitions)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Template::enableWarnings(bool enable)
|
void Template::enableWarnings(const bool enable)
|
||||||
{
|
{
|
||||||
warnings=enable;
|
warnings=enable;
|
||||||
}
|
}
|
||||||
|
|||||||
24
third_party/QtWebApp/templateengine/template.h
vendored
24
third_party/QtWebApp/templateengine/template.h
vendored
@ -14,6 +14,8 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include "templateglobal.h"
|
#include "templateglobal.h"
|
||||||
|
|
||||||
|
namespace stefanfrings {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Enhanced version of QString for template processing. Templates
|
Enhanced version of QString for template processing. Templates
|
||||||
are usually loaded from files, but may also be loaded from
|
are usually loaded from files, but may also be loaded from
|
||||||
@ -41,10 +43,10 @@
|
|||||||
t.setVariable("username", "Stefan");
|
t.setVariable("username", "Stefan");
|
||||||
t.setCondition("locked",false);
|
t.setCondition("locked",false);
|
||||||
t.loop("user",2);
|
t.loop("user",2);
|
||||||
t.setVariable("user0.name,"Markus");
|
t.setVariable("user0.name","Markus");
|
||||||
t.setVariable("user0.time,"8:30");
|
t.setVariable("user0.time","8:30");
|
||||||
t.setVariable("user1.name,"Roland");
|
t.setVariable("user1.name","Roland");
|
||||||
t.setVariable("user1.time,"8:45");
|
t.setVariable("user1.time","8:45");
|
||||||
</pre></code></p>
|
</pre></code></p>
|
||||||
<p>
|
<p>
|
||||||
The code example above shows how variable within loops are numbered.
|
The code example above shows how variable within loops are numbered.
|
||||||
@ -95,7 +97,7 @@ public:
|
|||||||
@param source The template source text
|
@param source The template source text
|
||||||
@param sourceName Name of the source file, used for logging
|
@param sourceName Name of the source file, used for logging
|
||||||
*/
|
*/
|
||||||
Template(QString source, QString sourceName);
|
Template(const QString source, const QString sourceName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Constructor that reads the template from a file. Note that this class does not
|
Constructor that reads the template from a file. Note that this class does not
|
||||||
@ -106,7 +108,7 @@ public:
|
|||||||
@see TemplateLoader
|
@see TemplateLoader
|
||||||
@see TemplateCache
|
@see TemplateCache
|
||||||
*/
|
*/
|
||||||
Template(QFile& file, QTextCodec* textCodec);
|
Template(QFile &file, const QTextCodec* textCodec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Replace a variable by the given value.
|
Replace a variable by the given value.
|
||||||
@ -121,7 +123,7 @@ public:
|
|||||||
@param value new value
|
@param value new value
|
||||||
@return The count of variables that have been processed
|
@return The count of variables that have been processed
|
||||||
*/
|
*/
|
||||||
int setVariable(QString name, QString value);
|
int setVariable(const QString name, const QString value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Set a condition. This affects tags with the syntax
|
Set a condition. This affects tags with the syntax
|
||||||
@ -135,7 +137,7 @@ public:
|
|||||||
@param value Value of the condition
|
@param value Value of the condition
|
||||||
@return The count of conditions that have been processed
|
@return The count of conditions that have been processed
|
||||||
*/
|
*/
|
||||||
int setCondition(QString name, bool value);
|
int setCondition(const QString name, bool value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Set number of repetitions of a loop.
|
Set number of repetitions of a loop.
|
||||||
@ -148,13 +150,13 @@ public:
|
|||||||
@param repetitions The number of repetitions
|
@param repetitions The number of repetitions
|
||||||
@return The number of loops that have been processed
|
@return The number of loops that have been processed
|
||||||
*/
|
*/
|
||||||
int loop(QString name, int repetitions);
|
int loop(QString name, const int repetitions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Enable warnings for missing tags
|
Enable warnings for missing tags
|
||||||
@param enable Warnings are enabled, if true
|
@param enable Warnings are enabled, if true
|
||||||
*/
|
*/
|
||||||
void enableWarnings(bool enable=true);
|
void enableWarnings(const bool enable=true);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -165,4 +167,6 @@ private:
|
|||||||
bool warnings;
|
bool warnings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end of namespace
|
||||||
|
|
||||||
#endif // TEMPLATE_H
|
#endif // TEMPLATE_H
|
||||||
|
|||||||
@ -3,7 +3,9 @@
|
|||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
|
||||||
TemplateCache::TemplateCache(QSettings* settings, QObject* parent)
|
using namespace stefanfrings;
|
||||||
|
|
||||||
|
TemplateCache::TemplateCache(const QSettings* settings, QObject* parent)
|
||||||
:TemplateLoader(settings,parent)
|
:TemplateLoader(settings,parent)
|
||||||
{
|
{
|
||||||
cache.setMaxCost(settings->value("cacheSize","1000000").toInt());
|
cache.setMaxCost(settings->value("cacheSize","1000000").toInt());
|
||||||
@ -11,14 +13,16 @@ TemplateCache::TemplateCache(QSettings* settings, QObject* parent)
|
|||||||
qDebug("TemplateCache: timeout=%i, size=%i",cacheTimeout,cache.maxCost());
|
qDebug("TemplateCache: timeout=%i, size=%i",cacheTimeout,cache.maxCost());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TemplateCache::tryFile(QString localizedName)
|
QString TemplateCache::tryFile(const QString localizedName)
|
||||||
{
|
{
|
||||||
qint64 now=QDateTime::currentMSecsSinceEpoch();
|
qint64 now=QDateTime::currentMSecsSinceEpoch();
|
||||||
|
mutex.lock();
|
||||||
// search in cache
|
// search in cache
|
||||||
qDebug("TemplateCache: trying cached %s",qPrintable(localizedName));
|
qDebug("TemplateCache: trying cached %s",qPrintable(localizedName));
|
||||||
CacheEntry* entry=cache.object(localizedName);
|
CacheEntry* entry=cache.object(localizedName);
|
||||||
if (entry && (cacheTimeout==0 || entry->created>now-cacheTimeout))
|
if (entry && (cacheTimeout==0 || entry->created>now-cacheTimeout))
|
||||||
{
|
{
|
||||||
|
mutex.unlock();
|
||||||
return entry->document;
|
return entry->document;
|
||||||
}
|
}
|
||||||
// search on filesystem
|
// search on filesystem
|
||||||
@ -27,6 +31,7 @@ QString TemplateCache::tryFile(QString localizedName)
|
|||||||
entry->document=TemplateLoader::tryFile(localizedName);
|
entry->document=TemplateLoader::tryFile(localizedName);
|
||||||
// Store in cache even when the file did not exist, to remember that there is no such file
|
// Store in cache even when the file did not exist, to remember that there is no such file
|
||||||
cache.insert(localizedName,entry,entry->document.size());
|
cache.insert(localizedName,entry,entry->document.size());
|
||||||
|
mutex.unlock();
|
||||||
return entry->document;
|
return entry->document;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,8 @@
|
|||||||
#include "templateglobal.h"
|
#include "templateglobal.h"
|
||||||
#include "templateloader.h"
|
#include "templateloader.h"
|
||||||
|
|
||||||
|
namespace stefanfrings {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Caching template loader, reduces the amount of I/O and improves performance
|
Caching template loader, reduces the amount of I/O and improves performance
|
||||||
on remote file systems. The cache has a limited size, it prefers to keep
|
on remote file systems. The cache has a limited size, it prefers to keep
|
||||||
@ -46,10 +48,15 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Constructor.
|
Constructor.
|
||||||
@param settings configurations settings
|
@param settings Configuration settings, usually stored in an INI file. Must not be 0.
|
||||||
|
Settings are read from the current group, so the caller must have called settings->beginGroup().
|
||||||
|
Because the group must not change during runtime, it is recommended to provide a
|
||||||
|
separate QSettings instance that is not used by other parts of the program.
|
||||||
|
The TemplateCache does not take over ownership of the QSettings instance, so the caller
|
||||||
|
should destroy it during shutdown.
|
||||||
@param parent Parent object
|
@param parent Parent object
|
||||||
*/
|
*/
|
||||||
TemplateCache(QSettings* settings, QObject* parent=nullptr);
|
TemplateCache(const QSettings* settings, QObject* parent=nullptr);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@ -58,7 +65,7 @@ protected:
|
|||||||
@param localizedName Name of the template with locale to find
|
@param localizedName Name of the template with locale to find
|
||||||
@return The template document, or empty string if not found
|
@return The template document, or empty string if not found
|
||||||
*/
|
*/
|
||||||
virtual QString tryFile(QString localizedName);
|
virtual QString tryFile(const QString localizedName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -73,6 +80,10 @@ private:
|
|||||||
/** Cache storage */
|
/** Cache storage */
|
||||||
QCache<QString,CacheEntry> cache;
|
QCache<QString,CacheEntry> cache;
|
||||||
|
|
||||||
|
/** Used to synchronize threads */
|
||||||
|
QMutex mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end of namespace
|
||||||
|
|
||||||
#endif // TEMPLATECACHE_H
|
#endif // TEMPLATECACHE_H
|
||||||
|
|||||||
@ -10,7 +10,9 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
|
||||||
TemplateLoader::TemplateLoader(QSettings* settings, QObject* parent)
|
using namespace stefanfrings;
|
||||||
|
|
||||||
|
TemplateLoader::TemplateLoader(const QSettings *settings, QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
templatePath=settings->value("path",".").toString();
|
templatePath=settings->value("path",".").toString();
|
||||||
@ -64,7 +66,6 @@ QString TemplateLoader::tryFile(QString localizedName)
|
|||||||
|
|
||||||
Template TemplateLoader::getTemplate(QString templateName, QString locales)
|
Template TemplateLoader::getTemplate(QString templateName, QString locales)
|
||||||
{
|
{
|
||||||
mutex.lock();
|
|
||||||
QSet<QString> tried; // used to suppress duplicate attempts
|
QSet<QString> tried; // used to suppress duplicate attempts
|
||||||
QStringList locs=locales.split(',',QString::SkipEmptyParts);
|
QStringList locs=locales.split(',',QString::SkipEmptyParts);
|
||||||
|
|
||||||
@ -78,7 +79,6 @@ Template TemplateLoader::getTemplate(QString templateName, QString locales)
|
|||||||
{
|
{
|
||||||
QString document=tryFile(localizedName);
|
QString document=tryFile(localizedName);
|
||||||
if (!document.isEmpty()) {
|
if (!document.isEmpty()) {
|
||||||
mutex.unlock();
|
|
||||||
return Template(document,localizedName);
|
return Template(document,localizedName);
|
||||||
}
|
}
|
||||||
tried.insert(localizedName);
|
tried.insert(localizedName);
|
||||||
@ -95,7 +95,6 @@ Template TemplateLoader::getTemplate(QString templateName, QString locales)
|
|||||||
QString document=tryFile(localizedName);
|
QString document=tryFile(localizedName);
|
||||||
if (!document.isEmpty())
|
if (!document.isEmpty())
|
||||||
{
|
{
|
||||||
mutex.unlock();
|
|
||||||
return Template(document,localizedName);
|
return Template(document,localizedName);
|
||||||
}
|
}
|
||||||
tried.insert(localizedName);
|
tried.insert(localizedName);
|
||||||
@ -106,11 +105,9 @@ Template TemplateLoader::getTemplate(QString templateName, QString locales)
|
|||||||
QString document=tryFile(templateName);
|
QString document=tryFile(templateName);
|
||||||
if (!document.isEmpty())
|
if (!document.isEmpty())
|
||||||
{
|
{
|
||||||
mutex.unlock();
|
|
||||||
return Template(document,templateName);
|
return Template(document,templateName);
|
||||||
}
|
}
|
||||||
|
|
||||||
qCritical("TemplateCache: cannot find template %s",qPrintable(templateName));
|
qCritical("TemplateCache: cannot find template %s",qPrintable(templateName));
|
||||||
mutex.unlock();
|
|
||||||
return Template("",templateName);
|
return Template("",templateName);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,8 @@
|
|||||||
#include "templateglobal.h"
|
#include "templateglobal.h"
|
||||||
#include "template.h"
|
#include "template.h"
|
||||||
|
|
||||||
|
namespace stefanfrings {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Loads localized versions of template files. If the caller requests a file with the
|
Loads localized versions of template files. If the caller requests a file with the
|
||||||
name "index" and the suffix is ".tpl" and the requested locale is "de_DE, de, en-US",
|
name "index" and the suffix is ".tpl" and the requested locale is "de_DE, de, en-US",
|
||||||
@ -20,7 +22,7 @@
|
|||||||
|
|
||||||
- index-de_DE.tpl
|
- index-de_DE.tpl
|
||||||
- index-de.tpl
|
- index-de.tpl
|
||||||
- index-en_US.tpl
|
- index-en_US.tpl
|
||||||
- index-en.tpl
|
- index-en.tpl
|
||||||
- index.tpl
|
- index.tpl
|
||||||
|
|
||||||
@ -45,7 +47,7 @@ public:
|
|||||||
@param settings configurations settings
|
@param settings configurations settings
|
||||||
@param parent parent object
|
@param parent parent object
|
||||||
*/
|
*/
|
||||||
TemplateLoader(QSettings* settings, QObject* parent=nullptr);
|
TemplateLoader(const QSettings* settings, QObject* parent=nullptr);
|
||||||
|
|
||||||
/** Destructor */
|
/** Destructor */
|
||||||
virtual ~TemplateLoader();
|
virtual ~TemplateLoader();
|
||||||
@ -59,7 +61,7 @@ public:
|
|||||||
ignored.
|
ignored.
|
||||||
@return If the template cannot be loaded, an error message is logged and an empty template is returned.
|
@return If the template cannot be loaded, an error message is logged and an empty template is returned.
|
||||||
*/
|
*/
|
||||||
Template getTemplate(QString templateName, QString locales=QString());
|
Template getTemplate(const QString templateName, const QString locales=QString());
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@ -68,7 +70,7 @@ protected:
|
|||||||
@param localizedName Name of the template with locale to find
|
@param localizedName Name of the template with locale to find
|
||||||
@return The template document, or empty string if not found
|
@return The template document, or empty string if not found
|
||||||
*/
|
*/
|
||||||
virtual QString tryFile(QString localizedName);
|
virtual QString tryFile(const QString localizedName);
|
||||||
|
|
||||||
/** Directory where the templates are searched */
|
/** Directory where the templates are searched */
|
||||||
QString templatePath;
|
QString templatePath;
|
||||||
@ -78,9 +80,8 @@ protected:
|
|||||||
|
|
||||||
/** Codec for decoding the files */
|
/** Codec for decoding the files */
|
||||||
QTextCodec* textCodec;
|
QTextCodec* textCodec;
|
||||||
|
|
||||||
/** Used to synchronize threads */
|
|
||||||
QMutex mutex;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end of namespace
|
||||||
|
|
||||||
#endif // TEMPLATELOADER_H
|
#endif // TEMPLATELOADER_H
|
||||||
|
|||||||
Reference in New Issue
Block a user