From: Konrad Rosenbaum Date: Sat, 9 Jul 2016 20:40:23 +0000 (+0200) Subject: conversion to session manager: stage 1 session manager as external process X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=a390fe0d9ddb66cfe1f876bed5f99c2a31e03b9a;p=web%2Fkonrad%2Fsmoke.git conversion to session manager: stage 1 session manager as external process --- diff --git a/Makefile b/Makefile index 5aee58f..784629c 100644 --- a/Makefile +++ b/Makefile @@ -101,8 +101,11 @@ server: wob client: wob taurus tzone wbase cd iface && $(QMAKE) $(QMAKEFLAGS) && $(MAKE) + cd cfglib && $(QMAKE) $(QMAKEFLAGS) && $(MAKE) + cd sesscli && $(QMAKE) $(QMAKEFLAGS) && $(MAKE) cd src && $(QMAKE) $(QMAKEFLAGS) && $(MAKE) cd mainapp && $(QMAKE) $(QMAKEFLAGS) && $(MAKE) + cd sessman && $(QMAKE) $(QMAKEFLAGS) && $(MAKE) cd plugins && $(QMAKE) $(QMAKEFLAGS) && $(MAKE) taurus: @@ -130,7 +133,7 @@ lrelease: cd src && $(LREL) smoke.pro cd iface && $(LREL) iface.pro for i in `find plugins -name '*.pro'` ; do $(LREL) $$i ; done - mkdir -p bin && cp src/smoke*.qm iface/smoke*.qm bin + mkdir -p bin && cp src/smoke*.qm iface/smoke*.qm sessman/*.qm bin cp `find plugins -name '*.qm'` bin -$(MAKE) -C www/translations LREL=$(LREL) XPAT=$(XPAT) lrelease diff --git a/basics.pri b/basics.pri index b014e21..ea115eb 100644 --- a/basics.pri +++ b/basics.pri @@ -7,7 +7,7 @@ DESTDIR = $$PWD/bin # this is default on Windows, we have it here to have all systems behave the same way CONFIG += hide_symbols #use PRL files (link info) -CONFIG += create_prl link_prl +CONFIG += create_prl link_prl #put debug symbols in separate file (on linux) CONFIG += separate_debug_info #enable C++-11 features diff --git a/iface/msinterface.cpp b/iface/msinterface.cpp index 5a3fd1e..ece3e4d 100644 --- a/iface/msinterface.cpp +++ b/iface/msinterface.cpp @@ -106,16 +106,24 @@ bool MSInterface::login(QString username,QString passwd) { m_uname=username;m_passwd=passwd; MTLogin lg=MTLogin::query(username,passwd,m_host,m_hostkey); - if(lg.stage()==lg.Error) + if(lg.stage()==lg.Error){ MBoxWrapper::warning(tr("Warning"),tr("Login failed: %1").arg(tr(lg.errorString().toLatin1()))); - else - setSessionId(lg.getsessionid()); + return false; + } if(lg.stage()!=lg.Success)return false; //schedule re-login before session times out int msecs=QDateTime::currentDateTime().msecsTo(QDateTime::fromTime_t(lg.getvalidtill())); msecs-=120000;//do it 2 min before session runs out if(msecs>100000)//but only if it does not become annoying... - QTimer::singleShot(msecs,this,SLOT(relogin())); + QTimer::singleShot(msecs,this,SIGNAL(needRelogin())); + // initialize + return loginSession(m_uname,lg.getsessionid()); +} + +bool MSInterface::loginSession (QString username, QString sessionid ) +{ + m_uname=username; + setSessionId(sessionid); //get rights and roles MTGetMyRights mrt=MTGetMyRights::asyncQuery(); MTGetMyRoles mrl=MTGetMyRoles::asyncQuery(); @@ -130,7 +138,7 @@ bool MSInterface::login(QString username,QString passwd) // qDebug()<<"have flags"< allRights()const{return userrights;} @@ -117,6 +120,8 @@ class MSIFACE_EXPORT MSInterface:public MInterface public slots: /**logs into the server, returns true on success*/ bool login(QString username,QString passwd); + /**initializes with a known session ID, returns true on success*/ + bool loginSession(QString username,QString sessionid); /**logs out of the server*/ void logout(); /**refreshes the login*/ @@ -128,6 +133,9 @@ class MSIFACE_EXPORT MSInterface:public MInterface /**force template store to update its templates*/ void updateTemplates(); + signals: + /// emitted when a re-login would be necessary + void needRelogin(); private: QString profileid,m_sessid,m_uname,m_passwd,m_host,m_hostkey; mutable QListuserrights; diff --git a/sesscli/scli.cpp b/sesscli/scli.cpp new file mode 100644 index 0000000..5bf5751 --- /dev/null +++ b/sesscli/scli.cpp @@ -0,0 +1,201 @@ +// +// C++ Implementation: Session Client +// +// Description: Session Client Class - connects to a session manager (or even starts one) +// and enables exchange of session data. +// +// +// Author: Konrad Rosenbaum , (C) 2016 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "scli.h" +#include "scrand.h" + +#include +#include +#include +#include +#include +#include +#include + +MSessionClient::MSessionClient() +{ + //check parameters for socket name + QString sms; + for(QString arg:qApp->arguments()) + if(arg.startsWith("-sms:")){ + sms=arg.mid(5); + break; + } + //none found: start session manager and wait for socket name + if(sms.isEmpty()){ + //generate reverse socket + QString key=QString::fromLatin1(MagicSmokeRandom::getRandomBytes(32).toHex()); + QLocalServer serv; + serv.setSocketOptions(QLocalServer::UserAccessOption); + serv.setMaxPendingConnections(1); + if(!serv.listen("magicsmoke-smr-"+key)){ + qDebug()<<"Ouch! Unable to create local socket server to communicate with Session Manager!"; + return; + } + //start process + qDebug()<<"Starting Session Manager..."; + if(!QProcess::startDetached(qApp->applicationDirPath()+"/magicsmoke-sessman", QStringList()<<"-slave:"+key)){ + qDebug()<<"Ouch! Unable to start session manager!"; + return; + } + //wait for connection + if(!serv.waitForNewConnection(10000)){ + qDebug()<<"Ouch! Session Manager did not respond!"; + return; + } + QLocalSocket *s=serv.nextPendingConnection(); + if(s==nullptr){ + qDebug()<<"Ouch! Session Manager did not connect back! Something is strange."; + return; + } + //read Session ID data + if(!s->waitForReadyRead(10000)){ + qDebug()<<"Ouch! Session Manager did not send a socket ID. Giving up."; + s->deleteLater(); + return; + } + sms=QString::fromLatin1(s->readLine().trimmed()); + s->deleteLater(); + serv.close(); + if(sms.size()!=64 || !QRegExp("[a-f0-9]+",Qt::CaseInsensitive).exactMatch(sms)){ + qDebug()<<"Ouch! Session Manager did not send a valid socket ID."<connectToServer("magicsmoke-sms-"+sms); + if(!s->waitForConnected(10000)){ + qDebug()<<"Ouch! Unable to connect to Session Manager!"; + s->deleteLater(); + return; + } + msocket=s; + connect(s,SIGNAL(readyRead()),this,SLOT(readSocket())); + connect(s,SIGNAL(disconnected()),this,SLOT(socketLost())); + connect(s,SIGNAL(error(QLocalSocket::LocalSocketError)),this,SLOT(socketLost())); + s->write("clientinit magicsmoke\n"); +} + +MSessionClient::~MSessionClient() +{ + if(msocket!=nullptr) + msocket->close(); +} + +bool MSessionClient::isConnected() const +{ + return msocket!=nullptr && msocket->isOpen(); +} + +QString MSessionClient::currentSessionId() const +{ + return msid; +} + +QString MSessionClient::currentProfileId() const +{ + return mprofile; +} + +QString MSessionClient::currentUsername() const +{ + return muser; +} + +bool MSessionClient::sessionIsAvailable() const +{ + return !msid.isEmpty(); +} + +bool MSessionClient::waitForSessionAvailable() +{ + if(!isConnected())return false; + if(!msid.isEmpty())return true; + //wait for signal + QEventLoop loop; + connect(this,SIGNAL(sessionIdChanged(QString)),&loop,SLOT(quit())); + connect(this,SIGNAL(managerLost()),&loop,SLOT(quit())); + loop.exec(); + return !msid.isEmpty(); +} + +QList< QPair< QString, QString > > MSessionClient::menuEntries() const +{ + if(!isConnected())return QList>(); + if(mmenu.isEmpty()){ + //get menu + QEventLoop loop; + connect(this,SIGNAL(menuChanged()),&loop,SLOT(quit())); + connect(this,SIGNAL(managerLost()),&loop,SLOT(quit())); + QTimer::singleShot(5000,&loop,SLOT(quit())); + msocket->write("getmenu\n"); + msocket->waitForBytesWritten(1000); + loop.exec(); + } + return mmenu; +} + +void MSessionClient::socketLost() +{ + qDebug()<<"Warning: Session Manager Socket lost!"; + if(msocket) + msocket->deleteLater(); + msocket=nullptr; + msid.clear(); + emit managerLost(); + emit sessionLost(); +} + +void MSessionClient::readSocket() +{ + while(msocket->canReadLine()){ + const QString line=QString::fromUtf8(msocket->readLine()).trimmed(); + const int pos=line.indexOf(' '); + const QString cmd=pos>0?line.left(pos):line; + const QString par=pos>0?line.mid(pos+1):QString(); + qDebug()<<"Received session manager command"<isOpen()) + msocket->write(QString("exec "+cmd+"\n").toUtf8()); +} + diff --git a/sesscli/scli.h b/sesscli/scli.h new file mode 100644 index 0000000..5a874ae --- /dev/null +++ b/sesscli/scli.h @@ -0,0 +1,74 @@ +// +// C++ Interface: Session Client +// +// Description: Session Client Class - connects to a session manager (or even starts one) +// and enables exchange of session data. +// +// +// Author: Konrad Rosenbaum , (C) 2016 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_SC_SCLI_H +#define MAGICSMOKE_SC_SCLI_H + +#include +#include +#include +#include + +#ifdef MAGICSMOKE_SESSCLI_LIB_BUILD +# define MAGICSMOKE_SESSCLI_EXPORT Q_DECL_EXPORT +#else +# define MAGICSMOKE_SESSCLI_EXPORT Q_DECL_IMPORT +#endif + +class MAGICSMOKE_SESSCLI_EXPORT MSessionClient:public QObject +{ + Q_OBJECT +public: + ///Initialize the session client, make sure it is connected to the Session Manager + MSessionClient(); + ///Disconnect the session client. + virtual ~MSessionClient(); + + ///Wait until a session is available or the Session Manager quits. + ///\returns true if a session is available, false on error + virtual bool waitForSessionAvailable(); + + ///Returns true if there currently is a session available. + virtual bool sessionIsAvailable()const; + ///Returns the session id. + virtual QString currentSessionId()const; + ///Returns the profile id. + virtual QString currentProfileId()const; + ///Returns the user name + virtual QString currentUsername()const; + ///Returns true if the client is connected to a manager. If false there is something wrong. + virtual bool isConnected()const; + + virtual QList> menuEntries()const; + +public slots: + void execServerCommand(QString); + +signals: + void sessionIdChanged(QString sessionId); + void sessionLost(); + void managerLost(); + void menuChanged(); + +private slots: + void socketLost(); + void readSocket(); + +private: + QLocalSocket*msocket=nullptr; + QString msid,mprofile,muser; + QList> mmenu; +}; + + +#endif diff --git a/sesscli/scrand.h b/sesscli/scrand.h new file mode 100644 index 0000000..873c074 --- /dev/null +++ b/sesscli/scrand.h @@ -0,0 +1,63 @@ +// +// C++ Interface: Random Number Retriever +// +// +// Author: Konrad Rosenbaum , (C) 2016 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_SC_RAND_H +#define MAGICSMOKE_SC_RAND_H + +#ifdef Q_OS_WIN32 +#include +#pragma comment(lib, "advapi32.lib") +#else +#include +#endif + +#include + +namespace MagicSmokeRandom { + +/// Get some crypto strength random bytes. May return less than requested. +inline QByteArray getRandomBytes(quint8 bytes) +{ + if(bytes==0)return QByteArray(); +#if defined(Q_OS_UNIX)||defined(Q_OS_LINUX)||defined(Q_OS_DARWIN) + //try urandom, then random + QFile fd("/dev/urandom"); + if(!fd.open(QIODevice::ReadOnly)){ + fd.setFileName("/dev/random"); + if(!fd.open(QIODevice::ReadOnly)){ + qDebug()<<"Unable to open /dev/{u}random - sorry."; + return QByteArray(); + } + } + QByteArray r=fd.read(bytes); + fd.close(); + return r; +#elif defined(Q_OS_WIN32) + BYTE data[256]; + HCRYPTPROV hCryptProv=0; + if (!::CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)){ + qDebug()<<"Error: Unable to acquire crypto context."; + return QByteArray(); + } + QByteArray r; + if(::CryptGenRandom(hCryptProv,bytes,data)){ + r=QByteArray((const char*)data,bytes); + }else{ + qDebug()<<"Error: Unable to get random numbers from OS."; + } + if(!::CryptReleaseContext(hProvider, 0)) + qDebug()<<"Warning: unable to release crypto context!"; + return r; +#endif +} + +} + +#endif diff --git a/sesscli/scrand.pri b/sesscli/scrand.pri new file mode 100644 index 0000000..9d95f27 --- /dev/null +++ b/sesscli/scrand.pri @@ -0,0 +1,5 @@ +# Random Stuff + +win32 { +#LIBS += -ladvapi32 +} diff --git a/sesscli/sesscli.pri b/sesscli/sesscli.pri new file mode 100644 index 0000000..fe0ec37 --- /dev/null +++ b/sesscli/sesscli.pri @@ -0,0 +1,5 @@ +#Include PRI for the session client library + +LIBS += -lmagicsmoke-sesscli +INCLUDEPATH += $$PWD/../sesscli +QT += network diff --git a/sesscli/sesscli.pro b/sesscli/sesscli.pro new file mode 100644 index 0000000..9f7e5d4 --- /dev/null +++ b/sesscli/sesscli.pro @@ -0,0 +1,27 @@ +#Project File for MagicSmoke Session Client Library +# (c) Konrad Rosenbaum, 2016 + +#basics +TEMPLATE = lib +VERSION = 0.1 +TARGET = magicsmoke-sesscli + +include(../basics.pri) +include(scrand.pri) + +#Localization +TRANSLATIONS = \ + smoke-sc_de.ts \ + smoke-sc_de_SAX.ts \ + smoke-sc_en.ts + +#main source files +SOURCES = scli.cpp +HEADERS = scli.h +INCLUDEPATH += . + +#make sure exports are ok +DEFINES += MAGICSMOKE_SESSCLI_LIB_BUILD=1 + +#make sure the correct Qt DLLs are used +QT += network diff --git a/sessman/icon.qrc b/sessman/icon.qrc new file mode 100644 index 0000000..9be79e1 --- /dev/null +++ b/sessman/icon.qrc @@ -0,0 +1,9 @@ + + + + + + ../src/images/icon.png + + diff --git a/src/dialogs/login.cpp b/sessman/login.cpp similarity index 85% rename from src/dialogs/login.cpp rename to sessman/login.cpp index b72330b..1566497 100644 --- a/src/dialogs/login.cpp +++ b/sessman/login.cpp @@ -10,15 +10,16 @@ // // -#include "main.h" +// #include "main.h" #include "login.h" #include "msinterface.h" -#include "overview.h" -#include "configdialog.h" +// #include "overview.h" +// #include "configdialog.h" #include #include #include +#include #include #include #include @@ -44,7 +45,7 @@ MLogin::MLogin() m->addAction(tr("&Exit"),this,SLOT(close())); m=mb->addMenu(tr("&Configure")); m->addAction(tr("&Configuration..."),this,SLOT(configwin())); - mb->addMenu(MApplication::helpMenu()); +// mb->addMenu(MApplication::helpMenu()); //create central widget QGridLayout*gl; @@ -110,14 +111,15 @@ void MLogin::loadProfile() void MLogin::startLogin() { + qDebug()<<"Logging in..."; //make it impossible for the user to interfere setEnabled(false); QProgressDialog pd(this); pd.setWindowTitle(tr("Login")); pd.setLabelText(tr("Logging in...")); pd.setCancelButton(nullptr); - pd.setRange(-30,100); - pd.setValue(-30); + pd.setRange(0,100); + pd.setValue(10); pd.setVisible(true); //create request object MSInterface *mw=new MSInterface(profiles->itemData(profiles->currentIndex()).toString()); @@ -128,7 +130,7 @@ void MLogin::startLogin() setEnabled(true); return; } - pd.setValue(-20); + pd.setValue(30); //start login request if(!mw->login(username->text(),password->text())){ QMessageBox::warning(this,tr("Warning"),tr("Unable to log in.")); @@ -136,33 +138,29 @@ void MLogin::startLogin() setEnabled(true); return; } - pd.setValue(-10); + pd.setValue(70); pd.setLabelText(tr("Getting data...")); //initialize - mw->initialize(); - pd.setValue(0); +// mw->initialize(); + pd.setValue(100); //open window - MOverview *mo=new MOverview(profiles->itemData(profiles->currentIndex()).toString(), - [&pd](int val,QString txt){ - pd.setValue(val); - pd.setLabelText(txt); - } - ); - mo->showRestored(); + emit loginSucceeded(); //make sure the application exits (only) after everything is cleaned up qApp->setQuitOnLastWindowClosed(false); - connect(mw,SIGNAL(destroyed(QObject*)),qApp,SLOT(quit())); hide(); + + // make sure relogin works + connect(mw,SIGNAL(needRelogin()),this,SLOT(relogin())); } void MLogin::configwin() { - MConfigDialog cd; - cd.exec(); - initProfiles(); - loadProfile(); +// MConfigDialog cd; +// cd.exec(); +// initProfiles(); +// loadProfile(); } void MLogin::resizeEvent(QResizeEvent* ) @@ -174,3 +172,13 @@ void MLogin::resizeEvent(QResizeEvent* ) resizer->move(rect().bottomRight() -resizer->rect().bottomRight()); resizer->raise(); } + +void MLogin::relogin() +{ + MSInterface*ms=MSInterface::instance(); + if(ms==nullptr)return; + if(ms->relogin()) + emit loginSucceeded(); + else + emit lostSession(); +} diff --git a/src/dialogs/login.h b/sessman/login.h similarity index 88% rename from src/dialogs/login.h rename to sessman/login.h index 04d9d66..1035fa2 100644 --- a/src/dialogs/login.h +++ b/sessman/login.h @@ -40,6 +40,13 @@ class MLogin:public QWidget void loadProfile(); void startLogin(); void configwin(); + + public slots: + void relogin(); + + signals: + void loginSucceeded(); + void lostSession(); }; #endif diff --git a/sessman/sessman.pro b/sessman/sessman.pro new file mode 100644 index 0000000..6b628ce --- /dev/null +++ b/sessman/sessman.pro @@ -0,0 +1,27 @@ +#Project File for MagicSmoke Session Manager +# (c) Konrad Rosenbaum, 2016 + +#basics +TEMPLATE = app +VERSION = 0.1 +TARGET = magicsmoke-sessman + +include(../basics.pri) +include(../sesscli/scrand.pri) +include(../iface/iface.pri) + +#Localization +TRANSLATIONS = \ + smoke-sm_de.ts \ + smoke-sm_de_SAX.ts \ + smoke-sm_en.ts + +#main source files +SOURCES = sman.cpp login.cpp +HEADERS = sman.h login.h +INCLUDEPATH += . +DEPENDPATH += $$INCLUDEPATH +RESOURCES += icon.qrc + +#make sure the correct Qt DLLs are used +QT += network gui widgets diff --git a/sessman/sman.cpp b/sessman/sman.cpp new file mode 100644 index 0000000..3c77193 --- /dev/null +++ b/sessman/sman.cpp @@ -0,0 +1,281 @@ +// +// C++ Implementation: Session Manager +// +// +// Author: Konrad Rosenbaum , (C) 2016 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + + +#include +#include +#include +#include +#include +#include +#include + +#include "sman.h" +#include "login.h" +#include "boxwrapper.h" + +#include "../sesscli/scrand.h" + +#include + +MSessionManager::MSessionManager ( QObject* parent ) : QObject ( parent ) +{ + // create socket + mkey=QString::fromLatin1(MagicSmokeRandom::getRandomBytes(32).toHex()); + if(mkey.size()<64){ + qDebug()<<"Error: unable to get a secure name for my server socket!"; + qApp->exit(1); + return; + } + QLocalServer *serv=new QLocalServer(this); + serv->setSocketOptions(QLocalServer::UserAccessOption); + if(!serv->listen("magicsmoke-sms-"+mkey)){ + qDebug()<<"Error: unable to open server socket -"<errorString(); + serv->deleteLater(); + return; + } + mserver=serv; + connect(mserver,SIGNAL(newConnection()),this,SLOT(newConnection())); + qDebug()<<"Server socket ready."; + + // check for slave socket + for(QString arg:qApp->arguments()){ + if(arg.startsWith("-slave:")){ + QString sk=arg.mid(7).trimmed(); + qDebug()<<"Attempting to communicate with slave"<setToolTip(tr("MagicSmoke Session Manager, waiting for login...")); + micon->show(); +} + +MSessionManager::~MSessionManager() +{ + if(mserver){ + mserver->close(); + mserver->deleteLater(); + mserver=nullptr; + } + MSInterface*ms=MSInterface::instance(); + if(ms){ + ms->logout(); + delete ms; + } + qApp->quit(); +} + + +bool MSessionManager::hasSession() const +{ + MSInterface*ms=MSInterface::instance(); + if(ms) + return !ms->sessionId().isEmpty(); + else + return false; +} + +QString MSessionManager::sessionId() const +{ + MSInterface*ms=MSInterface::instance(); + if(ms) + return ms->sessionId(); + else + return QString(); +} + +QString MSessionManager::username() const +{ + MSInterface*ms=MSInterface::instance(); + if(ms) + return ms->currentUser(); + else + return QString(); +} + +QString MSessionManager::profile() const +{ + MSInterface*ms=MSInterface::instance(); + if(ms) + return ms->profileId(); + else + return QString(); +} + +QString MSessionManager::profileName() const +{ + MSInterface*ms=MSInterface::instance(); + if(ms) + return ms->profileName(); + else + return QString(); +} + +bool MSessionManager::isActive() const +{ + return mserver!=nullptr && mserver->isListening(); +} + +void MSessionManager::newConnection() +{ + while(mserver->hasPendingConnections()){ + QLocalSocket*s=mserver->nextPendingConnection(); + if(!s)return; + s->setParent(this); + connect(s,SIGNAL(readyRead()),this,SLOT(readyRead())); + connect(s,SIGNAL(disconnected()),this,SLOT(socketClosed())); + connect(s,SIGNAL(error(QLocalSocket::LocalSocketError)),this,SLOT(socketClosed())); + connect(s,SIGNAL(destroyed(QObject*)),this,SLOT(socketLost(QObject*))); + mconnections.append(s); + } +} + +void MSessionManager::readyRead() +{ + //find socket + QLocalSocket*s=qobject_cast(sender()); + if(s==nullptr){ + qDebug()<<"Warning: readyRead called without socket caller."; + return; + } + if(!mconnections.contains(s)){ + qDebug()<<"Warning: readyRead called from unknown socket."; + return; + } + //get command + while(s->canReadLine()){ + const QString line=QString::fromUtf8(s->readLine().trimmed()); + if(line.isEmpty())continue; + const int pos=line.indexOf(' '); + const QString cmd=pos>0?line.left(pos):line; + const QString par=pos>0?line.mid(pos+1):QString(); + qDebug()<<"Received session client request"<deleteLater(); + return; + } + sendSessionInfo(s); + }else if(cmd=="getmenu") + sendMenu(s); + else if(cmd=="exec") + execCmd(par); + else + qDebug()<<"Warning: unknown client command"<(o); + if(s==nullptr){ + qDebug()<<"Warning: socketLost called without socket caller."; + return; + } + if(!mconnections.contains(s)){ + qDebug()<<"Warning: socketLost called from unknown socket."; + return; + } + //remove from list + mconnections.removeAll(s); + //was this the last? + if(mconnections.isEmpty()){ + qDebug()<<"This was the last connection. Quitting now."; + deleteLater(); + } +} + +void MSessionManager::sendMenu(QLocalSocket*s) +{ + s->write("newmenu\n"); + //TODO: send "menu command entry-text" for each entry + s->write("endmenu\n"); +} + +void MSessionManager::execCmd ( QString cmd) +{ + qDebug()<<"I wish I knew how to execute"<setProcessChannelMode(QProcess::ForwardedChannels); + p->start(qApp->applicationDirPath()+"/magicsmoke",QStringList()<<"-sms:"+mkey); +} + +void MSessionManager::loginSucceeded() +{ + micon->setToolTip(tr("MagicSmoke Session Manager, logged in as %1 at %2.").arg(username()).arg(profileName())); + if(mconnections.count()>0) + sendNewSessionId(); + else + execCmd("msmoke"); +} + +void MSessionManager::sendNewSessionId() +{ + qDebug()<<"Sending session data..."; + for(QLocalSocket*s:mconnections) + sendSessionInfo(s); +} + +void MSessionManager::sendSessionInfo ( QLocalSocket* s) +{ + if(sessionId().isEmpty())return; + s->write(QString("profile "+profile()+"\n").toUtf8()); + s->write(QString("user "+username()+"\n").toUtf8()); + s->write(QString("sid "+sessionId()+"\n").toLatin1()); + s->flush(); +} + +void MSessionManager::loginLost() +{ + for(QLocalSocket*s:mconnections) + s->write("closed\n"); +} + + +int main(int ac,char**av) +{ + QApplication app(ac,av); + //locate settings + app.setOrganizationName("MagicSmoke"); + app.setApplicationName("MagicSmoke2"); + + //set icon + app.setWindowIcon(QIcon(":/icon.png")); + + MSInterface::setAppDataDir("$BASE/.magicSmoke2"); + + MBoxWrapper::setWarning([](QString title,QString text){QMessageBox::warning(nullptr,title,text);}); + + + MSessionManager *sm=new MSessionManager(&app); + MLogin lw; + lw.connect(&lw,SIGNAL(loginSucceeded()),sm,SLOT(loginSucceeded())); + lw.connect(&lw,SIGNAL(lostSession()),sm,SLOT(loginLost())); + lw.show(); + + return app.exec(); +} diff --git a/sessman/sman.h b/sessman/sman.h new file mode 100644 index 0000000..a0cafab --- /dev/null +++ b/sessman/sman.h @@ -0,0 +1,59 @@ +// +// C++ Interface: Session Client +// +// Description: Session Client Class - connects to a session manager (or even starts one) +// and enables exchange of session data. +// +// +// Author: Konrad Rosenbaum , (C) 2016 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_SC_SCLI_H +#define MAGICSMOKE_SC_SCLI_H + +#include +#include + +class QLocalServer; +class QLocalSocket; +class QSystemTrayIcon; + +class MSessionManager:public QObject +{ + Q_OBJECT +public: + explicit MSessionManager ( QObject* parent = 0 ); + virtual ~MSessionManager(); + + virtual bool isActive()const; + virtual bool hasSession()const; + virtual QString sessionId()const; + virtual QString username()const; + virtual QString profile()const; + virtual QString profileName()const; + +private slots: + void newConnection(); + void readyRead(); + void socketClosed(); + void socketLost(QObject*); + + void loginSucceeded(); + void sendNewSessionId(); + void loginLost(); +private: + QLocalServer*mserver=nullptr; + QListmconnections; + QString mkey; + QSystemTrayIcon*micon; + + void sendMenu(QLocalSocket*); + void execCmd(QString); + void sendSessionInfo(QLocalSocket*); +}; + + +#endif diff --git a/src/dialogs/dialogs.pri b/src/dialogs/dialogs.pri index 52975ea..ff60fff 100644 --- a/src/dialogs/dialogs.pri +++ b/src/dialogs/dialogs.pri @@ -3,7 +3,6 @@ HEADERS += \ dialogs/eventedit.h \ dialogs/eventsummary.h \ dialogs/orderwin.h \ - dialogs/login.h \ dialogs/shipping.h \ dialogs/customerdlg.h \ dialogs/checkdlg.h \ @@ -21,7 +20,6 @@ SOURCES += \ dialogs/eventedit.cpp \ dialogs/eventsummary.cpp \ dialogs/orderwin.cpp \ - dialogs/login.cpp \ dialogs/shipping.cpp \ dialogs/customerdlg.cpp \ dialogs/checkdlg.cpp \ @@ -35,4 +33,4 @@ SOURCES += \ RESOURCES += dialogs/dialogfiles.qrc -INCLUDEPATH += ./dialogs \ No newline at end of file +INCLUDEPATH += ./dialogs diff --git a/src/libs.pri b/src/libs.pri index 8e1aded..09bd6b8 100644 --- a/src/libs.pri +++ b/src/libs.pri @@ -9,6 +9,9 @@ include ($$PWD/../iface/iface.pri) # Aurora Updater library include($$PWD/../taurus/aurora.pri) +# Session Client library +include($$PWD/../sesscli/sesscli.pri) + #make sure the correct Qt DLLs are used QT += xml network script scripttools QT += widgets printsupport diff --git a/src/main.cpp b/src/main.cpp index f92e056..eb272f8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,12 +38,15 @@ #include "hmac.h" #include "keygen.h" #include "main.h" -#include "login.h" +// #include "login.h" #include "msinterface.h" #include #include "misc.h" #include #include "boxwrapper.h" +#include "overview.h" + +#include QString choseLanguage(bool warn) { @@ -474,10 +477,22 @@ int MApplication::realmain(int argc,char**argv) //init app.initialize(); + MSessionClient sc; + sc.connect(&sc,SIGNAL(sessionLost()),&app,SLOT(quit())); + sc.connect(&sc,SIGNAL(managerLost()),&app,SLOT(quit())); + if(sc.waitForSessionAvailable()){ + MSInterface*ms=new MSInterface(sc.currentProfileId()); + ms->loginSession(sc.currentUsername(), sc.currentSessionId()); + MOverview *mo=new MOverview(sc.currentProfileId()); + mo->showRestored(); + }else{ + qDebug()<<"Unable to get session. Giving up."; + return 1; + } //open main window - MLogin mmw; - mmw.show(); + //MLogin mmw; + //mmw.show(); return app.exec(); } diff --git a/src/mwin/overview.cpp b/src/mwin/overview.cpp index 3fa34c1..237b672 100644 --- a/src/mwin/overview.cpp +++ b/src/mwin/overview.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -66,7 +67,7 @@ #include "MTBackup" #include "MTGetAllUsers" -MOverview::MOverview(QString pk,std::functioninitUpdate) +MOverview::MOverview(QString pk) :MTabWin(pk),entrancetab(nullptr) { rtimer.setInterval(QSettings().value("profiles/"+pk+"/refresh",300).toInt()*1000); @@ -139,19 +140,26 @@ MOverview::MOverview(QString pk,std::functioninitUpdate) ->setEnabled(req->hasRight(req->RBackup)); m2=m->addMenu(tr("&Configuration")); - m2->addAction(tr("&Change Language..."),this,SLOT(changeLang())); + m2->addAction(tr("&Change Language..."),this,SLOT(changeLang())); m2->addAction(tr("&Auto-Refresh settings..."),this,SLOT(setRefresh())); m2->addAction(tr("&Server Access settings..."),this,SLOT(webSettings())); m2->addAction(tr("&Display settings..."),this,SLOT(displaySettings())); m2->addAction(tr("&Label Printing settings..."),this,SLOT(labelSettings())); - m2->addAction(tr("&OpenOffice settings..."),this,SLOT(openOfficeSettings())); - m2->addAction(tr("&Barcode Scanner settings..."),this,SLOT(barcodeSettings())); + m2->addAction(tr("&OpenOffice settings..."),this,SLOT(openOfficeSettings())); + m2->addAction(tr("&Barcode Scanner settings..."),this,SLOT(barcodeSettings())); //make sure webrequest knows its settings webSettings(false); //Event tab - if(initUpdate)initUpdate(10,tr("Getting events...")); + QProgressDialog pd(this); + pd.setWindowTitle(tr("Login")); + pd.setLabelText(tr("Getting data...")); + pd.setCancelButton(nullptr); + pd.setRange(0,100); + pd.setValue(10); + pd.setVisible(true); + pd.setValue(10);pd.setLabelText(tr("Getting events...")); eventtab=new MEventsTab(pk); addTab(eventtab,tr("Events"),eventtab->menu()); @@ -167,13 +175,13 @@ MOverview::MOverview(QString pk,std::functioninitUpdate) connect(carttab,SIGNAL(requestFocus()), this,SLOT(switchToCartTab())); //Order List Tab - if(initUpdate)initUpdate(40,tr("Getting Orders...")); + pd.setValue(40);pd.setLabelText(tr("Getting Orders...")); ordertab=new MOrdersTab(pk); addTab(ordertab, tr("Order List"), ordertab->menu()); connect(ordertab,SIGNAL(selectEventIds(QList&)), eventtab,SLOT(selectEventIds(QList&)), Qt::DirectConnection); //Entrance Control Tab - if(initUpdate)initUpdate(70,tr("Getting Entrance Data...")); + pd.setValue(70);pd.setLabelText(tr("Getting Entrance Data...")); entrancetab=new MEntranceTab(pk); addTab(entrancetab,tr("Entrance"),entrancetab->menu()); connect(entrancetab,SIGNAL(askForFocus(QWidget*)),this,SLOT(setCurrentTab(QWidget*))); diff --git a/src/mwin/overview.h b/src/mwin/overview.h index f845e2b..512504b 100644 --- a/src/mwin/overview.h +++ b/src/mwin/overview.h @@ -21,8 +21,6 @@ #include "tabwin.h" -#include - class QAction; class QCheckBox; class QComboBox; @@ -49,7 +47,7 @@ class MOverview:public MTabWin Q_OBJECT public: /**construct the window with web-request/session handler and QSettings-key for current profile*/ - MOverview(QString,std::functioninitUpdate=nullptr); + MOverview(QString); ~MOverview(); protected: /**handle closing the window: close the session too*/