Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions qmlui/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,13 @@ void App::startup()
rootContext()->setContextProperty("networkManager", m_networkManager);

connect(m_networkManager, &NetworkManager::clientAccessRequest, this, &App::slotClientAccessRequest);
connect(m_networkManager, &NetworkManager::clientAccessRequestCancelled,
this, &App::slotClientAccessRequestCancelled);
connect(m_networkManager, &NetworkManager::clientAutoAuthorized, this,
[this](const QString &sessionId)
{
m_networkManager->sendWorkspaceToClient(sessionId, fileName());
});
connect(m_networkManager, &NetworkManager::accessMaskChanged, this, &App::setAccessMask);
connect(m_networkManager, &NetworkManager::requestProjectLoad, this, &App::slotLoadDocFromMemory);
connect(m_networkManager, &NetworkManager::requestProjectClear, this, &App::slotClearDocFromNetwork);
Expand Down Expand Up @@ -483,13 +490,21 @@ void App::slotClosing()
//QTimer::singleShot(2000, []() { QCoreApplication::exit(0); });
}

void App::slotClientAccessRequest(QString name)
void App::slotClientAccessRequest(QString sessionId, QString name,
QString peerAddress, quint16 peerPort)
{
QMetaObject::invokeMethod(rootObject(), "openAccessRequest",
Q_ARG(QVariant, name));
Q_ARG(QVariant, sessionId), Q_ARG(QVariant, name),
Q_ARG(QVariant, peerAddress), Q_ARG(QVariant, peerPort));
}

void App::slotClientAccessRequestCancelled(QString sessionId)
{
QMetaObject::invokeMethod(rootObject(), "closeAccessRequest",
Q_ARG(QVariant, sessionId));
}

void App::slotClientProjectRequest(QString name)
void App::slotClientProjectRequest(QString sessionId)
{
/* The workspace is served from a file. If the current project has never
* been saved, or has pending changes, dump it to a temporary file first,
Expand All @@ -501,15 +516,15 @@ void App::slotClientProjectRequest(QString name)
fileName = QString("%1/%2").arg(QDir::tempPath()).arg("qlcplus_netproject.qxw");
if (saveXML(fileName, true) != QFile::NoError)
{
qWarning() << Q_FUNC_INFO << "Unable to serve the project to" << name;
qWarning() << Q_FUNC_INFO << "Unable to serve the project to" << sessionId;
return;
}
}

qDebug() << Q_FUNC_INFO << "Serving" << fileName << "to" << name;
qDebug() << Q_FUNC_INFO << "Serving" << fileName << "to session" << sessionId;

if (m_networkManager->sendWorkspaceToClient(name, fileName) == false)
qWarning() << Q_FUNC_INFO << "Failed to send the workspace to" << name;
if (m_networkManager->sendWorkspaceToClient(sessionId, fileName) == false)
qWarning() << Q_FUNC_INFO << "Failed to send the workspace to session" << sessionId;
}

void App::slotAccessMaskChanged(int mask)
Expand Down
6 changes: 4 additions & 2 deletions qmlui/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,12 @@ protected slots:
void slotSceneGraphInitialized();
void slotScreenChanged(QScreen *screen);
void slotClosing();
void slotClientAccessRequest(QString name);
void slotClientAccessRequest(QString sessionId, QString name,
QString peerAddress, quint16 peerPort);
void slotClientAccessRequestCancelled(QString sessionId);

/** Serve the current workspace to a client that requested it */
void slotClientProjectRequest(QString name);
void slotClientProjectRequest(QString sessionId);

void slotAccessMaskChanged(int mask);
void slotDocAutosave();
Expand Down
13 changes: 12 additions & 1 deletion qmlui/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ int main(int argc, char *argv[])
"Enable the native network server");
parser.addOption(remoteOption);

QCommandLineOption allowAllNativeOption(QStringList() << "sa" << "server-allow-all",
"Automatically grant full access to every native TCP client (unsafe on untrusted networks)");
parser.addOption(allowAllNativeOption);

parser.process(app);

