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:
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
# 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
{
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();
// qDebug()<<"have flags"<<userflags;
userroles=mrl.getrole();
// for(int i=0;i<userroles.size();i++)qDebug("have role %s",userroles[i].toLatin1().data());
-
+
return true;
}
QString path=parent.path();
if(path==QString() || path.endsWith('/'))return parent;
parent.setPath(path.left(path.lastIndexOf('/')+1));
+ return parent;
+}
+
+QString MSInterface::profileName() const
+{
+ return QSettings().value("profiles/"+profileid+"/name").toString();
}
/**returns the profile ID of this session*/
QString profileId()const{return profileid;}
+
+ ///returns the human readable name of the profile
+ QString profileName()const;
///return all rights of the current user
QList<Right> allRights()const{return userrights;}
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*/
/**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 QList<Right>userrights;
--- /dev/null
+//
+// 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 <konrad@silmor.de>, (C) 2016
+//
+// Copyright: See README/COPYING.GPL files that come with this distribution
+//
+//
+
+#include "scli.h"
+#include "scrand.h"
+
+#include <QCoreApplication>
+#include <QEventLoop>
+#include <QLocalServer>
+#include <QProcess>
+#include <QRegExp>
+#include <QStringList>
+#include <QTimer>
+
+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."<<sms;
+ return;
+ }
+ qDebug()<<"Got session socket ID from Session Manager.";
+ }
+ //open socket
+ QLocalSocket *s=new QLocalSocket(this);
+ s->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<QPair<QString,QString>>();
+ 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"<<cmd<<"with param"<<(cmd!="sid"?par:"(censored)");
+ if(cmd=="sid"){
+ msid=par;
+ qDebug()<<"Received new Session ID.";
+ emit sessionIdChanged(msid);
+ }else if(cmd=="profile"){
+ qDebug()<<"Using session profile"<<par;
+ mprofile=par;
+ }else if(cmd=="user"){
+ qDebug()<<"Username"<<par;
+ muser=par;
+ }else if(cmd=="newmenu"){
+ mmenu.clear();
+ }else if(cmd=="menu"){
+ }else if(cmd=="endmenu"){
+ qDebug()<<"New Menu received from Session Manager!";
+ emit menuChanged();
+ }else if(cmd=="closed"){
+ msid.clear();
+ qDebug()<<"Warning: Session lost!";
+ emit sessionLost();
+ }else if(cmd=="quit"){
+ socketLost();
+ }else
+ qDebug()<<"Warning: unknown session manager signal"<<cmd<<"encountered. Ignoring it.";
+ }
+}
+
+void MSessionClient::execServerCommand ( QString cmd)
+{
+ if(msocket && msocket->isOpen())
+ msocket->write(QString("exec "+cmd+"\n").toUtf8());
+}
+
--- /dev/null
+//
+// 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 <konrad@silmor.de>, (C) 2016
+//
+// Copyright: See README/COPYING.GPL files that come with this distribution
+//
+//
+
+#ifndef MAGICSMOKE_SC_SCLI_H
+#define MAGICSMOKE_SC_SCLI_H
+
+#include <QObject>
+#include <QList>
+#include <QPair>
+#include <QLocalSocket>
+
+#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<QPair<QString,QString>> 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<QPair<QString,QString>> mmenu;
+};
+
+
+#endif
--- /dev/null
+//
+// C++ Interface: Random Number Retriever
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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 <windows.h>
+#pragma comment(lib, "advapi32.lib")
+#else
+#include <QFile>
+#endif
+
+#include <QByteArray>
+
+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
--- /dev/null
+# Random Stuff
+
+win32 {
+#LIBS += -ladvapi32
+}
--- /dev/null
+#Include PRI for the session client library
+
+LIBS += -lmagicsmoke-sesscli
+INCLUDEPATH += $$PWD/../sesscli
+QT += network
--- /dev/null
+#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
--- /dev/null
+<!DOCTYPE RCC>
+<!-- Copyright: (c) Konrad Rosenbaum, 2007-2011
+See COPYING.GPL for details. -->
+<RCC version="1.0">
+ <qresource>
+ <!-- main app icon -->
+ <file alias="icon.png">../src/images/icon.png</file>
+ </qresource>
+</RCC>
//
//
-#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 <QApplication>
#include <QByteArray>
#include <QComboBox>
+#include <QDebug>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QLabel>
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;
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());
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."));
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* )
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();
+}
void loadProfile();
void startLogin();
void configwin();
+
+ public slots:
+ void relogin();
+
+ signals:
+ void loginSucceeded();
+ void lostSession();
};
#endif
--- /dev/null
+#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
--- /dev/null
+//
+// C++ Implementation: Session Manager
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2016
+//
+// Copyright: See README/COPYING.GPL files that come with this distribution
+//
+//
+
+
+#include <QApplication>
+#include <QDebug>
+#include <QLocalServer>
+#include <QLocalSocket>
+#include <QMessageBox>
+#include <QSystemTrayIcon>
+#include <QProcess>
+
+#include "sman.h"
+#include "login.h"
+#include "boxwrapper.h"
+
+#include "../sesscli/scrand.h"
+
+#include <msinterface.h>
+
+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 -"<<serv->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"<<sk;
+ QLocalSocket ls;
+ ls.connectToServer("magicsmoke-smr-"+sk);
+ if(!ls.waitForConnected(5000)){
+ qDebug()<<"Unable to connect to slave.";
+ continue;
+ }
+ ls.write(mkey.toLatin1()+"\n");
+ ls.waitForBytesWritten(1000);
+ ls.close();
+ }
+ }
+
+ //create systray icon
+ micon=new QSystemTrayIcon(QIcon(":/icon.png"),this);
+ micon->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<QLocalSocket*>(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"<<cmd<<"with param"<<par;
+ if(cmd=="clientinit"){
+ if(par!="magicsmoke"){
+ qDebug()<<"Warning: clientinit from non magicsmoke! Very strange.";
+ s->deleteLater();
+ return;
+ }
+ sendSessionInfo(s);
+ }else if(cmd=="getmenu")
+ sendMenu(s);
+ else if(cmd=="exec")
+ execCmd(par);
+ else
+ qDebug()<<"Warning: unknown client command"<<cmd;
+ }
+}
+
+void MSessionManager::socketClosed()
+{
+ socketLost(sender());
+}
+
+void MSessionManager::socketLost ( QObject* o)
+{
+ QLocalSocket*s=qobject_cast<QLocalSocket*>(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"<<cmd;
+ QProcess *p=new QProcess;
+ p->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();
+}
--- /dev/null
+//
+// 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 <konrad@silmor.de>, (C) 2016
+//
+// Copyright: See README/COPYING.GPL files that come with this distribution
+//
+//
+
+#ifndef MAGICSMOKE_SC_SCLI_H
+#define MAGICSMOKE_SC_SCLI_H
+
+#include <QObject>
+#include <QList>
+
+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;
+ QList<QLocalSocket*>mconnections;
+ QString mkey;
+ QSystemTrayIcon*micon;
+
+ void sendMenu(QLocalSocket*);
+ void execCmd(QString);
+ void sendSessionInfo(QLocalSocket*);
+};
+
+
+#endif
dialogs/eventedit.h \
dialogs/eventsummary.h \
dialogs/orderwin.h \
- dialogs/login.h \
dialogs/shipping.h \
dialogs/customerdlg.h \
dialogs/checkdlg.h \
dialogs/eventedit.cpp \
dialogs/eventsummary.cpp \
dialogs/orderwin.cpp \
- dialogs/login.cpp \
dialogs/shipping.cpp \
dialogs/customerdlg.cpp \
dialogs/checkdlg.cpp \
RESOURCES += dialogs/dialogfiles.qrc
-INCLUDEPATH += ./dialogs
\ No newline at end of file
+INCLUDEPATH += ./dialogs
# 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
#include "hmac.h"
#include "keygen.h"
#include "main.h"
-#include "login.h"
+// #include "login.h"
#include "msinterface.h"
#include <ELAM/Engine>
#include "misc.h"
#include <Aurora>
#include "boxwrapper.h"
+#include "overview.h"
+
+#include <scli.h>
QString choseLanguage(bool warn)
{
//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();
}
#include <QMenu>
#include <QMenuBar>
#include <QMessageBox>
+#include <QProgressDialog>
#include <QPushButton>
#include <QSettings>
#include <QSpinBox>
#include "MTBackup"
#include "MTGetAllUsers"
-MOverview::MOverview(QString pk,std::function<void(int,QString)>initUpdate)
+MOverview::MOverview(QString pk)
:MTabWin(pk),entrancetab(nullptr)
{
rtimer.setInterval(QSettings().value("profiles/"+pk+"/refresh",300).toInt()*1000);
->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());
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<int>&)), eventtab,SLOT(selectEventIds(QList<int>&)), 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*)));
#include "tabwin.h"
-#include <functional>
-
class QAction;
class QCheckBox;
class QComboBox;
Q_OBJECT
public:
/**construct the window with web-request/session handler and QSettings-key for current profile*/
- MOverview(QString,std::function<void(int,QString)>initUpdate=nullptr);
+ MOverview(QString);
~MOverview();
protected:
/**handle closing the window: close the session too*/