summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2013-02-20 15:01:35 +0100
committerPierre Rossi <pierre.rossi@gmail.com>2013-11-01 13:57:49 +0100
commitb1d0a375185925506e893d3b32cf19a941a73141 (patch)
tree834a670e5989c9791cb00968803025bc63757cc3
parent211f8ac57b6718dd36691ac34326e9aa405664b6 (diff)
downloadqtwebchannel-b1d0a375185925506e893d3b32cf19a941a73141.tar.gz
Validate the QWebChannel secret and use the QWebChannel protocol.
Change-Id: Idafda1326de072f9fa1853cb54cb0de459186bb1 Reviewed-by: Pierre Rossi <pierre.rossi@gmail.com>
-rw-r--r--src/qwebchannel.cpp48
-rw-r--r--src/qwebsocketserver.cpp9
-rw-r--r--src/qwebsocketserver.h7
-rw-r--r--src/webchannel.js2
4 files changed, 40 insertions, 26 deletions
diff --git a/src/qwebchannel.cpp b/src/qwebchannel.cpp
index 7ae766e..2a78624 100644
--- a/src/qwebchannel.cpp
+++ b/src/qwebchannel.cpp
@@ -47,31 +47,25 @@
#include "qwebsocketserver.h"
-class QWebChannelPrivate : public QObject
+class QWebChannelPrivate : public QWebSocketServer
{
Q_OBJECT
public:
- QWebSocketServer m_server;
- QString m_secret;
+ QByteArray m_secret;
bool m_useSecret;
QString m_baseUrl;
bool m_starting;
QWebChannelPrivate(QObject* parent)
- : QObject(parent)
+ : QWebSocketServer(parent)
, m_useSecret(true)
, m_starting(false)
{
- connect(&m_server, SIGNAL(error(QAbstractSocket::SocketError)),
+ connect(this, SIGNAL(error(QAbstractSocket::SocketError)),
SLOT(socketError()));
}
- virtual ~QWebChannelPrivate()
- {
- m_server.close();
- }
-
void initLater()
{
if (m_starting)
@@ -84,41 +78,55 @@ signals:
void failed(const QString& reason);
void initialized();
+protected:
+ virtual bool isValid(const HeaderData& connection);
+
private slots:
void init();
void socketError();
};
+bool QWebChannelPrivate::isValid(const HeaderData& connection)
+{
+ if (!QWebSocketServer::isValid(connection)) {
+ return false;
+ }
+ return connection.protocol == QByteArrayLiteral("QWebChannel")
+ && connection.path == m_secret;
+}
+
void QWebChannelPrivate::init()
{
- m_server.close();
+ close();
m_starting = false;
if (m_useSecret) {
- m_secret = QUuid::createUuid().toString();
- m_secret = m_secret.mid(1, m_secret.size() - 2);
+ m_secret = QUuid::createUuid().toByteArray();
+ // replace { by /
+ m_secret[0] = '/';
+ // chop of trailing }
+ m_secret.chop(1);
}
- if (!m_server.listen(QHostAddress::LocalHost)) {
- emit failed(m_server.errorString());
+ if (!listen(QHostAddress::LocalHost)) {
+ emit failed(errorString());
return;
}
- m_baseUrl = QString("localhost:%1/%2").arg(m_server.port()).arg(m_secret);
- qDebug() << m_baseUrl;
+ m_baseUrl = QString("localhost:%1%2").arg(port()).arg(QString::fromLatin1(m_secret));
emit initialized();
}
void QWebChannelPrivate::socketError()
{
- emit failed(m_server.errorString());
+ emit failed(errorString());
}
QWebChannel::QWebChannel(QObject *parent)
: QObject(parent)
, d(new QWebChannelPrivate(this))
{
- connect(&d->m_server, SIGNAL(textDataReceived(QString)),
+ connect(d, SIGNAL(textDataReceived(QString)),
SIGNAL(rawMessageReceived(QString)));
connect(d, SIGNAL(failed(QString)),
SIGNAL(failed(QString)));
@@ -157,7 +165,7 @@ void QWebChannel::onInitialized()
void QWebChannel::sendRawMessage(const QString& message)
{
- d->m_server.sendMessage(message);
+ d->sendMessage(message);
}
#include <qwebchannel.moc>
diff --git a/src/qwebsocketserver.cpp b/src/qwebsocketserver.cpp
index 81d47e9..a87d4bf 100644
--- a/src/qwebsocketserver.cpp
+++ b/src/qwebsocketserver.cpp
@@ -86,6 +86,11 @@ QWebSocketServer::QWebSocketServer(QObject* parent)
SIGNAL(error(QAbstractSocket::SocketError)));
}
+QWebSocketServer::~QWebSocketServer()
+{
+ close();
+}
+
bool QWebSocketServer::listen(const QHostAddress& address, quint16 port)
{
return m_server->listen(address, port);
@@ -136,7 +141,7 @@ void QWebSocketServer::disconnected()
}
static const QByteArray headerSwitchProtocols = QByteArrayLiteral("HTTP/1.1 101 Switching Protocols");
-static const QByteArray headerGet = QByteArrayLiteral("GET /");
+static const QByteArray headerGet = QByteArrayLiteral("GET ");
static const QByteArray headerHTTP = QByteArrayLiteral("HTTP/1.1");
static const QByteArray headerHost = QByteArrayLiteral("Host: ");
static const QByteArray headerUpgrade = QByteArrayLiteral("Upgrade: websocket");
@@ -375,7 +380,7 @@ void QWebSocketServer::sendMessage(const QString& message)
sendFrame(Frame::TextFrame, message.toUtf8());
}
-void QWebSocketServer::sendFrame(QWebSocketServer::Frame::Opcode opcode, const QByteArray& data)
+void QWebSocketServer::sendFrame(Frame::Opcode opcode, const QByteArray& data)
{
QHash< QTcpSocket*, Connection >::const_iterator it = m_connections.constBegin();
while (it != m_connections.constEnd()) {
diff --git a/src/qwebsocketserver.h b/src/qwebsocketserver.h
index a660222..875cb58 100644
--- a/src/qwebsocketserver.h
+++ b/src/qwebsocketserver.h
@@ -53,6 +53,7 @@ class QWebSocketServer : public QObject
public:
explicit QWebSocketServer(QObject* parent = 0);
+ virtual ~QWebSocketServer();
bool listen(const QHostAddress& address = QHostAddress::LocalHost, quint16 port = 0);
void close();
@@ -99,6 +100,9 @@ protected:
bool hasConnection;
bool wasUpgraded;
};
+ virtual bool isValid(const HeaderData& connection);
+
+private:
struct Frame
{
enum State {
@@ -136,9 +140,6 @@ protected:
Frame currentFrame;
};
- virtual bool isValid(const HeaderData& connection);
-
-private:
void readHeaderData(QTcpSocket* socket, HeaderData& header);
void close(QTcpSocket* socket, const HeaderData& header);
void upgrade(QTcpSocket* socket, HeaderData& header);
diff --git a/src/webchannel.js b/src/webchannel.js
index 37e2314..3ee2b0c 100644
--- a/src/webchannel.js
+++ b/src/webchannel.js
@@ -44,7 +44,7 @@ var QWebChannel = function(baseUrl, initCallback)
var channel = this;
///TODO: use ssl?
var socketUrl = "ws://" + baseUrl;
- this.socket = new WebSocket(socketUrl);
+ this.socket = new WebSocket(socketUrl, "QWebChannel");
this.send = function(data)
{
channel.socket.send(JSON.stringify(data));