bool enableWebAccess = parser.isSet(webAccessOption)
Expand All @@ -138,7 +142,8 @@ int main(int argc, char *argv[])
bool enableWebAuth = parser.isSet(webAuthOption);
int webAccessPort = parser.value(webPortOption).toInt();
QString webAccessPasswordFile = parser.value(webAuthFileOption);
bool enableNativeServer = parser.isSet(remoteOption);
bool allowAllNative = parser.isSet(allowAllNativeOption);
bool enableNativeServer = parser.isSet(remoteOption) || allowAllNative;

#if !defined Q_OS_ANDROID
// 3D enablement
Expand Down Expand Up @@ -225,6 +230,12 @@ int main(int argc, char *argv[])
if ((enableWebAccess || enableNativeServer) && qlcplusApp.networkManager() != nullptr)
{
NetworkManager *netMgr = qlcplusApp.networkManager();
netMgr->setAllowAllNative(allowAllNative);
if (allowAllNative)
{
qCritical().noquote()
<< "WARNING: --server-allow-all grants full QLC+ control to every native client, including LAN clients. Keep TCP port 9998 firewalled or use only a trusted network.";
}
int forcedTypes = NetworkManager::NoServer;

if (enableWebAccess)
Expand Down
12 changes: 11 additions & 1 deletion qmlui/qml/MainView.qml
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,22 @@ Rectangle
dimScreen.visible = enable
}

function openAccessRequest(clientName)
function openAccessRequest(sessionId, clientName, peerAddress, peerPort)
{
clientAccessPopup.deciding = false
clientAccessPopup.sessionId = sessionId
clientAccessPopup.clientName = clientName
clientAccessPopup.peerAddress = peerAddress
clientAccessPopup.peerPort = peerPort
clientAccessPopup.open()
}

function closeAccessRequest(sessionId)
{
if (clientAccessPopup.sessionId === sessionId)
clientAccessPopup.close()
}

function saveProject()
{
actionsMenu.handleSaveAction()
Expand Down
29 changes: 23 additions & 6 deletions qmlui/qml/popup/PopupNetworkConnect.qml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,17 @@ CustomPopupDialog
width: mainView.width / 3
title: qsTr("Client access request")

property string sessionId: ""
property string clientName: ""
property string peerAddress: ""
property int peerPort: 0
property bool deciding: false

onClosed:
{
if (!deciding && sessionId !== "")
networkManager.setClientAccess(sessionId, false, 0)
}

contentItem:
GridLayout
Expand All @@ -44,9 +54,12 @@ CustomPopupDialog
Layout.columnSpan: 2
Layout.fillWidth: true
//wrapText: true
height: UISettings.listItemHeight * 3
label: qsTr("A client with name <") + clientName +
qsTr(">\nis requesting access to this session.\nAccess level:")
height: UISettings.listItemHeight * 5
label: qsTr("A client is requesting access to this session.") +
"\n" + qsTr("Name: ") + clientName +
"\n" + qsTr("Peer: ") + peerAddress + ":" + peerPort +
"\n" + qsTr("Session ID: ") + sessionId +
"\n" + qsTr("Access level:")
}

// row 2
Expand Down Expand Up @@ -190,8 +203,10 @@ CustomPopupDialog
label: qsTr("Deny")
onClicked:
{
networkManager.setClientAccess(clientName, false, 0)
var deniedSession = sessionId
deciding = true
popupRoot.close()
networkManager.setClientAccess(deniedSession, false, 0)
}
}

Expand All @@ -217,9 +232,11 @@ CustomPopupDialog
if (ioCheck.checked)
access |= App.AC_InputOutput

networkManager.setClientAccess(clientName, true, access)
networkManager.sendWorkspaceToClient(clientName, qlcplus.fileName())
var allowedSession = sessionId
deciding = true
popupRoot.close()
if (networkManager.setClientAccess(allowedSession, true, access))
networkManager.sendWorkspaceToClient(allowedSession, qlcplus.fileName())
}
}
}
Expand Down
Loading
Loading