From 4b590a43888676d7e5724d43a6f41a76b334cc39 Mon Sep 17 00:00:00 2001 From: Philipp Swoboda Date: Wed, 8 Apr 2026 22:22:50 +0200 Subject: [PATCH] Fixes for TirugaDashboard --- src/include/qhttpengine/handler.h | 17 ++-- src/include/qhttpengine/qobjecthandler.h | 115 ++++++----------------- src/src/handler.cpp | 25 ++--- src/src/handler_p.h | 6 +- src/src/qobjecthandler.cpp | 23 ++--- src/src/qobjecthandler_p.h | 22 ++--- src/src/range.cpp | 13 +-- 7 files changed, 82 insertions(+), 139 deletions(-) diff --git a/src/include/qhttpengine/handler.h b/src/include/qhttpengine/handler.h index 9dd3fab..8dd0d0c 100644 --- a/src/include/qhttpengine/handler.h +++ b/src/include/qhttpengine/handler.h @@ -24,11 +24,10 @@ #define QHTTPENGINE_HANDLER_H #include +#include #include "qhttpengine_export.h" -class QRegExp; - namespace QHttpEngine { @@ -49,24 +48,24 @@ class QHTTPENGINE_EXPORT HandlerPrivate; * match. * * To add a redirect, use the addRedirect() method. The first parameter is a - * QRegExp pattern that the request path will be tested against. If it + * QRegularExpression pattern that the request path will be tested against. If it * matches, an HTTP 302 redirect will be written to the socket and the request * closed. For example, to have the root path "/" redirect to "/index.html": * * @code * QHttpEngine::Handler handler; - * handler.addRedirect(QRegExp("^$"), "/index.html"); + * handler.addRedirect(QRegularExpression("^$"), "/index.html"); * @endcode * * To add a sub-handler, use the addSubHandler() method. Again, the first - * parameter is a QRegExp pattern. If the pattern matches, the portion of the + * parameter is a QRegularExpression pattern. If the pattern matches, the portion of the * path that matched the pattern is removed from the path and it is passed to * the sub-handler's route() method. For example, to have a sub-handler * invoked when the path begins with "/api/": * * @code * QHttpEngine::Handler handler, subHandler; - * handler.addSubHandler(QRegExp("^api/"), &subHandler); + * handler.addSubHandler(QRegularExpression("^api/"), &subHandler); * @endcode * * If the request doesn't match any redirect or sub-handler patterns, it is @@ -100,7 +99,7 @@ public: * The destination path may use "%1", "%2", etc. to refer to captured * parts of the pattern. The client will receive an HTTP 302 redirect. */ - void addRedirect(const QRegExp &pattern, const QString &path); + void addRedirect(const QRegularExpression &pattern, const QString &path); /** * @brief Add a handler for a specific pattern @@ -109,7 +108,7 @@ public: * used when the route() method is invoked to determine whether the * request matches any patterns. The order of the list is preserved. */ - void addSubHandler(const QRegExp &pattern, Handler *handler); + void addSubHandler(const QRegularExpression &pattern, Handler *handler); /** * @brief Route an incoming request @@ -137,4 +136,4 @@ private: } -#endif // QHTTPENGINE_HANDLER_H +#endif // QHTTPENGINE_HANDLER_H \ No newline at end of file diff --git a/src/include/qhttpengine/qobjecthandler.h b/src/include/qhttpengine/qobjecthandler.h index 851a8e4..1a10ceb 100644 --- a/src/include/qhttpengine/qobjecthandler.h +++ b/src/include/qhttpengine/qobjecthandler.h @@ -25,6 +25,8 @@ #include +#include + #include "qhttpengine_export.h" namespace QHttpEngine @@ -56,10 +58,7 @@ class QHTTPENGINE_EXPORT QObjectHandlerPrivate; * * QHttpEngine::QObjectHandler handler; * Object object; - * // Old connection syntax * handler.registerMethod("something", &object, SLOT(something(QHttpEngine::Socket*))); - * // New connection syntax - * handler.registerMethod("something", &object, &Object::something); * @endcode * * It is also possible to use this class with a functor, eliminating the need @@ -85,79 +84,39 @@ public: explicit QObjectHandler(QObject *parent = 0); /** - * @brief Register a method - * - * This overload uses the traditional connection syntax with macros. - * - * The readAll parameter determines whether all data must be received by - * the socket before invoking the slot. + * @brief Register a method using slot macro (Qt5/6 compatible) */ void registerMethod(const QString &name, QObject *receiver, const char *method, bool readAll = true); -#ifdef DOXYGEN /** - * @brief Register a method - * - * This overload uses the new connection syntax with member pointers. + * @brief Register a method using member function pointer */ - void registerMethod(const QString &name, QObject *receiver, PointerToMemberFunction method, bool readAll = true); - - /** - * @brief Register a method - * - * This overload uses the new functor syntax (without context). - */ - void registerMethod(const QString &name, Functor functor, bool readAll = true); - - /** - * @brief Register a method - * - * This overload uses the new functor syntax (with context). - */ - void registerMethod(const QString &name, QObject *receiver, Functor functor, bool readAll = true); -#else - template - inline void registerMethod(const QString &name, - typename QtPrivate::FunctionPointer::Object *receiver, - Func1 slot, - bool readAll = true) { - - typedef QtPrivate::FunctionPointer SlotType; - - // Ensure the slot doesn't have too many arguments - Q_STATIC_ASSERT_X(int(SlotType::ArgumentCount) == 1, - "The slot must have exactly one argument."); - - // Ensure the argument is of the correct type - Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible::Value>::value), - "The slot parameters do not match"); - - // Invoke the implementation - registerMethodImpl(name, receiver, new QtPrivate::QSlotObject(slot), readAll); + template + void registerMethod(const QString &name, + typename QtPrivate::FunctionPointer::Object *receiver, + Func slot, + bool readAll = true) { + // Wrap the member function call + registerMethodImpl(name, receiver, [receiver, slot](Socket *socket) { + (receiver->*slot)(socket); + }, readAll); } - template - inline typename std::enable_if::value, void>::type - registerMethod(const QString &name, Func1 slot, bool readAll = true) { - registerMethod(name, Q_NULLPTR, slot, readAll); + /** + * @brief Register a method using functor (Qt6 compatible) + */ + template + void registerMethod(const QString &name, Func slot, bool readAll = true) { + registerMethodImpl(name, Q_NULLPTR, slot, readAll); } - template - inline typename std::enable_if::IsPointerToMemberFunction && -#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) - !std::is_same::value, -#else - !QtPrivate::is_same::value, -#endif - void>::type - registerMethod(const QString &name, QObject *context, Func1 slot, bool readAll = true) { - - // There is an easier way to do this but then the header wouldn't - // compile on non-C++11 compilers - return registerMethod_functor(name, context, slot, &Func1::operator(), readAll); + /** + * @brief Register a method using functor with context + */ + template + void registerMethod(const QString &name, QObject *context, Func slot, bool readAll = true) { + registerMethodImpl(name, context, slot, readAll); } -#endif - protected: @@ -168,25 +127,9 @@ protected: private: - template - inline void registerMethod_functor(const QString &name, QObject *context, Func1 slot, Func1Operator, bool readAll) { - - typedef QtPrivate::FunctionPointer SlotType; - - // Ensure the slot doesn't have too many arguments - Q_STATIC_ASSERT_X(int(SlotType::ArgumentCount) == 1, - "The slot must have exactly one argument."); - - // Ensure the argument is of the correct type - Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible::Value>::value), - "The slot parameters do not match"); - - registerMethodImpl(name, context, - new QtPrivate::QFunctorSlotObject(slot), - readAll); - } - - void registerMethodImpl(const QString &name, QObject *receiver, QtPrivate::QSlotObjectBase *slotObj, bool readAll); + // Store callbacks using std::function for Qt6 compatibility + void registerMethodImpl(const QString &name, QObject *context, + std::function callback, bool readAll); QObjectHandlerPrivate *const d; friend class QObjectHandlerPrivate; @@ -194,4 +137,4 @@ private: } -#endif // QHTTPENGINE_QOBJECTHANDLER_H +#endif // QHTTPENGINE_QOBJECTHANDLER_H \ No newline at end of file diff --git a/src/src/handler.cpp b/src/src/handler.cpp index c281e1f..324b61b 100644 --- a/src/src/handler.cpp +++ b/src/src/handler.cpp @@ -45,12 +45,12 @@ void Handler::addMiddleware(Middleware *middleware) d->middleware.append(middleware); } -void Handler::addRedirect(const QRegExp &pattern, const QString &path) +void Handler::addRedirect(const QRegularExpression &pattern, const QString &path) { d->redirects.append(Redirect(pattern, path)); } -void Handler::addSubHandler(const QRegExp &pattern, Handler *handler) +void Handler::addSubHandler(const QRegularExpression &pattern, Handler *handler) { d->subHandlers.append(SubHandler(pattern, handler)); } @@ -58,18 +58,20 @@ void Handler::addSubHandler(const QRegExp &pattern, Handler *handler) void Handler::route(Socket *socket, const QString &path) { // Run through each of the middleware - foreach (Middleware *middleware, d->middleware) { + for (Middleware *middleware : d->middleware) { if (!middleware->process(socket)) { return; } } // Check each of the redirects for a match - foreach (Redirect redirect, d->redirects) { - if (redirect.first.indexIn(path) != -1) { + for (Redirect &redirect : d->redirects) { + QRegularExpressionMatch match = redirect.first.match(path); + if (match.hasMatch()) { QString newPath = redirect.second; - foreach (QString replacement, redirect.first.capturedTexts().mid(1)) { - newPath = newPath.arg(replacement); + QStringList captured = match.capturedTexts(); + for (int i = 1; i < captured.size(); ++i) { + newPath = newPath.arg(captured.at(i)); } socket->writeRedirect(newPath.toUtf8()); return; @@ -77,9 +79,10 @@ void Handler::route(Socket *socket, const QString &path) } // Check each of the sub-handlers for a match - foreach (SubHandler subHandler, d->subHandlers) { - if (subHandler.first.indexIn(path) != -1) { - subHandler.second->route(socket, path.mid(subHandler.first.matchedLength())); + for (SubHandler &subHandler : d->subHandlers) { + QRegularExpressionMatch match = subHandler.first.match(path); + if (match.hasMatch()) { + subHandler.second->route(socket, path.mid(match.capturedLength())); return; } } @@ -92,4 +95,4 @@ void Handler::process(Socket *socket, const QString &) { // The default response is simply a 404 error socket->writeError(Socket::NotFound); -} +} \ No newline at end of file diff --git a/src/src/handler_p.h b/src/src/handler_p.h index b1d2927..2b39075 100644 --- a/src/src/handler_p.h +++ b/src/src/handler_p.h @@ -26,15 +26,15 @@ #include #include #include -#include +#include #include namespace QHttpEngine { -typedef QPair Redirect; -typedef QPair SubHandler; +typedef QPair Redirect; +typedef QPair SubHandler; class HandlerPrivate : public QObject { diff --git a/src/src/qobjecthandler.cpp b/src/src/qobjecthandler.cpp index fdf3330..8107d65 100644 --- a/src/src/qobjecthandler.cpp +++ b/src/src/qobjecthandler.cpp @@ -48,7 +48,7 @@ void QObjectHandlerPrivate::invokeSlot(Socket *socket, Method m) if (m.oldSlot) { // Obtain the slot index - int index = m.receiver->metaObject()->indexOfSlot(m.slot.method + 1); + int index = m.receiver->metaObject()->indexOfMethod(m.slotMethod + 1); if (index == -1) { socket->writeError(Socket::InternalServerError); return; @@ -64,17 +64,17 @@ void QObjectHandlerPrivate::invokeSlot(Socket *socket, Method m) } // Invoke the method - if (!m.receiver->metaObject()->method(index).invoke( - m.receiver, Q_ARG(Socket*, socket))) { + if (!method.invoke(m.receiver, Q_ARG(Socket*, socket))) { socket->writeError(Socket::InternalServerError); return; } } else { - void *args[] = { - Q_NULLPTR, - &socket - }; - m.slot.slotObj->call(m.receiver, args); + // Call the std::function callback + if (m.callback) { + m.callback(socket); + } else { + socket->writeError(Socket::InternalServerError); + } } } @@ -104,7 +104,8 @@ void QObjectHandler::registerMethod(const QString &name, QObject *receiver, cons d->map.insert(name, QObjectHandlerPrivate::Method(receiver, method, readAll)); } -void QObjectHandler::registerMethodImpl(const QString &name, QObject *receiver, QtPrivate::QSlotObjectBase *slotObj, bool readAll) +void QObjectHandler::registerMethodImpl(const QString &name, QObject *context, + std::function callback, bool readAll) { - d->map.insert(name, QObjectHandlerPrivate::Method(receiver, slotObj, readAll)); -} + d->map.insert(name, QObjectHandlerPrivate::Method(callback, readAll)); +} \ No newline at end of file diff --git a/src/src/qobjecthandler_p.h b/src/src/qobjecthandler_p.h index 190f9ee..2b922ac 100644 --- a/src/src/qobjecthandler_p.h +++ b/src/src/qobjecthandler_p.h @@ -25,6 +25,7 @@ #include #include +#include namespace QHttpEngine { @@ -47,23 +48,18 @@ public: public: Method() {} Method(QObject *receiver, const char *method, bool readAll) - : receiver(receiver), oldSlot(true), slot(method), readAll(readAll) {} - Method(QObject *receiver, QtPrivate::QSlotObjectBase *slotObj, bool readAll) - : receiver(receiver), oldSlot(false), slot(slotObj), readAll(readAll) {} + : receiver(receiver), oldSlot(true), slotMethod(method), readAll(readAll) {} + Method(std::function callback, bool readAll) + : receiver(nullptr), oldSlot(false), callback(callback), readAll(readAll) {} - QObject *receiver; + QObject *receiver = nullptr; bool oldSlot; - union slot{ - slot() {} - slot(const char *method) : method(method) {} - slot(QtPrivate::QSlotObjectBase *slotObj) : slotObj(slotObj) {} - const char *method; - QtPrivate::QSlotObjectBase *slotObj; - } slot; + const char *slotMethod = nullptr; + std::function callback; bool readAll; }; - void invokeSlot(Socket*socket, Method m); + void invokeSlot(Socket *socket, Method m); QMap map; @@ -74,4 +70,4 @@ private: } -#endif // QHTTPENGINE_QOBJECTHANDLER_P_H +#endif // QHTTPENGINE_QOBJECTHANDLER_P_H \ No newline at end of file diff --git a/src/src/range.cpp b/src/src/range.cpp index aa9e29e..f27a39f 100644 --- a/src/src/range.cpp +++ b/src/src/range.cpp @@ -20,7 +20,7 @@ * IN THE SOFTWARE. */ -#include +#include #include @@ -44,13 +44,14 @@ Range::Range() Range::Range(const QString &range, qint64 dataSize) : d(new RangePrivate(this)) { - QRegExp regExp("^(\\d*)-(\\d*)$"); + QRegularExpression regExp("^(\\d*)-(\\d*)$"); int from = 0, to = -1; - if (regExp.indexIn(range.trimmed()) != -1) { - QString fromStr = regExp.cap(1); - QString toStr = regExp.cap(2); + QRegularExpressionMatch match = regExp.match(range.trimmed()); + if (match.hasMatch()) { + QString fromStr = match.captured(1); + QString toStr = match.captured(2); // If both strings are empty - range is invalid. Setting to out of // bounds range and returning. @@ -281,4 +282,4 @@ QString Range::contentRange() const } return QString("%1-%2/%3").arg(fromStr, toStr, sizeStr); -} +} \ No newline at end of file