mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-04 21:27:58 +02:00
Fix QxtFifo and move qxtweb modules in their respective folder
This commit is contained in:
@@ -241,7 +241,7 @@ ENDIF( WIN32 )
|
|||||||
#TODO: support external qxt
|
#TODO: support external qxt
|
||||||
set(QXTWEB_FOUND TRUE)
|
set(QXTWEB_FOUND TRUE)
|
||||||
set(QXTWEB_LIBRARIES qxtweb-standalone)
|
set(QXTWEB_LIBRARIES qxtweb-standalone)
|
||||||
set(QXTWEB_INCLUDE_DIRS ${THIRDPARTY_DIR}/qxt/qxtweb-standalone/qxtweb ${CMAKE_CURRENT_BINARY_DIR})
|
set(QXTWEB_INCLUDE_DIRS ${THIRDPARTY_DIR}/qxt/qxtweb-standalone/web ${THIRDPARTY_DIR}/qxt/qxtweb-standalone/network ${THIRDPARTY_DIR}/qxt/qxtweb-standalone/core ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
### libportfwd
|
### libportfwd
|
||||||
set(LIBPORTFWD_INCLUDE_DIR ${THIRDPARTY_DIR}/libportfwd/include)
|
set(LIBPORTFWD_INCLUDE_DIR ${THIRDPARTY_DIR}/libportfwd/include)
|
||||||
|
31
thirdparty/qxt/qxtweb-standalone/CMakeLists.txt
vendored
31
thirdparty/qxt/qxtweb-standalone/CMakeLists.txt
vendored
@@ -7,16 +7,18 @@ ENDIF( ${CMAKE_VERSION} VERSION_GREATER 2.8.3 )
|
|||||||
|
|
||||||
setup_qt()
|
setup_qt()
|
||||||
|
|
||||||
SET(qxtweb "qxtweb")
|
SET( qxtcore "core" )
|
||||||
|
SET( qxtnet "network" )
|
||||||
|
SET( qxtweb "web" )
|
||||||
|
|
||||||
ADD_DEFINITIONS(-Wall -O2 -DNDEBUG)
|
ADD_DEFINITIONS( -Wall -O2 -DNDEBUG )
|
||||||
IF(NOT WIN32)
|
IF( NOT WIN32 )
|
||||||
ADD_DEFINITIONS(-fPIC)
|
ADD_DEFINITIONS( -fPIC )
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ADD_DEFINITIONS( -DBUILD_QXT_CORE -DBUILD_QXT_WEB )
|
ADD_DEFINITIONS( -DBUILD_QXT_CORE -DBUILD_QXT_WEB )
|
||||||
|
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES( ${qxtweb} )
|
INCLUDE_DIRECTORIES( ${qxtweb} ${qxtcore} ${qxtnet} )
|
||||||
|
|
||||||
macro(create_qxtweb_fancy_header simpleHeader fancyHeader)
|
macro(create_qxtweb_fancy_header simpleHeader fancyHeader)
|
||||||
file(WRITE ${CMAKE_BINARY_DIR}/QxtWeb/${fancyHeader} "#include \"${simpleHeader}\"" )
|
file(WRITE ${CMAKE_BINARY_DIR}/QxtWeb/${fancyHeader} "#include \"${simpleHeader}\"" )
|
||||||
@@ -41,24 +43,23 @@ SET( sources
|
|||||||
${qxtweb}/qxtwebcontent.cpp
|
${qxtweb}/qxtwebcontent.cpp
|
||||||
${qxtweb}/qxtwebevent.cpp
|
${qxtweb}/qxtwebevent.cpp
|
||||||
${qxtweb}/qxtwebservicedirectory.cpp
|
${qxtweb}/qxtwebservicedirectory.cpp
|
||||||
${qxtweb}/qxtwebslotservice.cpp
|
|
||||||
${qxtweb}/qxtwebcgiservice.cpp
|
|
||||||
${qxtweb}/qhttpheader.cpp
|
${qxtweb}/qhttpheader.cpp
|
||||||
|
${qxtweb}/qxtwebslotservice.cpp
|
||||||
|
|
||||||
# Ripped bits of QxtCore:
|
# Ripped bits of QxtCore:
|
||||||
${qxtweb}/qxtmetaobject.cpp
|
${qxtcore}/qxtmetaobject.cpp
|
||||||
${qxtweb}/qxtnull.cpp
|
${qxtcore}/qxtnull.cpp
|
||||||
${qxtweb}/qxtfifo.cpp
|
${qxtcore}/qxtfifo.cpp
|
||||||
|
|
||||||
# QxtNetwork
|
# QxtNetwork
|
||||||
${qxtweb}/qxtsslserver.cpp
|
${qxtnet}/qxtsslserver.cpp
|
||||||
|
|
||||||
# automoc hack
|
# automoc hack
|
||||||
${qxtweb}/qxtboundfunction.h
|
${qxtcore}/qxtboundfunction.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
ADD_LIBRARY(qxtweb-standalone STATIC
|
ADD_LIBRARY( qxtweb-standalone STATIC
|
||||||
${mocstuff}
|
${mocstuff}
|
||||||
${headers}
|
${headers}
|
||||||
${sources}
|
${sources}
|
||||||
@@ -69,6 +70,6 @@ target_link_libraries( qxtweb-standalone
|
|||||||
${QT_LIBRARIES}
|
${QT_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
qt5_use_modules(qxtweb-standalone Network)
|
qt5_use_modules( qxtweb-standalone Network )
|
||||||
|
|
||||||
set_target_properties(qxtweb-standalone PROPERTIES AUTOMOC TRUE)
|
set_target_properties( qxtweb-standalone PROPERTIES AUTOMOC TRUE )
|
||||||
|
@@ -137,17 +137,14 @@ QxtFifo::QxtFifo(const QByteArray &prime, QObject *parent) : QIODevice(parent)
|
|||||||
QXT_INIT_PRIVATE(QxtFifo);
|
QXT_INIT_PRIVATE(QxtFifo);
|
||||||
setOpenMode(QIODevice::ReadWrite);
|
setOpenMode(QIODevice::ReadWrite);
|
||||||
// Since we're being constructed, access to the internals is safe
|
// Since we're being constructed, access to the internals is safe
|
||||||
|
QxtFifoNode* node;
|
||||||
QxtFifoNode *head;
|
|
||||||
int available;
|
|
||||||
#if QT_VERSION >= 0x50000
|
#if QT_VERSION >= 0x50000
|
||||||
head = qxt_d().head.load();
|
node = qxt_d().head.load();
|
||||||
available = qxt_d().available.load();
|
|
||||||
#else
|
#else
|
||||||
head = qxt_d().head;
|
node = qxt_d().head;
|
||||||
available = qxt_d().available;
|
|
||||||
#endif
|
#endif
|
||||||
|
node->content = prime;
|
||||||
|
qxt_d().available.QXT_ADD( prime.size() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
@@ -51,8 +51,6 @@
|
|||||||
|
|
||||||
#define QXT_DLLEXPORT DO_NOT_USE_THIS_ANYMORE
|
#define QXT_DLLEXPORT DO_NOT_USE_THIS_ANYMORE
|
||||||
|
|
||||||
#define QXT_STATIC
|
|
||||||
|
|
||||||
#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
|
#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
|
||||||
# if defined(BUILD_QXT_CORE)
|
# if defined(BUILD_QXT_CORE)
|
||||||
# define QXT_CORE_EXPORT Q_DECL_EXPORT
|
# define QXT_CORE_EXPORT Q_DECL_EXPORT
|
@@ -1,27 +1,33 @@
|
|||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
** Copyright (c) 2006 - 2011, the LibQxt project.
|
||||||
** Copyright (C) Qxt Foundation. Some rights reserved.
|
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
||||||
**
|
** All rights reserved.
|
||||||
** This file is part of the QxtCore module of the Qxt library.
|
**
|
||||||
**
|
** Redistribution and use in source and binary forms, with or without
|
||||||
** This library is free software; you can redistribute it and/or modify it
|
** modification, are permitted provided that the following conditions are met:
|
||||||
** under the terms of the Common Public License, version 1.0, as published
|
** * Redistributions of source code must retain the above copyright
|
||||||
** by IBM, and/or under the terms of the GNU Lesser General Public License,
|
** notice, this list of conditions and the following disclaimer.
|
||||||
** version 2.1, as published by the Free Software Foundation.
|
** * Redistributions in binary form must reproduce the above copyright
|
||||||
**
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
|
** documentation and/or other materials provided with the distribution.
|
||||||
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
** * Neither the name of the LibQxt project nor the
|
||||||
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
|
** names of its contributors may be used to endorse or promote products
|
||||||
** FITNESS FOR A PARTICULAR PURPOSE.
|
** derived from this software without specific prior written permission.
|
||||||
**
|
**
|
||||||
** You should have received a copy of the CPL and the LGPL along with this
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
|
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
** included with the source distribution for more information.
|
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
** If you did not receive a copy of the licenses, contact the Qxt Foundation.
|
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
**
|
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
** <http://libqxt.org> <foundation@libqxt.org>
|
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
**
|
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
****************************************************************************/
|
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**
|
||||||
|
** <http://libqxt.org> <foundation@libqxt.org>
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
#ifndef QXTMETATYPE_H
|
#ifndef QXTMETATYPE_H
|
||||||
#define QXTMETATYPE_H
|
#define QXTMETATYPE_H
|
||||||
@@ -32,13 +38,19 @@
|
|||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
#include <qxtglobal.h>
|
#include <qxtglobal.h>
|
||||||
|
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||||
|
#define qxtcreate create
|
||||||
|
#else
|
||||||
|
#define qxtcreate construct
|
||||||
|
#endif
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class /*QXT_CORE_EXPORT*/ QxtMetaType
|
class /*QXT_CORE_EXPORT*/ QxtMetaType
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static inline T* construct(const T* copy = 0)
|
static inline T* construct(const T* copy = 0)
|
||||||
{
|
{
|
||||||
return QMetaType::construct(qMetaTypeId<T>(), reinterpret_cast<const void*>(copy));
|
return QMetaType::qxtcreate(qMetaTypeId<T>(), reinterpret_cast<const void*>(copy));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void destroy(T* data)
|
static inline void destroy(T* data)
|
||||||
@@ -111,11 +123,7 @@ public:
|
|||||||
|
|
||||||
inline void* qxtConstructByName(const char* typeName, const void* copy = 0)
|
inline void* qxtConstructByName(const char* typeName, const void* copy = 0)
|
||||||
{
|
{
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
|
return QMetaType::qxtcreate(QMetaType::type(typeName), copy);
|
||||||
return QMetaType::create(QMetaType::type(typeName), copy);
|
|
||||||
#else
|
|
||||||
return QMetaType::construct(QMetaType::type(typeName), copy);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void qxtDestroyByName(const char* typeName, void* data)
|
inline void qxtDestroyByName(const char* typeName, void* data)
|
@@ -39,7 +39,7 @@
|
|||||||
#include <QSslSocket>
|
#include <QSslSocket>
|
||||||
|
|
||||||
class QxtSslServerPrivate;
|
class QxtSslServerPrivate;
|
||||||
class QxtSslServer : public QTcpServer
|
class QXT_NETWORK_EXPORT QxtSslServer : public QTcpServer
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
@@ -1,2 +0,0 @@
|
|||||||
#include "qxtabstracthttpconnector.h"
|
|
||||||
|
|
@@ -1,2 +0,0 @@
|
|||||||
#include "qxtabstractwebservice.h"
|
|
||||||
|
|
@@ -1,2 +0,0 @@
|
|||||||
#include "qxtabstractwebsessionmanager.h"
|
|
||||||
|
|
@@ -1,2 +0,0 @@
|
|||||||
#include "qxthtmltemplate.h"
|
|
||||||
|
|
@@ -1 +0,0 @@
|
|||||||
#include "qxtabstracthttpconnector.h"
|
|
@@ -1,2 +0,0 @@
|
|||||||
#include "qxthttpsessionmanager.h"
|
|
||||||
|
|
@@ -1,2 +0,0 @@
|
|||||||
#include "qxtmail.h"
|
|
||||||
|
|
@@ -1 +0,0 @@
|
|||||||
#include "qxtabstracthttpconnector.h"
|
|
@@ -1,2 +0,0 @@
|
|||||||
#include "qxtsendmail.h"
|
|
||||||
|
|
@@ -1 +0,0 @@
|
|||||||
#include "qxtweb.h"
|
|
@@ -1 +0,0 @@
|
|||||||
#include "qxtwebcgiservice.h"
|
|
@@ -1,2 +0,0 @@
|
|||||||
#include "qxtwebcontent.h"
|
|
||||||
|
|
@@ -1,2 +0,0 @@
|
|||||||
#include "qxtwebevent.h"
|
|
||||||
|
|
@@ -1,2 +0,0 @@
|
|||||||
#include "qxtwebevent.h"
|
|
||||||
|
|
@@ -1 +0,0 @@
|
|||||||
#include "qxtwebevent.h"
|
|
@@ -1,2 +0,0 @@
|
|||||||
#include "qxtwebevent.h"
|
|
||||||
|
|
@@ -1,2 +0,0 @@
|
|||||||
#include "qxtwebevent.h"
|
|
||||||
|
|
@@ -1 +0,0 @@
|
|||||||
#include "qxtwebevent.h"
|
|
@@ -1,2 +0,0 @@
|
|||||||
#include "qxtwebevent.h"
|
|
||||||
|
|
@@ -1,2 +0,0 @@
|
|||||||
#include "qxtwebservicedirectory.h"
|
|
||||||
|
|
@@ -1,2 +0,0 @@
|
|||||||
#include "qxtwebslotservice.h"
|
|
||||||
|
|
@@ -1 +0,0 @@
|
|||||||
#include "qxtwebevent.h"
|
|
@@ -1,251 +0,0 @@
|
|||||||
|
|
||||||
/****************************************************************************
|
|
||||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
|
||||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
|
||||||
** All rights reserved.
|
|
||||||
**
|
|
||||||
** Redistribution and use in source and binary forms, with or without
|
|
||||||
** modification, are permitted provided that the following conditions are met:
|
|
||||||
** * Redistributions of source code must retain the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer.
|
|
||||||
** * Redistributions in binary form must reproduce the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer in the
|
|
||||||
** documentation and/or other materials provided with the distribution.
|
|
||||||
** * Neither the name of the LibQxt project nor the
|
|
||||||
** names of its contributors may be used to endorse or promote products
|
|
||||||
** derived from this software without specific prior written permission.
|
|
||||||
**
|
|
||||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
|
||||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
**
|
|
||||||
** <http://libqxt.org> <foundation@libqxt.org>
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#include "qxtglobal.h"
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\headerfile <QxtGlobal>
|
|
||||||
\title Global Qxt Declarations
|
|
||||||
\inmodule QxtCore
|
|
||||||
|
|
||||||
\brief The <QxtGlobal> header provides basic declarations and
|
|
||||||
is included by all other Qxt headers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\macro QXT_VERSION
|
|
||||||
\relates <QxtGlobal>
|
|
||||||
|
|
||||||
This macro expands a numeric value of the form 0xMMNNPP (MM =
|
|
||||||
major, NN = minor, PP = patch) that specifies Qxt's version
|
|
||||||
number. For example, if you compile your application against Qxt
|
|
||||||
0.4.0, the QXT_VERSION macro will expand to 0x000400.
|
|
||||||
|
|
||||||
You can use QXT_VERSION to use the latest Qt features where
|
|
||||||
available. For example:
|
|
||||||
\code
|
|
||||||
#if QXT_VERSION >= 0x000400
|
|
||||||
qxtTabWidget->setTabMovementMode(QxtTabWidget::InPlaceMovement);
|
|
||||||
#endif
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
\sa QXT_VERSION_STR, qxtVersion()
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\macro QXT_VERSION_STR
|
|
||||||
\relates <QxtGlobal>
|
|
||||||
|
|
||||||
This macro expands to a string that specifies Qxt's version number
|
|
||||||
(for example, "0.4.0"). This is the version against which the
|
|
||||||
application is compiled.
|
|
||||||
|
|
||||||
\sa qxtVersion(), QXT_VERSION
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\relates <QxtGlobal>
|
|
||||||
|
|
||||||
Returns the version number of Qxt at run-time as a string (for
|
|
||||||
example, "0.4.0"). This may be a different version than the
|
|
||||||
version the application was compiled against.
|
|
||||||
|
|
||||||
\sa QXT_VERSION_STR
|
|
||||||
*/
|
|
||||||
const char * qxtVersion()
|
|
||||||
{
|
|
||||||
return QXT_VERSION_STR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\headerfile <QxtPimpl>
|
|
||||||
\title The Qxt private implementation
|
|
||||||
\inmodule QxtCore
|
|
||||||
|
|
||||||
\brief The <QxtPimpl> header provides tools for hiding
|
|
||||||
details of a class.
|
|
||||||
|
|
||||||
Application code generally doesn't have to be concerned about hiding its
|
|
||||||
implementation details, but when writing library code it is important to
|
|
||||||
maintain a constant interface, both source and binary. Maintaining a constant
|
|
||||||
source interface is easy enough, but keeping the binary interface constant
|
|
||||||
means moving implementation details into a private class. The PIMPL, or
|
|
||||||
d-pointer, idiom is a common method of implementing this separation. QxtPimpl
|
|
||||||
offers a convenient way to connect the public and private sides of your class.
|
|
||||||
|
|
||||||
\section1 Getting Started
|
|
||||||
Before you declare the public class, you need to make a forward declaration
|
|
||||||
of the private class. The private class must have the same name as the public
|
|
||||||
class, followed by the word Private. For example, a class named MyTest would
|
|
||||||
declare the private class with:
|
|
||||||
\code
|
|
||||||
class MyTestPrivate;
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
\section1 The Public Class
|
|
||||||
Generally, you shouldn't keep any data members in the public class without a
|
|
||||||
good reason. Functions that are part of the public interface should be declared
|
|
||||||
in the public class, and functions that need to be available to subclasses (for
|
|
||||||
calling or overriding) should be in the protected section of the public class.
|
|
||||||
To connect the private class to the public class, include the
|
|
||||||
QXT_DECLARE_PRIVATE macro in the private section of the public class. In the
|
|
||||||
example above, the private class is connected as follows:
|
|
||||||
\code
|
|
||||||
private:
|
|
||||||
QXT_DECLARE_PRIVATE(MyTest)
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
Additionally, you must include the QXT_INIT_PRIVATE macro in the public class's
|
|
||||||
constructor. Continuing with the MyTest example, your constructor might look
|
|
||||||
like this:
|
|
||||||
\code
|
|
||||||
MyTest::MyTest() {
|
|
||||||
// initialization
|
|
||||||
QXT_INIT_PRIVATE(MyTest);
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
\section1 The Private Class
|
|
||||||
As mentioned above, data members should usually be kept in the private class.
|
|
||||||
This allows the memory layout of the private class to change without breaking
|
|
||||||
binary compatibility for the public class. Functions that exist only as
|
|
||||||
implementation details, or functions that need access to private data members,
|
|
||||||
should be implemented here.
|
|
||||||
|
|
||||||
To define the private class, inherit from the template QxtPrivate class, and
|
|
||||||
include the QXT_DECLARE_PUBLIC macro in its public section. The template
|
|
||||||
parameter should be the name of the public class. For example:
|
|
||||||
\code
|
|
||||||
class MyTestPrivate : public QxtPrivate<MyTest> {
|
|
||||||
public:
|
|
||||||
MyTestPrivate();
|
|
||||||
QXT_DECLARE_PUBLIC(MyTest)
|
|
||||||
};
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
\section1 Accessing Private Members
|
|
||||||
Use the qxt_d() function (actually a function-like object) from functions in
|
|
||||||
the public class to access the private class. Similarly, functions in the
|
|
||||||
private class can invoke functions in the public class by using the qxt_p()
|
|
||||||
function (this one's actually a function).
|
|
||||||
|
|
||||||
For example, assume that MyTest has methods named getFoobar and doBaz(),
|
|
||||||
and MyTestPrivate has a member named foobar and a method named doQuux().
|
|
||||||
The code might resemble this example:
|
|
||||||
\code
|
|
||||||
int MyTest::getFoobar() {
|
|
||||||
return qxt_d().foobar;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyTestPrivate::doQuux() {
|
|
||||||
qxt_p().doBaz(foobar);
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \macro QXT_DECLARE_PRIVATE(PUB)
|
|
||||||
* \relates <QxtPimpl>
|
|
||||||
* Declares that a public class has a related private class.
|
|
||||||
*
|
|
||||||
* This shuold be put in the private section of the public class. The
|
|
||||||
* parameter \a PUB must be the name of the public class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \macro QXT_DECLARE_PUBLIC(PUB)
|
|
||||||
* \relates <QxtPimpl>
|
|
||||||
* Declares that a private class has a related public class named \a PUB.
|
|
||||||
*
|
|
||||||
* This may be put anywhere in the declaration of the private class. The parameter is the name of the public class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \macro QXT_INIT_PRIVATE(PUB)
|
|
||||||
* \relates <QxtPimpl>
|
|
||||||
* Initializes resources owned by the private class.
|
|
||||||
*
|
|
||||||
* This should be called from the public class's constructor,
|
|
||||||
* before qxt_d() is used for the first time. The parameter \a PUB must be
|
|
||||||
* the name of the public class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \macro QXT_D(PUB)
|
|
||||||
* \relates <QxtPimpl>
|
|
||||||
* Returns a reference in the current scope named "d" to the private class
|
|
||||||
* associated with the public class \a PUB.
|
|
||||||
*
|
|
||||||
* This function is only available in a class using QXT_DECLARE_PRIVATE().
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \macro QXT_P(PUB)
|
|
||||||
* \relates <QxtPimpl>
|
|
||||||
* Creates a reference in the current scope named "q" to the public class
|
|
||||||
* named \a PUB.
|
|
||||||
*
|
|
||||||
* This macro only works in a class using QXT_DECLARE_PUBLIC().
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \fn QxtPrivate<PUB>& PUB::qxt_d()
|
|
||||||
* \relates <QxtPimpl>
|
|
||||||
* Returns a reference to the private class.
|
|
||||||
*
|
|
||||||
* This function is only available in a class using \a QXT_DECLARE_PRIVATE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \fn const QxtPrivate<PUB>& PUB::qxt_d() const
|
|
||||||
* \relates <QxtPimpl>
|
|
||||||
* Returns a const reference to the private class.
|
|
||||||
*
|
|
||||||
* This function is only available in a class using \a QXT_DECLARE_PRIVATE.
|
|
||||||
* This overload will be automatically used in const functions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \fn PUB& QxtPrivate::qxt_p()
|
|
||||||
* \relates <QxtPimpl>
|
|
||||||
* Returns a reference to the public class.
|
|
||||||
*
|
|
||||||
* This function is only available in a class using QXT_DECLARE_PUBLIC().
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \fn const PUB& QxtPrivate::qxt_p() const
|
|
||||||
* \relates <QxtPimpl>
|
|
||||||
* Returns a const reference to the public class.
|
|
||||||
*
|
|
||||||
* This function is only available in a class using QXT_DECLARE_PUBLIC().
|
|
||||||
* This overload will be automatically used in const functions.
|
|
||||||
*/
|
|
46
thirdparty/qxt/qxtweb-standalone/qxtweb/qxtweb.h
vendored
46
thirdparty/qxt/qxtweb-standalone/qxtweb/qxtweb.h
vendored
@@ -1,46 +0,0 @@
|
|||||||
#ifndef QXTWEB_H_INCLUDED
|
|
||||||
/****************************************************************************
|
|
||||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
|
||||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
|
||||||
** All rights reserved.
|
|
||||||
**
|
|
||||||
** Redistribution and use in source and binary forms, with or without
|
|
||||||
** modification, are permitted provided that the following conditions are met:
|
|
||||||
** * Redistributions of source code must retain the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer.
|
|
||||||
** * Redistributions in binary form must reproduce the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer in the
|
|
||||||
** documentation and/or other materials provided with the distribution.
|
|
||||||
** * Neither the name of the LibQxt project nor the
|
|
||||||
** names of its contributors may be used to endorse or promote products
|
|
||||||
** derived from this software without specific prior written permission.
|
|
||||||
**
|
|
||||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
|
||||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
**
|
|
||||||
** <http://libqxt.org> <foundation@libqxt.org>
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#define QXTWEB_H_INCLUDED
|
|
||||||
|
|
||||||
#include "qxtabstracthttpconnector.h"
|
|
||||||
#include "qxtabstractwebservice.h"
|
|
||||||
#include "qxtabstractwebsessionmanager.h"
|
|
||||||
#include "qxthtmltemplate.h"
|
|
||||||
#include "qxthttpsessionmanager.h"
|
|
||||||
#include "qxtwebcgiservice.h"
|
|
||||||
#include "qxtwebcontent.h"
|
|
||||||
#include "qxtwebevent.h"
|
|
||||||
#include "qxtwebjsonrpcservice.h"
|
|
||||||
#include "qxtwebservicedirectory.h"
|
|
||||||
#include "qxtwebslotservice.h"
|
|
||||||
|
|
||||||
#endif // QXTWEB_H_INCLUDED
|
|
@@ -1,445 +0,0 @@
|
|||||||
|
|
||||||
/****************************************************************************
|
|
||||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
|
||||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
|
||||||
** All rights reserved.
|
|
||||||
**
|
|
||||||
** Redistribution and use in source and binary forms, with or without
|
|
||||||
** modification, are permitted provided that the following conditions are met:
|
|
||||||
** * Redistributions of source code must retain the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer.
|
|
||||||
** * Redistributions in binary form must reproduce the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer in the
|
|
||||||
** documentation and/or other materials provided with the distribution.
|
|
||||||
** * Neither the name of the LibQxt project nor the
|
|
||||||
** names of its contributors may be used to endorse or promote products
|
|
||||||
** derived from this software without specific prior written permission.
|
|
||||||
**
|
|
||||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
|
||||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
**
|
|
||||||
** <http://libqxt.org> <foundation@libqxt.org>
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\class QxtWebCgiService
|
|
||||||
|
|
||||||
\inmodule QxtWeb
|
|
||||||
|
|
||||||
\brief The QxtWebCgiService class provides a CGI/1.1 gateway for QxtWeb
|
|
||||||
|
|
||||||
TODO: write docs
|
|
||||||
TODO: implement timeout
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "qxtwebcgiservice.h"
|
|
||||||
#include "qxtwebcgiservice_p.h"
|
|
||||||
#include "qxtwebevent.h"
|
|
||||||
#include "qxtwebcontent.h"
|
|
||||||
#include <QMap>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QProcess>
|
|
||||||
#include <QtDebug>
|
|
||||||
|
|
||||||
QxtCgiRequestInfo::QxtCgiRequestInfo() : sessionID(0), requestID(0), eventSent(false), terminateSent(false) {}
|
|
||||||
QxtCgiRequestInfo::QxtCgiRequestInfo(QxtWebRequestEvent* req) : sessionID(req->sessionID), requestID(req->requestID), eventSent(false), terminateSent(false) {}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Constructs a QxtWebCgiService object with the specified session \a manager and \a parent.
|
|
||||||
* This service will invoke the specified \a binary to handle incoming requests.
|
|
||||||
*
|
|
||||||
* Often, the session manager will also be the parent, but this is not a requirement.
|
|
||||||
*/
|
|
||||||
QxtWebCgiService::QxtWebCgiService(const QString& binary, QxtAbstractWebSessionManager* manager, QObject* parent) : QxtAbstractWebService(manager, parent)
|
|
||||||
{
|
|
||||||
QXT_INIT_PRIVATE(QxtWebCgiService);
|
|
||||||
qxt_d().binary = binary;
|
|
||||||
QObject::connect(&qxt_d().timeoutMapper, SIGNAL(mapped(QObject*)), &qxt_d(), SLOT(terminateProcess(QObject*)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the path to the CGI script that will be executed to handle requests.
|
|
||||||
*
|
|
||||||
* \sa setBinary()
|
|
||||||
*/
|
|
||||||
QString QxtWebCgiService::binary() const
|
|
||||||
{
|
|
||||||
return qxt_d().binary;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets the path to the CGI script \a bin that will be executed to handle requests.
|
|
||||||
*
|
|
||||||
* \sa binary()
|
|
||||||
*/
|
|
||||||
void QxtWebCgiService::setBinary(const QString& bin)
|
|
||||||
{
|
|
||||||
if (!QFile::exists(bin) || !(QFile::permissions(bin) & (QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther)))
|
|
||||||
{
|
|
||||||
qWarning() << "QxtWebCgiService::setBinary: " + bin + " does not appear to be executable.";
|
|
||||||
}
|
|
||||||
qxt_d().binary = bin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the maximum time a CGI script may execute, in milliseconds.
|
|
||||||
*
|
|
||||||
* The default value is 0, which indicates that CGI scripts will not be terminated
|
|
||||||
* due to long running times.
|
|
||||||
*
|
|
||||||
* \sa setTimeout()
|
|
||||||
*/
|
|
||||||
int QxtWebCgiService::timeout() const
|
|
||||||
{
|
|
||||||
return qxt_d().timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets the maximum \a time a CGI script may execute, in milliseconds.
|
|
||||||
*
|
|
||||||
* The timer is started when the script is launched. After the timeout elapses once,
|
|
||||||
* the script will be asked to stop, as QProcess::terminate(). (That is, the script
|
|
||||||
* will receive WM_CLOSE on Windows or SIGTERM on UNIX.) If the process has still
|
|
||||||
* failed to terminate after another timeout, it will be forcibly terminated, as
|
|
||||||
* QProcess::kill(). (That is, the script will receive TerminateProcess on Windows
|
|
||||||
* or SIGKILL on UNIX.)
|
|
||||||
*
|
|
||||||
* Set the timeout to 0 to disable this behavior; scripts will not be terminated
|
|
||||||
* due to excessive run time. This is the default behavior.
|
|
||||||
*
|
|
||||||
* CAUTION: Keep in mind that the timeout applies to the real running time of the
|
|
||||||
* script, not processor time used. A script that initiates a lengthy download
|
|
||||||
* may be interrupted while transferring data to the web browser. To avoid this
|
|
||||||
* behavior, see the timeoutOverride property to allow the script to request
|
|
||||||
* an extended timeout, or use a different QxtAbstractWebService object for
|
|
||||||
* serving streaming content or large files.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* \sa timeout(), timeoutOverride(), setTimeoutOverride(), QProcess::terminate(), QProcess::kill()
|
|
||||||
*/
|
|
||||||
void QxtWebCgiService::setTimeout(int time)
|
|
||||||
{
|
|
||||||
qxt_d().timeout = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns whether or not to allow scripts to override the timeout.
|
|
||||||
*
|
|
||||||
* \sa setTimeoutOverride(), setTimeout()
|
|
||||||
*/
|
|
||||||
bool QxtWebCgiService::timeoutOverride() const
|
|
||||||
{
|
|
||||||
return qxt_d().timeoutOverride;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets whether or not to allow scripts to override the timeout.
|
|
||||||
* Scripts are allowed to override if \a enable is \c true.
|
|
||||||
*
|
|
||||||
* As an extension to the CGI/1.1 gateway specification, a CGI script may
|
|
||||||
* output a "X-QxtWeb-Timeout" header to change the termination timeout
|
|
||||||
* on a per-script basis. Only enable this option if you trust the scripts
|
|
||||||
* being executed.
|
|
||||||
*
|
|
||||||
* \sa timeoutOverride(), setTimeout()
|
|
||||||
*/
|
|
||||||
void QxtWebCgiService::setTimeoutOverride(bool enable)
|
|
||||||
{
|
|
||||||
qxt_d().timeoutOverride = enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \reimp
|
|
||||||
*/
|
|
||||||
void QxtWebCgiService::pageRequestedEvent(QxtWebRequestEvent* event)
|
|
||||||
{
|
|
||||||
// Create the process object and initialize connections
|
|
||||||
QProcess* process = new QProcess(this);
|
|
||||||
qxt_d().requests[process] = QxtCgiRequestInfo(event);
|
|
||||||
qxt_d().processes[event->content] = process;
|
|
||||||
QxtCgiRequestInfo& requestInfo = qxt_d().requests[process];
|
|
||||||
QObject::connect(process, SIGNAL(readyRead()), &qxt_d(), SLOT(processReadyRead()));
|
|
||||||
QObject::connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), &qxt_d(), SLOT(processFinished()));
|
|
||||||
QObject::connect(process, SIGNAL(error(QProcess::ProcessError)), &qxt_d(), SLOT(processFinished()));
|
|
||||||
requestInfo.timeout = new QTimer(process);
|
|
||||||
qxt_d().timeoutMapper.setMapping(requestInfo.timeout, process);
|
|
||||||
QObject::connect(requestInfo.timeout, SIGNAL(timeout()), &qxt_d().timeoutMapper, SLOT(map()));
|
|
||||||
|
|
||||||
// Initialize the system environment
|
|
||||||
QStringList s_env = process->systemEnvironment();
|
|
||||||
QMap<QString, QString> env;
|
|
||||||
foreach(const QString& entry, s_env)
|
|
||||||
{
|
|
||||||
int pos = entry.indexOf('=');
|
|
||||||
env[entry.left(pos)] = entry.mid(pos + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Populate CGI/1.1 environment variables
|
|
||||||
env["SERVER_SOFTWARE"] = QString("QxtWeb/" QXT_VERSION_STR);
|
|
||||||
env["SERVER_NAME"] = event->url.host();
|
|
||||||
env["GATEWAY_INTERFACE"] = "CGI/1.1";
|
|
||||||
if (event->headers.contains("X-Request-Protocol"))
|
|
||||||
env["SERVER_PROTOCOL"] = event->headers.value("X-Request-Protocol");
|
|
||||||
else
|
|
||||||
env.remove("SERVER_PROTOCOL");
|
|
||||||
if (event->url.port() != -1)
|
|
||||||
env["SERVER_PORT"] = QString::number(event->url.port());
|
|
||||||
else
|
|
||||||
env.remove("SERVER_PORT");
|
|
||||||
env["REQUEST_METHOD"] = event->method;
|
|
||||||
env["PATH_INFO"] = event->url.path();
|
|
||||||
env["PATH_TRANSLATED"] = event->url.path(); // CGI/1.1 says we should resolve this, but we have no logical interpretation
|
|
||||||
env["SCRIPT_NAME"] = event->originalUrl.path().remove(QRegExp(QRegExp::escape(event->url.path()) + '$'));
|
|
||||||
env["SCRIPT_FILENAME"] = qxt_d().binary; // CGI/1.1 doesn't define this but PHP demands it
|
|
||||||
env.remove("REMOTE_HOST");
|
|
||||||
env["REMOTE_ADDR"] = event->remoteAddress.toString();
|
|
||||||
// TODO: If we ever support HTTP authentication, we should use these
|
|
||||||
env.remove("AUTH_TYPE");
|
|
||||||
env.remove("REMOTE_USER");
|
|
||||||
env.remove("REMOTE_IDENT");
|
|
||||||
if (event->contentType.isEmpty())
|
|
||||||
{
|
|
||||||
env.remove("CONTENT_TYPE");
|
|
||||||
env.remove("CONTENT_LENGTH");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
env["CONTENT_TYPE"] = event->contentType;
|
|
||||||
env["CONTENT_LENGTH"] = QString::number(event->content->unreadBytes());
|
|
||||||
}
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
|
|
||||||
env["QUERY_STRING"] = event->url.query();
|
|
||||||
#else
|
|
||||||
env["QUERY_STRING"] = event->url.encodedQuery();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Populate HTTP header environment variables
|
|
||||||
QMultiHash<QString, QString>::const_iterator iter = event->headers.constBegin();
|
|
||||||
while (iter != event->headers.constEnd())
|
|
||||||
{
|
|
||||||
QString key = "HTTP_" + iter.key().toUpper().replace('-', '_');
|
|
||||||
if (key != "HTTP_CONTENT_TYPE" && key != "HTTP_CONTENT_LENGTH")
|
|
||||||
env[key] = iter.value();
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Populate HTTP_COOKIE parameter
|
|
||||||
iter = event->cookies.constBegin();
|
|
||||||
QString cookies;
|
|
||||||
while (iter != event->cookies.constEnd())
|
|
||||||
{
|
|
||||||
if (!cookies.isEmpty())
|
|
||||||
cookies += "; ";
|
|
||||||
cookies += iter.key() + '=' + iter.value();
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
if (!cookies.isEmpty())
|
|
||||||
env["HTTP_COOKIE"] = cookies;
|
|
||||||
|
|
||||||
// Load environment into process space
|
|
||||||
QStringList p_env;
|
|
||||||
QMap<QString, QString>::iterator env_iter = env.begin();
|
|
||||||
while (env_iter != env.end())
|
|
||||||
{
|
|
||||||
p_env << env_iter.key() + '=' + env_iter.value();
|
|
||||||
env_iter++;
|
|
||||||
}
|
|
||||||
process->setEnvironment(p_env);
|
|
||||||
|
|
||||||
// Launch process
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
|
|
||||||
if (event->url.hasQuery() && event->url.query().contains('='))
|
|
||||||
#else
|
|
||||||
if (event->url.hasQuery() && event->url.encodedQuery().contains('='))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
// CGI/1.1 spec says to pass the query on the command line if there's no embedded = sign
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
|
|
||||||
process->start(qxt_d().binary + ' ' + event->url.query(), QIODevice::ReadWrite);
|
|
||||||
#else
|
|
||||||
process->start(qxt_d().binary + ' ' + event->url.encodedQuery(), QIODevice::ReadWrite);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
process->start(qxt_d().binary, QIODevice::ReadWrite);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the timeout
|
|
||||||
if(qxt_d().timeout > 0)
|
|
||||||
{
|
|
||||||
requestInfo.timeout->start(qxt_d().timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transmit POST data
|
|
||||||
if (event->content)
|
|
||||||
{
|
|
||||||
QObject::connect(event->content, SIGNAL(readyRead()), &qxt_d(), SLOT(browserReadyRead()));
|
|
||||||
qxt_d().browserReadyRead(event->content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \internal
|
|
||||||
*/
|
|
||||||
void QxtWebCgiServicePrivate::browserReadyRead(QObject* o_content)
|
|
||||||
{
|
|
||||||
if (!o_content) o_content = sender();
|
|
||||||
QxtWebContent* content = static_cast<QxtWebContent*>(o_content); // this is a private class, no worries about type safety
|
|
||||||
|
|
||||||
// Read POST data and copy it to the process
|
|
||||||
QByteArray data = content->readAll();
|
|
||||||
if (!data.isEmpty())
|
|
||||||
processes[content]->write(data);
|
|
||||||
|
|
||||||
// If no POST data remains unsent, clean up
|
|
||||||
if (!content->unreadBytes() && processes.contains(content))
|
|
||||||
{
|
|
||||||
processes[content]->closeWriteChannel();
|
|
||||||
processes.remove(content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \internal
|
|
||||||
*/
|
|
||||||
void QxtWebCgiServicePrivate::processReadyRead()
|
|
||||||
{
|
|
||||||
QProcess* process = static_cast<QProcess*>(sender());
|
|
||||||
QxtCgiRequestInfo& request = requests[process];
|
|
||||||
|
|
||||||
QByteArray line;
|
|
||||||
while (process->canReadLine())
|
|
||||||
{
|
|
||||||
// Read in a CGI/1.1 header line
|
|
||||||
line = process->readLine().replace(QByteArray("\r"), ""); //krazy:exclude=doublequote_chars
|
|
||||||
if (line == "\n")
|
|
||||||
{
|
|
||||||
// An otherwise-empty line indicates the end of CGI/1.1 headers and the start of content
|
|
||||||
QObject::disconnect(process, SIGNAL(readyRead()), this, 0);
|
|
||||||
QxtWebPageEvent* event = 0;
|
|
||||||
int code = 200;
|
|
||||||
if (request.headers.contains("status"))
|
|
||||||
{
|
|
||||||
// CGI/1.1 defines a "Status:" header that dictates the HTTP response code
|
|
||||||
code = request.headers["status"].left(3).toInt();
|
|
||||||
if (code >= 300 && code < 400) // redirect
|
|
||||||
{
|
|
||||||
event = new QxtWebRedirectEvent(request.sessionID, request.requestID, request.headers["location"], code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If a previous header (currently just status) hasn't created an event, create a normal page event here
|
|
||||||
if (!event)
|
|
||||||
{
|
|
||||||
event = new QxtWebPageEvent(request.sessionID, request.requestID, process);
|
|
||||||
event->status = code;
|
|
||||||
}
|
|
||||||
// Add other response headers passed from CGI (currently only Content-Type is supported)
|
|
||||||
if (request.headers.contains("content-type"))
|
|
||||||
event->contentType = request.headers["content-type"].toUtf8();
|
|
||||||
// TODO: QxtWeb doesn't support transmitting arbitrary HTTP headers right now, but it may be desirable
|
|
||||||
// for applications that know what kind of server frontend they're using to allow scripts to send
|
|
||||||
// protocol-specific headers.
|
|
||||||
|
|
||||||
// Post the event
|
|
||||||
qxt_p().postEvent(event);
|
|
||||||
request.eventSent = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Since we haven't reached the end of headers yet, parse a header
|
|
||||||
int pos = line.indexOf(": ");
|
|
||||||
QByteArray hdrName = line.left(pos).toLower();
|
|
||||||
QByteArray hdrValue = line.mid(pos + 2).replace(QByteArray("\n"), ""); //krazy:exclude=doublequote_chars
|
|
||||||
if (hdrName == "set-cookie")
|
|
||||||
{
|
|
||||||
// Parse a new cookie and post an event to send it to the client
|
|
||||||
QList<QByteArray> cookies = hdrValue.split(',');
|
|
||||||
foreach(const QByteArray& cookie, cookies)
|
|
||||||
{
|
|
||||||
int equals = cookie.indexOf("=");
|
|
||||||
int semi = cookie.indexOf(";");
|
|
||||||
QByteArray cookieName = cookie.left(equals);
|
|
||||||
int age = cookie.toLower().indexOf("max-age=", semi);
|
|
||||||
int secs = -1;
|
|
||||||
if (age >= 0)
|
|
||||||
secs = cookie.mid(age + 8, cookie.indexOf(";", age) - age - 8).toInt();
|
|
||||||
if (secs == 0)
|
|
||||||
{
|
|
||||||
qxt_p().postEvent(new QxtWebRemoveCookieEvent(request.sessionID, cookieName));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QByteArray cookieValue = cookie.mid(equals + 1, semi - equals - 1);
|
|
||||||
QDateTime cookieExpires;
|
|
||||||
if (secs != -1)
|
|
||||||
cookieExpires = QDateTime::currentDateTime().addSecs(secs);
|
|
||||||
qxt_p().postEvent(new QxtWebStoreCookieEvent(request.sessionID, cookieName, cookieValue, cookieExpires));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(hdrName == "x-qxtweb-timeout")
|
|
||||||
{
|
|
||||||
if(timeoutOverride)
|
|
||||||
request.timeout->setInterval(hdrValue.toInt());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Store other headers for later inspection
|
|
||||||
request.headers[hdrName] = hdrValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \internal
|
|
||||||
*/
|
|
||||||
void QxtWebCgiServicePrivate::processFinished()
|
|
||||||
{
|
|
||||||
QProcess* process = static_cast<QProcess*>(sender());
|
|
||||||
QxtCgiRequestInfo& request = requests[process];
|
|
||||||
|
|
||||||
if (!request.eventSent)
|
|
||||||
{
|
|
||||||
// If no event was posted, issue an internal error
|
|
||||||
qxt_p().postEvent(new QxtWebErrorEvent(request.sessionID, request.requestID, 500, "Internal Server Error"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up data structures
|
|
||||||
process->close();
|
|
||||||
QxtWebContent* key = processes.key(process);
|
|
||||||
if (key) processes.remove(key);
|
|
||||||
timeoutMapper.removeMappings(request.timeout);
|
|
||||||
requests.remove(process);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \internal
|
|
||||||
*/
|
|
||||||
void QxtWebCgiServicePrivate::terminateProcess(QObject* o_process)
|
|
||||||
{
|
|
||||||
QProcess* process = static_cast<QProcess*>(o_process);
|
|
||||||
QxtCgiRequestInfo& request = requests[process];
|
|
||||||
|
|
||||||
if(request.terminateSent)
|
|
||||||
{
|
|
||||||
// kill with fire
|
|
||||||
process->kill();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// kill nicely
|
|
||||||
process->terminate();
|
|
||||||
request.terminateSent = true;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,64 +0,0 @@
|
|||||||
|
|
||||||
/****************************************************************************
|
|
||||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
|
||||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
|
||||||
** All rights reserved.
|
|
||||||
**
|
|
||||||
** Redistribution and use in source and binary forms, with or without
|
|
||||||
** modification, are permitted provided that the following conditions are met:
|
|
||||||
** * Redistributions of source code must retain the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer.
|
|
||||||
** * Redistributions in binary form must reproduce the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer in the
|
|
||||||
** documentation and/or other materials provided with the distribution.
|
|
||||||
** * Neither the name of the LibQxt project nor the
|
|
||||||
** names of its contributors may be used to endorse or promote products
|
|
||||||
** derived from this software without specific prior written permission.
|
|
||||||
**
|
|
||||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
|
||||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
**
|
|
||||||
** <http://libqxt.org> <foundation@libqxt.org>
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef QXTWEBCGISERVICE_H
|
|
||||||
#define QXTWEBCGISERVICE_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <qxtglobal.h>
|
|
||||||
#include "qxtabstractwebsessionmanager.h"
|
|
||||||
#include "qxtabstractwebservice.h"
|
|
||||||
class QxtWebEvent;
|
|
||||||
class QxtWebRequestEvent;
|
|
||||||
|
|
||||||
class QxtWebCgiServicePrivate;
|
|
||||||
class QXT_WEB_EXPORT QxtWebCgiService : public QxtAbstractWebService
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
QxtWebCgiService(const QString& binary, QxtAbstractWebSessionManager* manager, QObject* parent = 0);
|
|
||||||
|
|
||||||
QString binary() const;
|
|
||||||
void setBinary(const QString& bin);
|
|
||||||
|
|
||||||
int timeout() const;
|
|
||||||
void setTimeout(int time);
|
|
||||||
|
|
||||||
bool timeoutOverride() const;
|
|
||||||
void setTimeoutOverride(bool enable);
|
|
||||||
|
|
||||||
virtual void pageRequestedEvent(QxtWebRequestEvent* event);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QXT_DECLARE_PRIVATE(QxtWebCgiService)
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // QXTWEBCGISERVICE_H
|
|
@@ -1,512 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
|
||||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
|
||||||
** All rights reserved.
|
|
||||||
**
|
|
||||||
** Redistribution and use in source and binary forms, with or without
|
|
||||||
** modification, are permitted provided that the following conditions are met:
|
|
||||||
** * Redistributions of source code must retain the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer.
|
|
||||||
** * Redistributions in binary form must reproduce the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer in the
|
|
||||||
** documentation and/or other materials provided with the distribution.
|
|
||||||
** * Neither the name of the LibQxt project nor the
|
|
||||||
** names of its contributors may be used to endorse or promote products
|
|
||||||
** derived from this software without specific prior written permission.
|
|
||||||
**
|
|
||||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
|
||||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
**
|
|
||||||
** <http://libqxt.org> <foundation@libqxt.org>
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\class QxtWebJsonRPCService
|
|
||||||
|
|
||||||
\inmodule QxtWeb
|
|
||||||
|
|
||||||
\brief The QxtWebJsonRPCService class provides a Slot based webservice that responds to JSONRPC
|
|
||||||
|
|
||||||
See http://json-rpc.org for details on the protocol
|
|
||||||
|
|
||||||
To create a Webservice, simply subclass QxtWebJsonRPCService. All slots are exposed as jsonrpc method
|
|
||||||
|
|
||||||
\code
|
|
||||||
class MyService : public QxtWebJsonRPCService
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public slots:
|
|
||||||
int add(int a, int b
|
|
||||||
{
|
|
||||||
return a +b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
\code
|
|
||||||
curl -d '{"method":"add", "id":1, "params": [9,2] }' localhost:1339
|
|
||||||
{"error":null,"id":1,"result":11}
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
\sa QxtAbstractWebService
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "qxtwebjsonrpcservice_p.h"
|
|
||||||
#include "qxtwebevent.h"
|
|
||||||
#include "qxtwebcontent.h"
|
|
||||||
#include "qxtjson.h"
|
|
||||||
|
|
||||||
#include <QtCore/QMetaMethod>
|
|
||||||
#include <QtCore/QMetaType>
|
|
||||||
#include <QtCore/QGenericReturnArgument>
|
|
||||||
#include <QtCore/QGenericArgument>
|
|
||||||
|
|
||||||
|
|
||||||
QxtWebJsonRPCService::Private::Private(QxtWebJsonRPCService *that)
|
|
||||||
: QObject()
|
|
||||||
, p(that)
|
|
||||||
, invokable(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void QxtWebJsonRPCService::Private::initTables(QObject *in)
|
|
||||||
{
|
|
||||||
invokable = in;
|
|
||||||
const QMetaObject *po = invokable->metaObject();
|
|
||||||
for (int i = po->methodOffset(); i < po->methodCount(); i++) {
|
|
||||||
|
|
||||||
QxtWebJsonRPCService::Private::Method method;
|
|
||||||
QMetaMethod mo = po->method (i);
|
|
||||||
#if QT_VERSION >= 0x50000
|
|
||||||
method.name = QByteArray(mo.methodSignature()).split('(').at(0);
|
|
||||||
#else
|
|
||||||
method.name = QByteArray(mo.signature()).split('(').at(0);
|
|
||||||
#endif
|
|
||||||
method.meta = mo;
|
|
||||||
method.argCount = mo.parameterTypes ().count();
|
|
||||||
method.returns = QByteArray(mo.typeName()).count();
|
|
||||||
methods.insert(method.name + QByteArray::number(method.argCount), method);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QxtWebJsonRPCService::Private::readFinished()
|
|
||||||
{
|
|
||||||
QxtWebContent *c = qobject_cast<QxtWebContent *>(sender());
|
|
||||||
handle(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QxtWebJsonRPCService::Private::handle(QxtWebContent *c)
|
|
||||||
{
|
|
||||||
QxtWebRequestEvent *event = content.take(c);
|
|
||||||
currentRequest = 0;
|
|
||||||
c->ignoreRemainingContent();
|
|
||||||
|
|
||||||
QString data = QString::fromUtf8(c->readAll());
|
|
||||||
|
|
||||||
QVariantMap var = QxtJSON::parse(data).toMap();
|
|
||||||
|
|
||||||
if (var.isEmpty()) {
|
|
||||||
QByteArray resp = "{\"result\": null, \"error\": \"invalid json data\", \"id\": 0}\r\n";
|
|
||||||
QxtWebPageEvent *err = new QxtWebPageEvent(event->sessionID, event->requestID, resp);
|
|
||||||
err->status = 500;
|
|
||||||
p->postEvent(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QVariant rid = var.value("id");
|
|
||||||
QString action = var.value("method").toString();
|
|
||||||
QVariant argsE = var.value("params");
|
|
||||||
handle(event, rid, action, argsE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QxtWebJsonRPCService::Private::handle(QxtWebRequestEvent *event, QVariant rid, QString action, QVariant argsE)
|
|
||||||
{
|
|
||||||
QVariantMap argsM;
|
|
||||||
QVariantList args;
|
|
||||||
|
|
||||||
if (argsE.type() == QVariant::Map) {
|
|
||||||
argsM = argsE.toMap();
|
|
||||||
args = argsM.values();
|
|
||||||
} else {
|
|
||||||
args = argsE.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!invokable)
|
|
||||||
initTables(p);
|
|
||||||
|
|
||||||
|
|
||||||
if (!methods.contains(action.toUtf8() + QByteArray::number(args.count()))) {
|
|
||||||
QVariantMap res;
|
|
||||||
res.insert("result", QVariant());
|
|
||||||
res.insert("error", "no such method or incorrect number of arguments");
|
|
||||||
res.insert("id", rid);
|
|
||||||
QxtWebPageEvent *err = new QxtWebPageEvent(event->sessionID, event->requestID,
|
|
||||||
QxtJSON::stringify(res).toUtf8() + "\r\n");
|
|
||||||
p->postEvent(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Method method = methods.value(action.toUtf8() + QByteArray::number(args.count()));
|
|
||||||
if (argsE.type() == QVariant::Map) {
|
|
||||||
args.clear();
|
|
||||||
foreach (const QString &pname, method.meta.parameterNames ()) {
|
|
||||||
args.append(argsM.value(pname));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QList<QGenericArgument> vargs;
|
|
||||||
foreach (const QVariant &ar, args) {
|
|
||||||
vargs.append(QGenericArgument(ar.typeName(), ar.data()));
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant returnValue;
|
|
||||||
currentRequest = event;
|
|
||||||
currentRequestId = rid;
|
|
||||||
requestCanceled = false;
|
|
||||||
|
|
||||||
bool ok = false;
|
|
||||||
if (method.returns) {
|
|
||||||
QVariant retA(QVariant::nameToType(method.meta.typeName()));
|
|
||||||
QGenericReturnArgument ret(retA.typeName(), retA.data());
|
|
||||||
if (args.count() > 8)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
ret,
|
|
||||||
(vargs.at(0)),
|
|
||||||
(vargs.at(1)),
|
|
||||||
(vargs.at(2)),
|
|
||||||
(vargs.at(3)),
|
|
||||||
(vargs.at(4)),
|
|
||||||
(vargs.at(5)),
|
|
||||||
(vargs.at(6)),
|
|
||||||
(vargs.at(7)),
|
|
||||||
(vargs.at(7))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (args.count() > 7)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
ret,
|
|
||||||
(vargs.at(0)),
|
|
||||||
(vargs.at(1)),
|
|
||||||
(vargs.at(2)),
|
|
||||||
(vargs.at(3)),
|
|
||||||
(vargs.at(4)),
|
|
||||||
(vargs.at(5)),
|
|
||||||
(vargs.at(6)),
|
|
||||||
(vargs.at(7))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (args.count() > 6)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
ret,
|
|
||||||
(vargs.at(0)),
|
|
||||||
(vargs.at(1)),
|
|
||||||
(vargs.at(2)),
|
|
||||||
(vargs.at(3)),
|
|
||||||
(vargs.at(4)),
|
|
||||||
(vargs.at(5)),
|
|
||||||
(vargs.at(6))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (args.count() > 5)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
ret,
|
|
||||||
(vargs.at(0)),
|
|
||||||
(vargs.at(1)),
|
|
||||||
(vargs.at(2)),
|
|
||||||
(vargs.at(3)),
|
|
||||||
(vargs.at(4)),
|
|
||||||
(vargs.at(5))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (args.count() > 4)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
ret,
|
|
||||||
(vargs.at(0)),
|
|
||||||
(vargs.at(1)),
|
|
||||||
(vargs.at(2)),
|
|
||||||
(vargs.at(3)),
|
|
||||||
(vargs.at(4))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (args.count() > 3)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
ret,
|
|
||||||
(vargs.at(0)),
|
|
||||||
(vargs.at(1)),
|
|
||||||
(vargs.at(2)),
|
|
||||||
(vargs.at(3))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (args.count() > 2)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
ret,
|
|
||||||
(vargs.at(0)),
|
|
||||||
(vargs.at(1)),
|
|
||||||
(vargs.at(2))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (args.count() > 1)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
ret,
|
|
||||||
(vargs.at(0)),
|
|
||||||
(vargs.at(1))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (args.count() > 0)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
ret,
|
|
||||||
(vargs.at(0))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
ret
|
|
||||||
);
|
|
||||||
}
|
|
||||||
returnValue = retA;
|
|
||||||
// the pass through QGenericReturnArgument didn't make it non null.
|
|
||||||
returnValue.data_ptr().is_null = 0;
|
|
||||||
} else {
|
|
||||||
if (args.count() > 8)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
(vargs.at(0)),
|
|
||||||
(vargs.at(1)),
|
|
||||||
(vargs.at(2)),
|
|
||||||
(vargs.at(3)),
|
|
||||||
(vargs.at(4)),
|
|
||||||
(vargs.at(5)),
|
|
||||||
(vargs.at(6)),
|
|
||||||
(vargs.at(7)),
|
|
||||||
(vargs.at(7))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (args.count() > 7)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
(vargs.at(0)),
|
|
||||||
(vargs.at(1)),
|
|
||||||
(vargs.at(2)),
|
|
||||||
(vargs.at(3)),
|
|
||||||
(vargs.at(4)),
|
|
||||||
(vargs.at(5)),
|
|
||||||
(vargs.at(6)),
|
|
||||||
(vargs.at(7))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (args.count() > 6)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
(vargs.at(0)),
|
|
||||||
(vargs.at(1)),
|
|
||||||
(vargs.at(2)),
|
|
||||||
(vargs.at(3)),
|
|
||||||
(vargs.at(4)),
|
|
||||||
(vargs.at(5)),
|
|
||||||
(vargs.at(6))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (args.count() > 5)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
(vargs.at(0)),
|
|
||||||
(vargs.at(1)),
|
|
||||||
(vargs.at(2)),
|
|
||||||
(vargs.at(3)),
|
|
||||||
(vargs.at(4)),
|
|
||||||
(vargs.at(5))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (args.count() > 4)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
(vargs.at(0)),
|
|
||||||
(vargs.at(1)),
|
|
||||||
(vargs.at(2)),
|
|
||||||
(vargs.at(3)),
|
|
||||||
(vargs.at(4))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (args.count() > 3)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
(vargs.at(0)),
|
|
||||||
(vargs.at(1)),
|
|
||||||
(vargs.at(2)),
|
|
||||||
(vargs.at(3))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (args.count() > 2)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
(vargs.at(0)),
|
|
||||||
(vargs.at(1)),
|
|
||||||
(vargs.at(2))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (args.count() > 1)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
(vargs.at(0)),
|
|
||||||
(vargs.at(1))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (args.count() > 0)
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable,
|
|
||||||
(vargs.at(0))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ok = method.meta.invoke(invokable
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!ok) {
|
|
||||||
QVariantMap res;
|
|
||||||
res.insert("result", QVariant());
|
|
||||||
res.insert("error", "execution failure");
|
|
||||||
res.insert("id", rid);
|
|
||||||
QxtWebPageEvent *err = new QxtWebPageEvent(event->sessionID, event->requestID,
|
|
||||||
QxtJSON::stringify(res).toUtf8() + "\r\n");
|
|
||||||
p->postEvent(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (requestCanceled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantMap res;
|
|
||||||
res.insert("result", returnValue);
|
|
||||||
res.insert("error", QVariant());
|
|
||||||
res.insert("id", rid);
|
|
||||||
QxtWebPageEvent *err = new QxtWebPageEvent(event->sessionID, event->requestID,
|
|
||||||
QxtJSON::stringify(res).toUtf8() + "\r\n");
|
|
||||||
p->postEvent(err);
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
/*!
|
|
||||||
Constructs a new QxtWebJsonRPCService with \a sm and \a parent.
|
|
||||||
*/
|
|
||||||
QxtWebJsonRPCService::QxtWebJsonRPCService(QxtAbstractWebSessionManager* sm, QObject* parent)
|
|
||||||
: QxtAbstractWebService(sm, parent)
|
|
||||||
, d(new Private(this))
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
QxtWebJsonRPCService::~QxtWebJsonRPCService()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* respond to the current request with an error.
|
|
||||||
*
|
|
||||||
* The return value of the current slot is NOT used.
|
|
||||||
* Instead null is returned, adhering to the jsonrpc specificaiton.
|
|
||||||
*
|
|
||||||
* Calling this function from somewhere else then a handler slot is undefined behaviour.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void QxtWebJsonRPCService::throwRPCError(QVariant error)
|
|
||||||
{
|
|
||||||
d->requestCanceled= true;
|
|
||||||
QxtWebRequestEvent *event = d->currentRequest;
|
|
||||||
|
|
||||||
QVariantMap res;
|
|
||||||
res.insert("result", QVariant());
|
|
||||||
res.insert("error", error);
|
|
||||||
res.insert("id", d->currentRequestId);
|
|
||||||
QxtWebPageEvent *err = new QxtWebPageEvent(event->sessionID, event->requestID,
|
|
||||||
QxtJSON::stringify(res).toUtf8() + "\r\n");
|
|
||||||
postEvent(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns the current absolute url of this service depending on the request \a event.
|
|
||||||
*/
|
|
||||||
QUrl QxtWebJsonRPCService::self(QxtWebRequestEvent* event)
|
|
||||||
|
|
||||||
{
|
|
||||||
QStringList u = event->url.path().split('/');
|
|
||||||
QStringList o = event->originalUrl.path().split('/');
|
|
||||||
u.removeFirst();
|
|
||||||
o.removeFirst();
|
|
||||||
for (int i = 0;i < u.count();i++)
|
|
||||||
o.removeLast();
|
|
||||||
|
|
||||||
|
|
||||||
QString r = "/";
|
|
||||||
foreach(const QString& d, o)
|
|
||||||
{
|
|
||||||
r += d + '/';
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\reimp
|
|
||||||
*/
|
|
||||||
void QxtWebJsonRPCService::pageRequestedEvent(QxtWebRequestEvent* event)
|
|
||||||
{
|
|
||||||
if (event->method == "GET") {
|
|
||||||
QVariantMap params;
|
|
||||||
QList<QPair<QByteArray, QByteArray> > enc = event->url.encodedQueryItems ();
|
|
||||||
for (int i = 0; i < enc.count(); i++) {
|
|
||||||
params.insert(
|
|
||||||
QUrl::fromPercentEncoding (enc.at(i).first),
|
|
||||||
QUrl::fromPercentEncoding (enc.at(i).second));
|
|
||||||
}
|
|
||||||
QString method = event->url.path().split('/').last();
|
|
||||||
d->handle(event, QVariant(), method, params);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (!event->content) {
|
|
||||||
QVariantMap res;
|
|
||||||
res.insert("result", QVariant());
|
|
||||||
res.insert("error", "missing POST data");
|
|
||||||
res.insert("id", QVariant());
|
|
||||||
QxtWebPageEvent *err = new QxtWebPageEvent(event->sessionID, event->requestID,
|
|
||||||
QxtJSON::stringify(res).toUtf8() + "\r\n");
|
|
||||||
err->status = 500;
|
|
||||||
postEvent(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->content.insert(event->content, event);
|
|
||||||
if (event->content->bytesNeeded() == 0) {
|
|
||||||
d->handle(event->content);
|
|
||||||
} else {
|
|
||||||
connect(event->content, SIGNAL(readChannelFinished()), d, SLOT(readFinished()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\reimp
|
|
||||||
*/
|
|
||||||
void QxtWebJsonRPCService::functionInvokedEvent(QxtWebRequestEvent* event)
|
|
||||||
{
|
|
||||||
postEvent(new QxtWebErrorEvent(event->sessionID, event->requestID, 500, "<h1>Not supported</h1>"));
|
|
||||||
}
|
|
@@ -1,56 +0,0 @@
|
|||||||
|
|
||||||
/****************************************************************************
|
|
||||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
|
||||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
|
||||||
** All rights reserved.
|
|
||||||
**
|
|
||||||
** Redistribution and use in source and binary forms, with or without
|
|
||||||
** modification, are permitted provided that the following conditions are met:
|
|
||||||
** * Redistributions of source code must retain the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer.
|
|
||||||
** * Redistributions in binary form must reproduce the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer in the
|
|
||||||
** documentation and/or other materials provided with the distribution.
|
|
||||||
** * Neither the name of the LibQxt project nor the
|
|
||||||
** names of its contributors may be used to endorse or promote products
|
|
||||||
** derived from this software without specific prior written permission.
|
|
||||||
**
|
|
||||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
|
||||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
**
|
|
||||||
** <http://libqxt.org> <foundation@libqxt.org>
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef QXTWEBJSONRPCSERVICE_H
|
|
||||||
#define QXTWEBJSONRPCSERVICE_H
|
|
||||||
|
|
||||||
#include "qxtabstractwebservice.h"
|
|
||||||
#include <QUrl>
|
|
||||||
|
|
||||||
class QXT_WEB_EXPORT QxtWebJsonRPCService : public QxtAbstractWebService
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit QxtWebJsonRPCService(QxtAbstractWebSessionManager* sm, QObject* parent = 0);
|
|
||||||
virtual ~QxtWebJsonRPCService();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void throwRPCError(QVariant error);
|
|
||||||
|
|
||||||
QUrl self(QxtWebRequestEvent* event);
|
|
||||||
virtual void pageRequestedEvent(QxtWebRequestEvent* event);
|
|
||||||
virtual void functionInvokedEvent(QxtWebRequestEvent* event);
|
|
||||||
private:
|
|
||||||
class Private;
|
|
||||||
Private *d;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // QXTWEBJSONRPCSERVICE_H
|
|
@@ -1,66 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
|
||||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
|
||||||
** All rights reserved.
|
|
||||||
**
|
|
||||||
** Redistribution and use in source and binary forms, with or without
|
|
||||||
** modification, are permitted provided that the following conditions are met:
|
|
||||||
** * Redistributions of source code must retain the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer.
|
|
||||||
** * Redistributions in binary form must reproduce the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer in the
|
|
||||||
** documentation and/or other materials provided with the distribution.
|
|
||||||
** * Neither the name of the LibQxt project nor the
|
|
||||||
** names of its contributors may be used to endorse or promote products
|
|
||||||
** derived from this software without specific prior written permission.
|
|
||||||
**
|
|
||||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
|
||||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
**
|
|
||||||
** <http://libqxt.org> <foundation@libqxt.org>
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#include "qxtwebjsonrpcservice.h"
|
|
||||||
#include "qxtwebcontent.h"
|
|
||||||
#include "qxtwebevent.h"
|
|
||||||
#include <QtCore/QMetaMethod>
|
|
||||||
|
|
||||||
class QxtWebJsonRPCService::Private : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
Private(QxtWebJsonRPCService *that);
|
|
||||||
QMap<QxtWebContent *, QxtWebRequestEvent*> content;
|
|
||||||
|
|
||||||
QxtWebJsonRPCService *p;
|
|
||||||
void initTables(QObject *invokable);
|
|
||||||
bool tablesInitilized;
|
|
||||||
QObject *invokable;
|
|
||||||
|
|
||||||
struct Method
|
|
||||||
{
|
|
||||||
QMetaMethod meta;
|
|
||||||
QByteArray name;
|
|
||||||
bool returns;
|
|
||||||
int argCount;
|
|
||||||
};
|
|
||||||
QMap<QByteArray, Method> methods;
|
|
||||||
|
|
||||||
QxtWebRequestEvent *currentRequest;
|
|
||||||
QVariant currentRequestId;
|
|
||||||
bool requestCanceled;
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void readFinished();
|
|
||||||
void handle(QxtWebContent *);
|
|
||||||
void handle( QxtWebRequestEvent *event, QVariant id, QString method, QVariant args);
|
|
||||||
};
|
|
||||||
|
|
@@ -42,11 +42,12 @@
|
|||||||
#ifndef QHTTP_H
|
#ifndef QHTTP_H
|
||||||
#define QHTTP_H
|
#define QHTTP_H
|
||||||
|
|
||||||
#include <QtCore/qobject.h>
|
#include <QObject>
|
||||||
#include <QtCore/qstringlist.h>
|
#include <QStringList>
|
||||||
#include <QtCore/qmap.h>
|
#include <QMap>
|
||||||
#include <QtCore/qpair.h>
|
#include <QPair>
|
||||||
#include <QtCore/qscopedpointer.h>
|
#include <QScopedPointer>
|
||||||
|
#include <qxtglobal.h>
|
||||||
|
|
||||||
QT_BEGIN_HEADER
|
QT_BEGIN_HEADER
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ class QSslError;
|
|||||||
class QHttpPrivate;
|
class QHttpPrivate;
|
||||||
|
|
||||||
class QHttpHeaderPrivate;
|
class QHttpHeaderPrivate;
|
||||||
class Q_NETWORK_EXPORT QHttpHeader
|
class QXT_WEB_EXPORT QHttpHeader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QHttpHeader();
|
QHttpHeader();
|
||||||
@@ -116,7 +117,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class QHttpResponseHeaderPrivate;
|
class QHttpResponseHeaderPrivate;
|
||||||
class Q_NETWORK_EXPORT QHttpResponseHeader : public QHttpHeader
|
class QXT_WEB_EXPORT QHttpResponseHeader : public QHttpHeader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QHttpResponseHeader();
|
QHttpResponseHeader();
|
||||||
@@ -144,7 +145,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class QHttpRequestHeaderPrivate;
|
class QHttpRequestHeaderPrivate;
|
||||||
class Q_NETWORK_EXPORT QHttpRequestHeader : public QHttpHeader
|
class QXT_WEB_EXPORT QHttpRequestHeader : public QHttpHeader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QHttpRequestHeader();
|
QHttpRequestHeader();
|
@@ -52,7 +52,7 @@ QxtWeb uses QxtWebContent as an abstraction for streaming data.
|
|||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
|
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -272,13 +272,13 @@ typedef QPair<QString, QString> QxtQueryItem;
|
|||||||
*/
|
*/
|
||||||
QHash<QString, QString> QxtWebContent::parseUrlEncodedQuery(const QString& data)
|
QHash<QString, QString> QxtWebContent::parseUrlEncodedQuery(const QString& data)
|
||||||
{
|
{
|
||||||
QUrl post("/?" + data);
|
|
||||||
QHash<QString, QString> rv;
|
QHash<QString, QString> rv;
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
|
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||||
foreach(const QxtQueryItem& item, QUrlQuery( post ).queryItems())
|
QUrl post("/?" + data);
|
||||||
#else
|
#else
|
||||||
foreach(const QxtQueryItem& item, post.queryItems())
|
QUrlQuery post("/?" + data);
|
||||||
#endif
|
#endif
|
||||||
|
foreach(const QxtQueryItem& item, post.queryItems())
|
||||||
{
|
{
|
||||||
rv.insertMulti(item.first, item.second);
|
rv.insertMulti(item.first, item.second);
|
||||||
}
|
}
|
@@ -42,7 +42,7 @@ A WebService that resolves the first part of the path to a slot name and passes
|
|||||||
\code
|
\code
|
||||||
class MyService : public QxtWebSlotService
|
class MyService : public QxtWebSlotService
|
||||||
{
|
{
|
||||||
//Q_OBJECT
|
// Q_OBJECT
|
||||||
public slots:
|
public slots:
|
||||||
void hello(QxtWebRequestEvent* event, QString a)
|
void hello(QxtWebRequestEvent* event, QString a)
|
||||||
{
|
{
|
Reference in New Issue
Block a user