diff options
author | Sebastian | 2010-05-12 19:42:27 +0200 |
---|---|---|
committer | Sebastian | 2010-05-12 19:42:27 +0200 |
commit | ce3329047d378a14006ce74ec273ac59e3375303 (patch) | |
tree | 782430f270b4c7aca1b35d5b7813518e3797c555 /src/util | |
download | pvs-ce3329047d378a14006ce74ec273ac59e3375303.tar.gz pvs-ce3329047d378a14006ce74ec273ac59e3375303.tar.xz pvs-ce3329047d378a14006ce74ec273ac59e3375303.zip |
initial import of latest svn version
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/CertManager.cpp | 87 | ||||
-rw-r--r-- | src/util/CertManager.h | 30 | ||||
-rw-r--r-- | src/util/TextFile.cpp | 39 | ||||
-rw-r--r-- | src/util/TextFile.h | 26 | ||||
-rw-r--r-- | src/util/clientGUIUtils.cpp | 144 | ||||
-rw-r--r-- | src/util/clientGUIUtils.h | 39 | ||||
-rw-r--r-- | src/util/consoleLogger.cpp | 355 | ||||
-rw-r--r-- | src/util/consoleLogger.h | 273 | ||||
-rw-r--r-- | src/util/dispatcher.h | 210 | ||||
-rw-r--r-- | src/util/pvsSettingsManager.cpp | 185 | ||||
-rw-r--r-- | src/util/pvsSettingsManager.h | 50 | ||||
-rw-r--r-- | src/util/serviceDiscoveryUtil.cpp | 65 | ||||
-rw-r--r-- | src/util/serviceDiscoveryUtil.h | 19 | ||||
-rw-r--r-- | src/util/timeUtil.cpp | 42 | ||||
-rw-r--r-- | src/util/timeUtil.h | 34 | ||||
-rw-r--r-- | src/util/util.cpp | 416 | ||||
-rw-r--r-- | src/util/util.h | 59 | ||||
-rw-r--r-- | src/util/vncClientThread.cpp | 249 | ||||
-rw-r--r-- | src/util/vncClientThread.h | 114 |
19 files changed, 2436 insertions, 0 deletions
diff --git a/src/util/CertManager.cpp b/src/util/CertManager.cpp new file mode 100644 index 0000000..99d2438 --- /dev/null +++ b/src/util/CertManager.cpp @@ -0,0 +1,87 @@ +/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/util/CertManager.cpp
+# - Manage SSL certificates
+# - provide access by name
+# -----------------------------------------------------------------------------
+*/
+
+#include "CertManager.h"
+#include "util.h"
+#include <QMap>
+#include <QFileInfo>
+#include <cstdlib>
+
+namespace CertManager
+{
+ static QMap<QString, QSslCertificate> _certs;
+ static QMap<QString, QSslKey> _keys;
+
+ void generateFiles(QString key, QString cert);
+
+ QSslKey getPrivateKey(QString name) {
+ if (_keys.contains(name)) return _keys[name];
+ QString cert = getPolicyFilePath(name);
+ QString key = cert;
+ key.append(".rsa");
+ cert.append(".crt");
+ //
+ QFileInfo keyfile(key);
+ QFileInfo certfile(cert);
+ if (keyfile.exists() && certfile.exists())
+ { // It wouldn't make sense to have one without the other
+ if (getCertificate(name).isNull()) return QSslKey();
+ QFile f(key);
+ f.open(QFile::ReadOnly);
+ QSslKey k = QSslKey(&f, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ _keys.insert(name, k);
+ return k;
+ }
+ generateFiles(key, cert);
+ keyfile = QFileInfo(key);
+ if (!keyfile.exists() || getCertificate(name).isNull()) return QSslKey();
+ QFile f(key);
+ f.open(QFile::ReadOnly);
+ QSslKey k = QSslKey(&f, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ if (!k.isNull()) _keys.insert(name, k);
+ return k;
+ }
+
+ QSslCertificate getCertificate(QString name) {
+ if (_certs.contains(name)) return _certs[name];
+ QString cert = getPolicyFilePath(name);
+ cert.append(".crt");
+ //
+ QFileInfo certfile(cert);
+ if (certfile.exists())
+ {
+ QList<QSslCertificate> certlist = QSslCertificate::fromPath(cert);
+ if (certlist.empty()) return QSslCertificate();
+ QSslCertificate c = certlist.first();
+ if (!c.isNull()) _certs.insert(name, c);
+ return c;
+ }
+ return QSslCertificate();
+ }
+
+ void generateFiles(QString key, QString cert)
+ {
+ char tmp[1000];
+ unlink(key.toLocal8Bit().data());
+ unlink(cert.toLocal8Bit().data());
+ snprintf(tmp, 1000, "openssl req -x509 -nodes -days 3650 -newkey rsa:1024 -subj '/C=DE/ST=BaWue/L=Freiburg/CN=openslx.org' -keyout \"%s\" -out \"%s\"",
+ key.toLocal8Bit().data(), cert.toLocal8Bit().data());
+ system(tmp);
+ snprintf(tmp, 1000, "chmod 0600 \"%s\" \"%s\"", key.toLocal8Bit().data(), cert.toLocal8Bit().data());
+ system(tmp);
+ }
+}
diff --git a/src/util/CertManager.h b/src/util/CertManager.h new file mode 100644 index 0000000..8caab8b --- /dev/null +++ b/src/util/CertManager.h @@ -0,0 +1,30 @@ +/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/util/CertManager.cpp
+# - Manage SSL certificates
+# - provide access by name
+# -----------------------------------------------------------------------------
+*/
+
+#ifndef CERTMANAGER_H_
+#define CERTMANAGER_H_
+
+#include <QtNetwork/QSslCertificate>
+#include <QtNetwork/QSslKey>
+
+namespace CertManager
+{
+ QSslKey getPrivateKey(QString name);
+ QSslCertificate getCertificate(QString name);
+}
+
+#endif /* CERTMANAGER_H_ */
diff --git a/src/util/TextFile.cpp b/src/util/TextFile.cpp new file mode 100644 index 0000000..0d04e47 --- /dev/null +++ b/src/util/TextFile.cpp @@ -0,0 +1,39 @@ +/*
+ * TextFile.cpp
+ *
+ * Created on: 13.02.2010
+ * Author: Zahl
+ */
+
+#include "TextFile.h"
+
+TextFile::TextFile(QString filename) : QTextStream()
+{
+ _file = new QFile(filename);
+ if (_file->open(QIODevice::ReadOnly))
+ {
+ this->setDevice(_file);
+ _good = true;
+ }
+ else
+ {
+ _good = false;
+ }
+}
+
+bool TextFile::good()
+{
+ return _good;
+}
+
+bool TextFile::eof()
+{
+ if (!_good || this->atEnd()) return true;
+ return false;
+}
+
+TextFile::~TextFile()
+{
+ _file->close();
+ delete _file;
+}
diff --git a/src/util/TextFile.h b/src/util/TextFile.h new file mode 100644 index 0000000..49932fa --- /dev/null +++ b/src/util/TextFile.h @@ -0,0 +1,26 @@ +/*
+ * TextFile.h
+ *
+ * Created on: 13.02.2010
+ * Author: Zahl
+ */
+
+#ifndef TEXTFILE_H_
+#define TEXTFILE_H_
+
+#include <QtCore/QFile>
+#include <QtCore/QTextStream>
+
+class TextFile : public QTextStream
+{
+public:
+ TextFile(QString filename);
+ virtual ~TextFile();
+ bool good();
+ bool eof();
+protected:
+ QFile *_file;
+ bool _good;
+};
+
+#endif /* TEXTFILE_H_ */
diff --git a/src/util/clientGUIUtils.cpp b/src/util/clientGUIUtils.cpp new file mode 100644 index 0000000..4d4cc0d --- /dev/null +++ b/src/util/clientGUIUtils.cpp @@ -0,0 +1,144 @@ +#include "clientGUIUtils.h" + +BlankScreen::BlankScreen() +{ + dpy = XOpenDisplay(NULL); + scr = DefaultScreen(dpy); + assert(dpy); + blackColor = BlackPixel(dpy, DefaultScreen(dpy)); + whiteColor = WhitePixel(dpy, DefaultScreen(dpy)); +// win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 200, 100, 0, blackColor, whiteColor); + win = XCreateSimpleWindow(dpy, RootWindow(dpy, scr), 10, 10, 200, 200, 1, WhitePixel(dpy, scr), BlackPixel(dpy, scr)); + + XSelectInput(dpy, win, ExposureMask | KeyPressMask); + locked = false; + offX = offY = 0; +} + +void BlankScreen::draw(bool force) +{ + if (locked)// no need to draw if we're not showing the window + { + XWindowAttributes xwa; + XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &xwa); + int hx = (xwa.width)>>2, hy = (xwa.height)>>2; + + if (XCheckTypedEvent(dpy, Expose, &ev) || force ) + { + hx += offX; + hy += offY; + + GC gcc = XCreateGC(dpy, win, 0, NULL); + XSetForeground(dpy, gcc, whiteColor); +// XClearArea(dpy, win, 0, 0, xwa.width, xwa.height, false); + if (lockMsg.size() > 0) + { + char *msg = const_cast<char*>(lockMsg.toUtf8().data()); + XDrawString(dpy, win, gcc/*DefaultGC(dpy, scr)*/, hx, hy, msg, strlen(msg)); + } + else + { + } + } + } +} + +bool BlankScreen::lock() +{ +#define lock_test + + if (locked) + return locked; + + // We want to get MapNotify events + XSelectInput(dpy, win, StructureNotifyMask); + + // "Map" the window (that is, make it appear on the screen) + XMapWindow(dpy, win); + + // Create a "Graphics Context" + //GC gc = XCreateGC(dpy, win, 0, NULL); + + XEvent xev; + Atom wm_state = XInternAtom(dpy, "_NET_WM_STATE", False); + Atom fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = win; + xev.xclient.message_type = wm_state; + xev.xclient.format = 32; + xev.xclient.data.l[0] = 1; + xev.xclient.data.l[1] = fullscreen; + xev.xclient.data.l[2] = 0; + + XSendEvent(dpy, DefaultRootWindow(dpy), False, + SubstructureNotifyMask, &xev); + + + + + // Wait for the MapNotify event + for (;;) + { + XEvent e; + XNextEvent(dpy, &e); + if (e.type == MapNotify) + break; + } + //Flush it! + //XFlush(dpy); + +#ifndef lock_test + // load the locked cursor, so people dont think they can click anything + // TODO: Use some kind of invisible cursor instead of the wait-cursor + Cursor locked_cur = XCreateFontCursor(dpy, XC_watch); + XDefineCursor(dpy, DefaultRootWindow(dpy),locked_cur); +#endif + + // grabbing of keyboard and mouse and hide the cursor + XGrabKeyboard(dpy, DefaultRootWindow(dpy), false, GrabModeAsync, GrabModeAsync, CurrentTime); + XGrabPointer(dpy, DefaultRootWindow(dpy), false, 0, GrabModeAsync, GrabModeAsync, None, NULL, CurrentTime); + + if (!locked) + ConsoleLog writeLine(QString("Locked")); + + // see header for more information on this switch + return locked = true; +} + +bool BlankScreen::lock_inputs() +{ + // grabbing of keyboard and mouse and hide the cursor + XGrabKeyboard(dpy, DefaultRootWindow(dpy), false, GrabModeAsync, GrabModeAsync, CurrentTime); + XGrabPointer(dpy, DefaultRootWindow(dpy), false, 0, GrabModeAsync, GrabModeAsync, None, NULL, CurrentTime); + return true; +} + +bool BlankScreen::unlock() +{ + + if (dpy) + { + + int retval = -1; + + //reset cursor to arrow (no *real* default here...) + Cursor normal_cur = XCreateFontCursor(dpy, XC_arrow); + XDefineCursor(dpy, DefaultRootWindow(dpy), normal_cur); + + // ungrabbing of keyboard and mouse + XUngrabPointer(dpy, CurrentTime); + XUngrabKeyboard(dpy, CurrentTime); + + + retval = XUnmapWindow(dpy,win); + if (retval == BadWindow) + ConsoleLog writeError(QString("Bad window while unmapping. Badwindow: ").append(int2String(retval))); + XFlush(dpy); + } + if (locked) + ConsoleLog writeLine(QString("Unlocked")); + + lockMsg.clear(); + return !(locked = false); +} diff --git a/src/util/clientGUIUtils.h b/src/util/clientGUIUtils.h new file mode 100644 index 0000000..28b05cc --- /dev/null +++ b/src/util/clientGUIUtils.h @@ -0,0 +1,39 @@ +#include "src/util/consoleLogger.h" +#include <X11/Xlib.h> // Every Xlib program must include this +#include <X11/cursorfont.h> +#include <assert.h> +#include <unistd.h> +#include <stdio.h> + + + +#define REFRESH_RATE 0.15 + +#ifndef _BLANKSCREEN_H_ +#define _BLANKSCREEN_H_ + +class BlankScreen +{ +public: + BlankScreen(); + void draw(bool force = false); + bool lock(); + bool unlock(); + void setLogMsg(QString msg); + bool lock_inputs(); + +private: + Display *dpy; + Window win; + XEvent ev; + int scr; + + bool locked; + + + QString lockMsg; + int blackColor, whiteColor; + int offX, offY; +}; + +#endif diff --git a/src/util/consoleLogger.cpp b/src/util/consoleLogger.cpp new file mode 100644 index 0000000..b523b40 --- /dev/null +++ b/src/util/consoleLogger.cpp @@ -0,0 +1,355 @@ +/* + # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of + # Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + # ----------------------------------------------------------------------------- + # consoleLogger.cpp + # - ???. + # ----------------------------------------------------------------------------- + */ + +#include "consoleLogger.h" + +#ifdef never +template<class T> +void ConsoleLogger::addListener(T* who, void (T :: *func)(QString)) +{ + LogNotify<T> *test = new LogNotify<T>(who, func); + _CBLog.push_back(dynamic_cast<LogNotifyEntry*>(test)); +} + +template<class T> +void ConsoleLogger::removeListener(T* who, void (T :: *func)(QString)) +{ + if (_CBLog.size()) + { + for (std::list<LogNotifyEntry*>::iterator it = _CBLog.begin(); it != _CBLog.end(); it++) + { + LogNotify<T> *probe = dynamic_cast<LogNotify<T>*>((*it)); + if (probe) + { + if (probe->getCallee() == who && probe->getCB() == func) + { + _CBLog.remove((*it)); + } + } + } + } +// LogNotify<T> *test = new LogNotify<T>(who, func); + // _CBLog.push_back(dynamic_cast<LogNotifyEntry*>(test)); +} + +#endif +int ConsoleLogger::writeLine(QString message, LOG_LEVEL level) +{ + if (message.size() == 0) + return -1; + + ConsoleEntry consoleEntry(_getTimeStamp(), message, level); + _announceWrite(consoleEntry); // tell the listeners! + _writeLine2File(consoleEntry.getLine()); + _log.push_back(consoleEntry); + + return _log.size(); +} + +int ConsoleLogger::writeline(const char* message, LOG_LEVEL level) +{ + if (message) + { + if (strlen(message) > 0) + return writeLine(QString(message), level); + } + return -1; +} + +int ConsoleLogger::writeError(QString error) +{ + return writeLine(error, LOG_ERROR); +} + +int ConsoleLogger::writeError(const char* error) +{ + return writeLine(error, LOG_ERROR); +} + +int ConsoleLogger::writeTerminal(QString terminal) +{ + // printing the line on the console happens further down the line! + return writeLine(terminal, LOG_TERMINAL); +} + +int ConsoleLogger::writeTerminal(const char* terminal) +{ + if (terminal) + if (strlen(terminal) > 0) + return writeTerminal(QString(terminal)); + + terminal = NULL; + return -1; +} + +int ConsoleLogger::writeNetwork(QString network) +{ + // printing the line on the console happens further down the line! + return writeLine(network, LOG_NETWORK); +} + +int ConsoleLogger::writeNetwork(const char* network) +{ + if (network) + if (strlen(network) > 0) + return writeNetwork(QString(network)); + + network = NULL; + return -1; +} + +int ConsoleLogger::writeChat(QString chat) +{ + return writeLine(chat, LOG_CHAT); +} + +int ConsoleLogger::writeChat(const char* chat) +{ + if (chat) + if (strlen(chat) > 0) + return writeChat(QString(chat)); + + chat = NULL; + return -1; +} + +void ConsoleLogger::getLine(int lineNum, char* line) +{ + QString tmp; + getLine(lineNum, &tmp); + if (tmp.size() > 0) + { + line = new char[_log[lineNum].getLine().size()+1]; + if (line) + { + memcpy(line, _log[lineNum].getLine().toUtf8().data(), _log[lineNum].getLine().size()); + if (strlen(line) > 0) + return; + } + } + line = NULL; + +} + +void ConsoleLogger::getLine(int lineNum, QString* line) +{ + if (lineNum <= int(_log.size())) + { + if (lineNum > 0) + lineNum--; + else if (lineNum < 0) + { + line = NULL; + return; + } + } + else + { + line->clear(); + line = NULL; + } +} + +void ConsoleLogger::setLogPath(QString logPath) +{ + getLogger()->_logPath = logPath; + getLogger()->_prepareLog(); +} + +void ConsoleLogger::setLogName(QString logName) +{ + getLogger()->_logName = logName; + getLogger()->_prepareLog(); +} + +void ConsoleLogger::dumpLog(DUMP_MODE mode) +{ + if (mode == DUMP_FILE || (DUMP_FILE_CONCAT && !_fileRead)) + getLogger()->_writeLog(); + if (mode == DUMP_FILE_CONCAT && _fileRead) + getLogger()->_writeLog(true); + if (mode == DUMP_ALL_LISTENERS) + { + for (int i = 0; i <int(_log.size()); i++) + { + _announceWrite(_log[i]); + } + } +} + +int ConsoleLogger::count = 0; + +ConsoleLogger* ConsoleLogger::_logger; + +ConsoleLogger* ConsoleLogger::getLogger() +{ + if (!_logger) + { + return ConsoleLogger::_logger = new ConsoleLogger(); + } + else + return ConsoleLogger::_logger; +} + +ConsoleLogger::ConsoleLogger() + : _logName(""), + _logPath(getPolicyFilePath(QString(""))), + _fileRead(false), + entryDispatcher() +{ +// _prepareLog(); +} + +ConsoleLogger::~ConsoleLogger() +{ + // doesnt work!? + _writeLog(); +} + +void ConsoleLogger::_prepareLog() +{ + _logFile.close(); + _logFileGood = false; + _readLog(); + + mkdir(getPolicyFilePath(QString()).toUtf8().data(), 0777); + QString fullpath; + fullpath.append(_logPath); + //TODO: handle wether path/ or path were entered? + fullpath.append(_logName); + _logFile.open(fullpath.toUtf8().data(), std::ofstream::out | std::ofstream::app); + if (_logFile.good()) + { + _logFileGood = true; + writeTerminal(QString("LogPath/Name changed to: ").append(fullpath)); + } + else + { + printf("ERROR: Logfile ( %s ) not accessible/found. Logs will not be available.\n", _logPath.toUtf8().data()); + } + _logFile.close(); +} + +void ConsoleLogger::_writeLine2File(QString line) +{ + if (_logFileGood) + { + QString fullpath; + fullpath.append(_logPath); + //TODO: handle wether path/ or path were entered? + fullpath.append(_logName); + _logFile.open(fullpath.toUtf8().data(), std::ofstream::out | std::ofstream::app); + + if (_logFile.good()) // one can never be too sure + { + _logFile.write(line.toUtf8().data(), line.size()); + } + + _logFile.close(); + } + +} + +// overwrites the file and dumps the complete log archive of this session +void ConsoleLogger::_writeLog(bool concat) +{ + if (_logFileGood) + { + QString fullpath; + fullpath.append(_logPath); + //TODO: handle wether path/ or path were entered? + fullpath.append(_logName); + + std::vector<ConsoleEntry> *tmpLog = NULL; + + if (concat) + { + std::vector<ConsoleEntry> newLog = _prev_log; + newLog.insert(newLog.end(), _log.begin(), _log.end()); + tmpLog = &newLog; + } + else + { + tmpLog = &_log; + } + _logFile.open(fullpath.toUtf8().data(), std::ofstream::out | std::ofstream::trunc); + + if (_logFile.good()) // one can never be too sure + { + for (int i = 0; i < int(tmpLog->size()); i++) + { + _logFile.write(tmpLog->at(i).getLine().toUtf8().data(), tmpLog->at(i).getLine().size()); + } + } + + _logFile.close(); + } +} + +void ConsoleLogger::_announceWrite(ConsoleEntry consoleEntry) +{ + + entryDispatcher.fire(consoleEntry); +} + +void ConsoleLogger::_readLog(QString path) +{ + // todo, read the file, filter the entries and recombine them if possible etc.. + // then save it all to _log_prev. + // then set _readFile to true, so the dump will concat our current log to the old and THEN overwrite the whole file + _prev_log.clear(); + _fileRead = false; +} + +QString ConsoleLogger::_getTimeStamp() +{ + time_t rawtime; + tm * ptm; + time ( &rawtime ); + + //ptm = gmtime ( &rawtime ); + ptm = localtime ( &rawtime ); + + QString tmpStr; + if (ptm->tm_mday < 10) + tmpStr.append(QString("0")); + tmpStr.append(int2String(ptm->tm_mday)); + tmpStr.push_back('.'); + if (ptm->tm_mon < 10) + tmpStr.append(QString("0")); + tmpStr.append(int2String(int(ptm->tm_mon) +1)); + tmpStr.push_back('.'); + int year = (ptm->tm_year % 100); + if (year < 10) + tmpStr.append(QString("0")); + tmpStr.append(int2String(year)); + tmpStr.push_back(' '); + if (ptm->tm_hour < 10) + tmpStr.append(QString("0")); + tmpStr.append(int2String(ptm->tm_hour)); + tmpStr.push_back(':'); + if (ptm->tm_min < 10) + tmpStr.append(QString("0")); + tmpStr.append(int2String(ptm->tm_min)); + tmpStr.push_back(':'); + if (ptm->tm_sec < 10) + tmpStr.append(QString("0")); + tmpStr.append(int2String(ptm->tm_sec)); + + return tmpStr; +} + diff --git a/src/util/consoleLogger.h b/src/util/consoleLogger.h new file mode 100644 index 0000000..3a0950d --- /dev/null +++ b/src/util/consoleLogger.h @@ -0,0 +1,273 @@ + +#include "util.h" +#include "dispatcher.h" +#include <vector> +#include <time.h> +#include <stdio.h> +#include <stdlib.h> +#include <list> + + +//#define as_daemon +#ifndef _CONSOLELOGGER_H_ +#define _CONSOLELOGGER_H_ + +/**********************************************************************************************************************/ +// Console-, and Message Dispatching / Logging (With timestamping!) +/**********************************************************************************************************************/ +// +// :: Usage :: +// +#define ConsoleLog ConsoleLogger::getLogger()-> //ease of acces! +// +// +// *Logging: +// +// ConsoleLog writeLine(<string/char*>); // sends out a message with "normal" loglevel +// ConsoleLog writeLine(<string/char*>, <loglevel>); // sends out a message with the chosen loglevel --> enum LOG_LEVEL +// ConsoleLog writeError(<string/char*>); // sends out a message with "Error" loglevel +// ConsoleLog writeTerminal(<string/char*>); // sends out a message with "Terminal" loglevel, which means it is +// // also printed on stdout +// ConsoleLog writeNetwork(<string/char*>); // sends out a message with "network" loglevel +// ConsoleLog writeChat(<string/char*>); // sends out a message with "Chat" loglevel +// +// *un/subscribing to the LogDispatcher +// +// ConsoleLog addListener(<pointer-to-object-of-Type-myClass>, &myClass::myMethod); +// callback signature --> typedef void (T::*callback)(ConsoleEntry); // with <U, T> as template // for more on ConsoleEntry, see later +// ConsoleLog removeListener(<pointer-to-object-of-Type-myClass>, &myClass::myMethod); +// +// *Misc +// +// ConsoleLog setLogPath(<string-path-to-log-directory>); // set the log directory (with a final /, the logfilename is appended.) +// ConsoleLog setLogName(<string-name>); // like the above, but for the filename. +// ConsoleLog dumpLog(DUMP_MODE); +// +// DUMP_FILE ::>> Dumps the whole log since the logger was started into the specified logfile. the file content gets overwritten +// DUMP_FILE_CONCAT ::>> The Same as above, but it will just append itself to the previously (if implemented) log which got \** +// ***\ read from the logfile which was present at logger start. if no log is found or logfile was not read, behaves as DUMP_FILE +// DUMP_TERMINAL ::>> Dumps the whole log into the terminal +// DUMP_ALL_LISTENERS ::>> Dumps the whole log to all listeners +// +// Alternatively, you can request a dump to a certain listener: +// ConsoleLog dump2Listener(<pointer-to-object-of-Type-myClass>, &myClass::myMethod); // it expects the same information as when subscribing +// // the PVS-Server console makes heavy use of this feature to implement its filters +// +// +// :: using the ConsoleEntry class :: +// +// *methods and members +// +// +// LOG_LEVEL getLevel() // returns the loglevel as LOG_LEVEL Enum-type +// QString getLine() // returns the complete line as shown in the logfile, with timestamp, loglevel prefix etc +// QString getMessage() // returns the message body, no gimmicks attached +// QString getPrefix() // returns the loglevel as string-represenation +// QString getTimeStamp() // returns the timestamp which was set at the creation of the object +// +// +// +// +// +// +/**********************************************************************************************************************/ + + + + + + +// Typdef at bottom of file : +// typedef ConsoleLogger::ConsoleEntry LogEntry; + + +class ConsoleLogger +{ +public: + + enum LOG_LEVEL { LOG_NORMAL, + LOG_ERROR, + LOG_CHAT, + LOG_TERMINAL, + LOG_NETWORK + }; + enum DUMP_MODE { DUMP_FILE, + DUMP_FILE_CONCAT, + DUMP_TERMINAL, + DUMP_ALL_LISTENERS, + }; + class ConsoleEntry + { + public: + ConsoleEntry(QString timeStamp, QString message, LOG_LEVEL level) + { + setLine(timeStamp, message, level); + }; + void setLine(QString timeStamp, QString message, LOG_LEVEL level) + { + _message = message; + _prefix = _prefixLine(level); + _timeStamp = timeStamp; + _line.append(QString("[ ").append(timeStamp)); + _line.append(QString(" ] ").append(_prefix)); + _line.append(QString(": ").append(message)); + _level = level; + if ('\n' != _line[_line.size()-1] && '\n' != _line[_line.size()]) + _line.push_back('\n'); // add an explicit newline char, so it looks better in the logfile + //#ifndef as_daemon + if (_level == LOG_TERMINAL) // may look strange here, but its quite central :-) + printf("%s\n", _line.toUtf8().data()); + //#endif + }; + LOG_LEVEL getLevel() + { + return _level; + }; + QString getLine() + { + return _line; + }; + QString getMessage() + { + return _message; + }; + QString getPrefix() + { + return _prefix; + }; + QString getTimeStamp() + { + return _timeStamp; + }; + + private: + QString _prefixLine(LOG_LEVEL level) + { + // switch anyone? + if (level == LOG_NORMAL) + return QString("PVS"); + if (level == LOG_ERROR) + return QString("PVS ERROR"); + if (level == LOG_TERMINAL) + return QString("PVS Terminal"); + if (level == LOG_CHAT) + return QString("PVS Chat"); + if (level == LOG_NETWORK) + return QString("PVS Network"); + return QString("UNDEFINED"); + }; + QString _line; // the complete line with timestamp and everything + QString _message; // the message itself + QString _prefix; // just the prefix + QString _timeStamp; // just the timestamp + LOG_LEVEL _level; + }; + + class LogNotifyEntry + { + public: + virtual void fire(ConsoleEntry consoleEntry) {}; + LogNotifyEntry() {}; + }; + +#ifdef never +private: + template<class T> + class LogNotify : public LogNotifyEntry + { + public: + typedef void (T::*callback)(ConsoleEntry); + LogNotify(T* who, callback func )//void (T :: *func)(QString)) + { + callee = who; + //callback = func; + myCB = func; + }; + virtual void fire(ConsoleEntry consoleEntry) + { + if (callee) + (callee->*myCB)(consoleEntry); + }; + T* getCallee() + { + return callee; + }; + callback getCB() + { + return myCB; + }; + + private: + T *callee; + callback myCB; + }; + +public: +#endif + // interfaces for the dispatcher for easy of access ( --> ConsoleLog Makro) + template<class T> void addListener(T* who, void (T :: *func)(ConsoleEntry)) + { + entryDispatcher.addListener(who, func); + }; + template<class T> void removeListener(T* who, void (T :: *func)(ConsoleEntry)) + { + entryDispatcher.removeListener(who, func); + }; + template<class T> void dump2Listener(T* who, void (T :: *func)(ConsoleEntry)) + { + for (int i = 0; i < int(_log.size()) ; i++) + (who->*func)(_log[i]); + }; + + int writeLine(QString message, LOG_LEVEL = LOG_NORMAL); + int writeline(const char* message, LOG_LEVEL = LOG_NORMAL); + int writeError(QString error); + int writeError(const char* error); + int writeTerminal(QString terminal); + int writeTerminal(const char* terminal); + int writeNetwork(QString network); + int writeNetwork(const char* network); + int writeChat(QString chat); + int writeChat(const char* chat); + void getLine(int lineNum, char* line); + void getLine(int lineNum, QString* line); + void setLogPath(QString logPath); + void setLogName(QString logName); + void dumpLog(DUMP_MODE mode = DUMP_FILE); + static ConsoleLogger* getLogger(); + static int count; +private: + + + std::vector<ConsoleEntry>* _getLog() + { + return &_log; + }; + static ConsoleLogger* _logger; + void _prepareLog(); + void _writeLine2File(QString line); + void _writeLog(bool concat = false); + void _announceWrite(ConsoleEntry consoleEntry); + void _readLog(QString path = QString("")); + QString _getTimeStamp(); + void _prefixLine(QString* line, LOG_LEVEL level = LOG_NORMAL); + + + + ConsoleLogger(); + ~ConsoleLogger(); + + QString _logName; + QString _logPath; + + bool _logFileGood, _fileRead; +// std::list<LogNotifyEntry*> _CBLog; + EventDispatcher<ConsoleEntry> entryDispatcher; + std::vector<ConsoleEntry> _log; + std::vector<ConsoleEntry> _prev_log; + std::ofstream _logFile; +}; + +typedef ConsoleLogger::ConsoleEntry LogEntry; + +#endif diff --git a/src/util/dispatcher.h b/src/util/dispatcher.h new file mode 100644 index 0000000..490a3be --- /dev/null +++ b/src/util/dispatcher.h @@ -0,0 +1,210 @@ +#ifndef _DISPATCHER_H_ +#define _DISPATCHER_H_ +#include <list> +#include <QString> +#include <iostream> +#include <map> + + +//****************************************************************************************************/ +// EventDispatcher && EventIdentDispatcher // +/***************************************************************************************************/ +// This handy class(es) act as very simple signals/events. +// Its OOP-only, so dont even try to add static functions +// or C-like methods! +// +// :: Return Types :: +// +// at the moment only callbacks for void methods with a parameter +// count of one ( whos type is the primary template parameter) +// +// :: callback signature :: +// +// typedef void (T::*callback)(U); // with <U, T> as template +// +// :: Usage Example :: +// +// *creating a Dispatcher +// +// -- EventDispatcher<Type A>* nameYourDispatcher = new EventDispatcher<Type A>; // simple Dispatcher +// -- EventIdentDispatcher<Type A>* nameYourIdentDispatcher = new EventIdentDispatcher<Type A>; // ident dispatcher +// +// *difference between simple and ident +// +// a simple dispatcher features only one type of signal, so you can only call all +// attached listeners at once or none at all +// +// an ident dispatcher uses an ident string to hold and fire more than one event type at once +// but is limited to the one defined parameter type for its methods +// +// *subscribung to a dispatcher +// +// -- nameYourDispatcher->addListener(<pointer-to-object-of-Type-myClass>, &myClass::myMethod); // simple Dispatcher +// -- nameYourIdentDispatcher->addListener(<string-as-ident>, <pointer-to-object-of-Type-myClass>, &myClass::myMethod); // ident dispatcher// +// +// you can add the same method/instance to different dispatchers oder differnt ident-distinguished dispatchers in a identdispatcher. +// you can also add the same method/instance to the same dispatchers all over again, which is not recommended +// +// +// *firing a dispatcher +// +// -- nameYourDispatcher->fire(Type_A Object); // simple Dispatcher +// -- nameYourIdentDispatcher->fire(<string-as-ident>, Type_A Object); // ident dispatcher// +// +// All respective attached callbacks are called in the order they were added +// +// +// *unsubscribing +// +// -- nameYourDispatcher->removeListener(<pointer-to-object-of-Type-myClass>, &myClass::myMethod); // simple Dispatcher +// -- nameYourIdentDispatcher->removeListener(<string-as-ident>, <pointer-to-object-of-Type-myClass>, &myClass::myMethod); // ident dispatcher// +// +// just the reverse of addListener. currently no removeAll() available +// +// +// +/***************************************************************************************************/ +class CallbackHandle +{ +}; + +template<class U> +class CallbackBase : public CallbackHandle +{ +public: + virtual void fire(U u) {}; + +private: +}; + +template<class T, class U> +class Callback : public CallbackBase<U> +{ +public: + + virtual void fire(U u) + { + if (cbVU) + (callee->*cbVU)(u); + }; + + typedef void (T::*callbackVU)(U); + + Callback(T* who, callbackVU cb) + { + cbVU = cb; + callee = who; + }; + + T* getCallee() + { + return callee; + }; + callbackVU getCBVU() + { + return cbVU; + }; + +private: + callbackVU cbVU; + T* callee; + +}; + +template<class U> +class EventDispatcher +{ +public: + template<class T> void addListener(T *who, void (T :: *func)(U)) + { + Callback<T, U> *tmp = new Callback<T, U>(who, func); + _listener.push_back(dynamic_cast<CallbackBase<U>*>(tmp)); + }; + void fire(U u) + { + for (typename std::list<CallbackBase<U>*>::iterator it = _listener.begin(); it != _listener.end(); it++) + { + if (*it) + { + (*it)->fire(u); + } + } + }; + + template<class T> void removeListener(T* who, void (T :: *func)(U)) + { + if (_listener.size()) + { + for (typename std::list<CallbackBase<U>*>::iterator it = _listener.begin(); it != _listener.end(); it++) + { + CallbackBase<U>* pro = (*it); + Callback<T, U> *probe = dynamic_cast<Callback<T,U>*>(pro); + if (probe) + { + if (probe->getCallee() == who && probe->getCBVU() == func ) + { + delete (probe); + _listener.remove((*it)); + return; + } + } + } + } + }; + +private: + + std::list<CallbackBase<U>*> _listener; +}; + +template<class U> +class EventIdentDispatcher +{ +public: + template<class T> void addListener(QString ident, T* who, void (T :: *func)(U)) + { + Callback<T, U>* tmp = new Callback<T, U>(who, func); + _listener.push_back(std::pair<QString, CallbackBase<U>*>(ident, dynamic_cast<CallbackBase<U>*>(tmp))); + }; + + void fire(QString ident, U u) + { + for ( typename std::list<std::pair<QString, CallbackBase<U>* > >::iterator it = _listener.begin(); it != _listener.end(); it++) + { + if ((*it).first.compare(ident) == 0 || QString("*").compare((*it).first) == 0) + { + if ((*it).second) + { + (*it).second->fire(u); + } + } + } + }; + template<class T> void removeListener(QString ident, T* who, void (T :: *func)(U)) + { + if (_listener.size()) + { + for (std::list<std::pair <QString, CallbackHandle*> >::iterator it = _listener.begin(); it != _listener.end(); it++) + { + if ((*it).first.compare(ident) == 0) + { + CallbackBase<U>* pro = (*it).second; + Callback<T, U> *probe = dynamic_cast<Callback<T,U>*>(pro); + if (probe) + { + if (probe->getCallee() == who && probe->getVoidCB == func) + { + delete (*it).second; + _listener.remove((*it)); + return; + } + } + } + } + } + }; +private: + std::list<std::pair<QString, CallbackBase<U>* > > _listener; +}; + +#endif diff --git a/src/util/pvsSettingsManager.cpp b/src/util/pvsSettingsManager.cpp new file mode 100644 index 0000000..a6a742b --- /dev/null +++ b/src/util/pvsSettingsManager.cpp @@ -0,0 +1,185 @@ +#include "pvsSettingsManager.h" +#include "TextFile.h" + +PVSSettingsManager* PVSSettingsManager::getManager() +{ + if (myself) + return myself; + else + return myself = new PVSSettingsManager; +} + +void PVSSettingsManager::setConfigFile(QString path) +{ + if (path.size() && fileExists(path)) + { + _path = path; + _parseFile(_path); + + } + else + ConsoleLog writeError(QString("Can't open config file \"").append(QString(path).append("\""))); +} + +bool PVSSettingsManager::hasEntry(QString name) +{ + for (SettingsIter it = settingsList.begin(); it != settingsList.end(); it++) + { + if ((*it).first.compare(name) == 0) + { + return true; + } + } + return false; +} + +QString PVSSettingsManager::getEntryString(QString name) +{ + for (SettingsIter it = settingsList.begin(); it != settingsList.end(); it++) + { + if ((*it).first.compare(name) == 0) + { + return (*it).second; + } + } + return QString(); +} + +void PVSSettingsManager::writeEntry(QString name, QString value) +{ + if (name.size() && value.size()) + return; + bool unique = true; + for (SettingsIter it = settingsList.begin(); it != settingsList.end(); it++) + { + if ((*it).first.compare(name) == 0) + { + unique = false; + (*it).second = value; + break; + } + } + if (unique) + { + SettingsEntry tmp(name, value); + settingsList.push_back(tmp); + } +} + + +PVSSettingsManager* PVSSettingsManager::myself = NULL; + +PVSSettingsManager::PVSSettingsManager() +{ + +} + +void PVSSettingsManager::setConfigs() +{ + //default settings + _configs.setValue("Chat/chatstate", "on"); + _configs.setValue("Chat/chatmode", "bossmode"); + _configs.setValue("Room/roomId", "0"); + _configs.setValue("VNC/permit", "off"); + _configs.setValue("VNC/quality", "high"); + _configs.sync(); +} +void PVSSettingsManager::reWriteConfigs(QString set, QString val) +{ + _configs.setValue(set, val); + _configs.sync(); +} + +void PVSSettingsManager::readConfigs(QString sett, QString vall) +{ + //TODO: read the config file.. + _configs.value("Chat/chatstate").toBool(); + _configs.value("Chat/chatmode").toString(); + _configs.value("Room/room").toInt(); + _configs.value("VNC/permit").toBool(); + _configs.value("VNC/quality").toString(); +} + +void PVSSettingsManager::_parseFile(QString path) +{ + QString line; + TextFile file(path); + + SettingsList tmpList; + + if (file.good()) + { + while (!file.eof()) + { + line = file.readLine(); + if (!(line.length() <=1)) // ignore blank + { + if (!(line[0] == '#' || line[0] == '/' || line[0] == '[')) // ignore comments and section headers + { + SettingsEntry tmp = _parseLine(line); + if (tmp.first.size() && tmp.second.size()) + { + bool unique = true; + for (SettingsIter it = tmpList.begin(); it != tmpList.end(); it++) + { + if ((*it).first.compare(tmp.first) == 0) + { + unique = false; + break; + } + } + if (unique) + tmpList.push_back(tmp); + } + } + } + } + } + else + { + ConsoleLog writeError(QString("No configfile \"").append(QString(path).append("\" found or file corrupt."))); + } + + if (tmpList.size()) + settingsList = tmpList; +} +#ifdef verbose +ConsoleLog writeLine(QString("Dumping Config Content of ").append(QString(path).append(" : "))); +for (SettingsIter it = settingsList.begin(); it != settingsList.end(); it++) +{ + ConsoleLog writeLine(QString("Option: ").append(QString((*it).first).append(QString(" | Value: ").append((*it).second)))); +} +ConsoleLog writeLine(QString("End of ").append(QString(path).append("."))); +#endif + +SettingsEntry PVSSettingsManager::_parseLine(QString line) +{ + QString name; + QString value; + + name = lineSplitter(line, "=\n\t", true); + value = lineSplitter(line, "=\n\t", false); + + if (!(name.size() && value.size())) + return SettingsEntry("",""); + + + // remove whitespaces in front of option name + for (int i = 0; i < name.size(); i++) + { + if (name[i] == '\t' || name[i] == ' ') + { + name.remove(i, 1); + i--; + } + else + break; + } + // whitespaces after the value are trimmed by the lineSplitter + + SettingsEntry tmp(name, value); + return tmp; +} + + + diff --git a/src/util/pvsSettingsManager.h b/src/util/pvsSettingsManager.h new file mode 100644 index 0000000..78607eb --- /dev/null +++ b/src/util/pvsSettingsManager.h @@ -0,0 +1,50 @@ +/// documentation test 1 +/// line 2 +/// line 3 +#ifndef _PVSSETTINGSMANGER_H_ +#define _PVSSETTINGSMANGER_H_ + +#include <list> +#include <map> +#include <src/util/util.h> +#include <src/util/consoleLogger.h> +#include <QSettings> + + +/// documentation test 1.1 +/// line 2.1 +/// line 3.1 + +typedef std::pair<QString, QString> SettingsEntry; ///< first = option name, second = option value +typedef std::list<SettingsEntry> SettingsList; ///< obvious +typedef std::list<SettingsEntry>::iterator SettingsIter; + + +class PVSSettingsManager; +/// documentation test 1.2 +/// line 2.2 +/// line 3.2 +class PVSSettingsManager +{ +public: + static PVSSettingsManager* getManager(); + void setConfigFile(QString path); + bool hasEntry(QString name); + QString getEntryString(QString name); + void writeEntry(QString name, QString value); + void setConfigs(); + void reWriteConfigs(QString set, QString val); + void readConfigs(QString sett, QString vall); +private: + static PVSSettingsManager* myself; + PVSSettingsManager(); + void _parseFile(QString path); + SettingsEntry _parseLine(QString line); + QString _path; + SettingsList settingsList; + QSettings _configs; + +}; + + +#endif diff --git a/src/util/serviceDiscoveryUtil.cpp b/src/util/serviceDiscoveryUtil.cpp new file mode 100644 index 0000000..32aa0fc --- /dev/null +++ b/src/util/serviceDiscoveryUtil.cpp @@ -0,0 +1,65 @@ +#include "serviceDiscoveryUtil.h"
+#include <cassert>
+
+void appendSdField(QByteArray* target, const char* id, QString data)
+{
+ assert(strlen(id) == 3);
+ target->append(id);
+ QByteArray tmp = data.toUtf8();
+ if (tmp.size() > 100) tmp.truncate(100);
+ target->append((char)tmp.size());
+ target->append(tmp);
+}
+
+SdFields parseSdFields(unsigned char* data, int len)
+{
+ SdFields fields;
+ for (;;)
+ {
+ //printf("%d bytes left: %s\n", len, (char*)data);
+ if (len < 4 || len < 4 + data[3]) break; // end of data
+ QString key = QString::fromUtf8((char*)data, 3);
+ QString val = QString::fromUtf8((char*)data+4, data[3]);
+ //printf("Key: %s, Val: %s\n", key.toUtf8().data(), val.toUtf8().data());
+ fields.insert(key, val);
+ len -= (4 + data[3]);
+ data += (4 + data[3]);
+ }
+ return fields;
+}
+
+QString sha1ToReadable(QByteArray input)
+{
+ unsigned char *ptr = (unsigned char *)input.data();
+ QString retval;
+ for (int i = (input.length() < 10 ? input.length() : 10); i; --i)
+ {
+ switch(*ptr++ % 0xD)
+ {
+ case 0x0: retval.append('S'); break;
+ case 0x1: retval.append('F'); break;
+ case 0x2: retval.append('M'); break;
+ case 0x3: retval.append('K'); break;
+ case 0x4: retval.append('H'); break;
+ case 0x5: retval.append('T'); break;
+ case 0x6: retval.append('P'); break;
+ case 0x7: retval.append('D'); break;
+ case 0x8: retval.append('Y'); break;
+ case 0x9: retval.append('W'); break;
+ case 0xA: retval.append('G'); break;
+ case 0xB: retval.append('L'); break;
+ case 0xC: retval.append('B'); break;
+ }
+ if (--i == 0) break;
+ switch((*ptr >> 2) % 5)
+ {
+ case 0: retval.append('a'); break;
+ case 1: retval.append('i'); break;
+ case 2: retval.append('u'); break;
+ case 3: retval.append('e'); break;
+ case 4: retval.append('o'); break;
+ }
+ if ((*ptr++ & 3) == 0) retval.append('n');
+ }
+ return retval;
+}
diff --git a/src/util/serviceDiscoveryUtil.h b/src/util/serviceDiscoveryUtil.h new file mode 100644 index 0000000..537daeb --- /dev/null +++ b/src/util/serviceDiscoveryUtil.h @@ -0,0 +1,19 @@ +#ifndef SERVICEDISCOVERYUTIL_H_
+#define SERVICEDISCOVERYUTIL_H_
+
+#include <QtCore/QString>
+#include <QtCore/QHash>
+
+typedef QHash<QString, QString> SdFields;
+
+// These two functions build/parse the message format used in SD broadcasts
+// It is some kind of key-value pairs, encoded as follows:
+// <3 chars/bytes, key><1 byte, value length in bytes><up to 100 chars/bytes, value>
+void appendSdField(QByteArray* target, const char* id, QString data);
+SdFields parseSdFields(unsigned char* data, int len);
+
+// This algorithm is supposed to generate a readable and maybe pronouncable
+// string from the fingerprint of the servers certificate
+QString sha1ToReadable(QByteArray input);
+
+#endif /* SERVICEDISCOVERYUTIL_H_ */
diff --git a/src/util/timeUtil.cpp b/src/util/timeUtil.cpp new file mode 100644 index 0000000..6f8e93d --- /dev/null +++ b/src/util/timeUtil.cpp @@ -0,0 +1,42 @@ +/* + # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of + # Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + # ----------------------------------------------------------------------------- + # timeUtil.cpp + # - ???. + # ----------------------------------------------------------------------------- + */ + +#include "timeUtil.h" + +TimeUtil::TimeUtil() +{ + seconds = useconds = mtime = 0; +} + +void TimeUtil::start() +{ + gettimeofday(&Begin, NULL); +} + +void TimeUtil::stop() +{ + gettimeofday(&End, NULL); + seconds = End.tv_sec - Begin.tv_sec; + useconds = End.tv_usec - Begin.tv_usec; + mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5; +} + +long TimeUtil::getMS() +{ + return mtime; +} + diff --git a/src/util/timeUtil.h b/src/util/timeUtil.h new file mode 100644 index 0000000..90d647d --- /dev/null +++ b/src/util/timeUtil.h @@ -0,0 +1,34 @@ +#ifndef TIME_UTIL +#define TIME_UTIL + +#include <sys/time.h> +#include <stdio.h> +#include <unistd.h> + + +#ifdef PROFILE +#define startTime(aaa) TimeUtil aaa ## Time = TimeUtil(); aaa ## Time.start(); +#define endTime(aaa) aaa ## Time.stop(); printf("Time to execute " #aaa " : %ld\n", aaa ## Time.getMS()); +#endif + +#ifndef PROFILE +#define startTime(aaa) +#define endTime(aaa) +#endif + + + +class TimeUtil +{ + +public: + TimeUtil(); + void start(); + void stop(); + long getMS(); +private: + long mtime, seconds, useconds; + struct timeval Begin, End; //initialize Begin and End for the timer +}; + +#endif diff --git a/src/util/util.cpp b/src/util/util.cpp new file mode 100644 index 0000000..c2d06a0 --- /dev/null +++ b/src/util/util.cpp @@ -0,0 +1,416 @@ +#include "util.h" +#include <QtGui/QDesktopServices> +#include "consoleLogger.h" +#include "TextFile.h" +#include <ctime> +#include <cstdlib> +#include <QStringList> +#include <iostream> + + +PVSServerEntry::PVSServerEntry(QString name) +{ + name_ = name; +} +void PVSServerEntry::addClient(QString client) +{ + clientList_.push_back(client); +} +bool PVSServerEntry::hasClient(QString client) +{ + for (std::list<QString>::iterator it = clientList_.begin(); it != clientList_.end(); it++) + { + if ((*it).compare(client) == 0) + return true; + } + return false; +} +QString PVSServerEntry::getName() +{ + return name_; +} + +int PVSServerEntry::getSize() +{ + return clientList_.size(); +} + + +//namespace util +//{ + +int getRandom(int min, int max) +{ + static bool init = true; + if (init) + { + init = false; + srand ( time(NULL) + getpid() ); + } + if (min >= max) return rand(); + return rand() % (max-min+1) + min; +} + +std::list<PVSServerEntry> getPVSServerEntryList(QString fileName) +{ + QString line; + TextFile file(fileName); + std::list<PVSServerEntry> entryList; + + if (file.good()) + { +// std::cout << "reading table file \"" << fileName <<"\"" << std::endl; + PVSServerEntry* tmpEntry = NULL; + while (!file.eof()) + { + line = file.readLine(); + + if (!(line.length() <=1)) // ignore blank + if (!(line[0] == '#' || line[0] == '/')) // ignore comments + { + if (line.mid(0, 5).compare(QString("start")) == 0) + { + if (tmpEntry != NULL) + { + // unclean file... but no reason to break down + //PVSServerEntry tmpEntry2 = *tmpEntry; + entryList.push_back(*tmpEntry); + delete tmpEntry; + tmpEntry = NULL; + } + QString tmpName(colonSplitter(line, false)); + if (tmpName.size()<1) + tmpName = QString("localhost"); + + tmpEntry = new PVSServerEntry(tmpName); + continue; + } + if (line.mid(0, 3).compare(QString("end")) == 0) + { + if (tmpEntry!=NULL) + { + entryList.push_back(*tmpEntry); + delete tmpEntry; + tmpEntry = NULL; + } + else + ;// ignore + + continue; + } + if (tmpEntry != NULL) + { + tmpEntry->addClient(line); + } + } + } + if (tmpEntry != NULL) + { + delete tmpEntry; + tmpEntry = NULL; + } + + return entryList; + } + else + { + std::cout << "ERROR: no file \"" << fileName.toStdString() <<"\" found or file corrupt" << std::endl; + } + return std::list<PVSServerEntry>(); +} +QString getFilenameFromPath(QString line) +{ + int lastSlash = 0; + for (int i = 0; i < line.length(); i++) + { + if (line.at(i) == '/') + { + lastSlash = i; + } + } + QString result; + if (lastSlash != 0 && lastSlash != line.length() -1) + { + result = line.mid(lastSlash+1, line.length()-(lastSlash+1)); + } + return result; +} + +QString lineSplitter(QString line, const char* signs, bool first) +{ + char *pch; + char* cLine = new char[line.length()+1]; + strcpy(cLine, line.toUtf8().data()); + pch = strtok (cLine,signs); + if (first) + { + QString tmp(pch); + delete cLine; + return tmp; + } + else + { + QString tmp; + char* tmpp = strtok(NULL, ";,\t\n"); + if (tmpp) + tmp = QString(tmpp); + delete cLine; + return tmp; + } +} + +QString colonSplitter(QString line, bool first) +{ + char *pch; + char* cLine = new char[line.length()+1]; + strcpy(cLine, line.toUtf8().data()); + pch = strtok (cLine," :\t\n"); + if (first) + { + QString tmp(pch); + delete[] cLine; + return tmp; + } + else + { + QString tmp; + char* tmpp = strtok(NULL, " ;,\t\n"); + if (tmpp) + tmp = QString(tmpp); + delete[] cLine; + return tmp; + } +} + +QString getUserName() +{ + struct passwd* passUser = getpwuid(getuid()); + QString username; + if (passUser) + { + username = QString(passUser->pw_name); + } + if (username.isEmpty()) + { + printf("USERNAME COULDNT BE RETRIEVED!\n"); + username = QString("USERNAMEERROR"); + } + return username; +} + +// Get full username. +QString getFullUsername() +{ + QString fullname = getUserName(); + struct passwd *pd; + + if (NULL == (pd = getpwuid(getuid()))) + {ConsoleLog writeError("getpwuid() error.");} + else + { + QString tmp = pd->pw_gecos; + QStringList userData = tmp.split(","); + if(userData[0].length() > 0 ) + { + fullname = userData[0]; + } + } + return fullname; +} + +bool fileExists(QString fileName) +{ + std::ifstream file(fileName.toLocal8Bit().data()); + if (file.good()) + { +#ifdef verbose + printf("fileExists(): file good.\n"); +#endif + file.close(); + return true; + } + return false; + +} + +QString getHomeDir() +{ + return QDesktopServices::storageLocation(QDesktopServices::HomeLocation); +} + +QString getPolicyDir() +{ + QString policyDir = getHomeDir(); + QString subPath("/.pvs/"); + policyDir.append(subPath); + return policyDir; +} + +QString getPolicyFilePath(QString fileName) +{ + + QString fullPath = getPolicyDir(); + fullPath.append(fileName); + return fullPath; +} +bool policyFileExists(QString fileName) +{ + std::ifstream file(getPolicyFilePath(fileName).toUtf8().data()); + if (file.good()) + { + file.close(); + return true; + } + return false; +} + +void createPolicyDir() +{ + mkdir(getPolicyDir().toUtf8().data(), 0777); +} + +void createPolicyFiles() +{ + if (!policyFileExists(QString(".allow"))) + { + std::ofstream file(getPolicyFilePath(QString(".allow")).toUtf8().data()); + file.close(); + } +#ifdef old_method + if (!policyFileExists(QString(".pass"))) + { + std::ofstream file(getPolicyFilePath(QString(".pass")).toUtf8().data()); + file.close(); + } +#endif +} + +QString readPassFromPassFile() +{ + TextFile file(getPolicyFilePath(".pass")); + if (file.good()) // should have been checked via exists before, but better be safe + { + QString pass; + pass = file.readLine(); // we expect a password in correct format. otherwise their fault + return pass; + } + else + return QString(); +} +bool getAllowed() +{ + printf("Checking %s\n", getPolicyFilePath(QString(".allow")).toUtf8().data()); + TextFile file(getPolicyFilePath(".allow")); + if (file.good()) // should have been checked via exists before, but better be safe + { + QString allowed; + allowed = file.readLine(); + if ( (allowed.compare(QString("1")) == 0) || + (allowed.compare(QString("true")) == 0) || + (allowed.compare(QString("t")) == 0) || + (allowed.compare(QString("T")) == 0) || + (allowed.compare(QString("true")) == 0) || + (allowed.compare(QString("allow")) == 0) || + (allowed.compare(QString("TRUE")) == 0) ) + return true; + } + printf("...negative\n"); + return false; +} + +QString int2String(int intInt) +{ + char tmp[50]; + snprintf(tmp, 49, "%d", intInt); + return QString(tmp); +} + +int string2Int(QString string) +{ + return atoi(string.toUtf8().data()); +} + +//}//end namespace util + + +#ifdef neverever +std::list<VNCConnectInfo*> readFile(char* fileName) +{ + QString line; + std::ifstream file(fileName); + std::list<VNCConnectInfo*> infoList; + + if (file.good()) + { +// std::cout << "reading clients file \"" << fileName <<"\"" << std::endl; + while (!file.eof()) + { + getline(file, line); + + if (!(line.length() <=1)) // ignore blank + if (!(line[0] == '#' || line[0] == '/')) // ignore comments + infoList.push_back(getConInfo(line)); + } + } + else + { + std::cout << "ERROR: no file \"" << fileName <<"\" found or file corrupt" << std::endl; + } + return infoList; +} + +VNCConnectInfo* getConInfo(QString line) +{ + char** arguments = new char*[100]; + char* cLine = new char[line.length()+1]; + strcpy(cLine, line.toUtf8().data()); + int count; + makeArgs(cLine , &count , arguments); + std::cout << "found " << count << " arguments" << std::endl; + if (count > 2) // assume that a password would be the second argument in the line, therefore the third argument in the argv + { + QString pass = QString(arguments[2]); + std::cout << "think i found a password" << std::endl; + count--; + delete arguments[2]; + // no changes to the arguments though, since the vnc-lib will ignore most of it anyway + return new VNCConnectInfo(count, arguments, pass); + } + + return new VNCConnectInfo(count, arguments); +} + +void makeArgs(char* line, int* count, char** arguments) +{ + (*count) = 1; + + arguments[(*count)-1] = new char[strlen("dummy")+1]; // get program name from somewhere + strcpy(arguments[(*count)-1], "dummy"); + + /*// include encodings + arguments[(*count)++] = new char[strlen("-encodings")+1]; + strcpy(arguments[(*count)], "-encodings"); + (*count)++; + arguments[(*count)++] = new char[strlen("tight")+1]; + strcpy(arguments[(*count)], "tight"); + (*count)++; + */ + + + if (line[strlen(line)-1] == '\n' || line[strlen(line)-1] == '\r') + line[strlen(line)-1] = '\0'; // remove newline + + char *pch; + pch = strtok (line," ,\t"); + while (pch != NULL && (*count) <= 3) + { + (*count)++; // count args + arguments[(*count)-1] = new char[strlen(pch)+1]; + strcpy(arguments[(*count)-1], pch); + pch = strtok (NULL, " ,\t"); + } +} + + +#endif + diff --git a/src/util/util.h b/src/util/util.h new file mode 100644 index 0000000..37565cb --- /dev/null +++ b/src/util/util.h @@ -0,0 +1,59 @@ +#include <QString> +#include <cstdio> +//#include <cstring> +#include <list> +#include <fstream> +#include <iostream> +#include <pwd.h> +#include <sys/types.h> +#include <sys/stat.h> + + + +#ifndef _PVSSERVERENTRY_H_ +#define _PVSSERVERENTRY_H_ +class PVSServerEntry +{ +public: + PVSServerEntry(QString name); + void addClient(QString client); + bool hasClient(QString client); + QString getName(); + int getSize(); +private: + QString name_; + std::list<QString> clientList_; +}; +#endif + +//namespace util +//{ +int getRandom(int min, int max); +std::list<PVSServerEntry> getPVSServerEntryList(QString fileName); +QString getFilenameFromPath(QString line); +QString lineSplitter(QString line, const char* signs, bool first); +QString colonSplitter(QString line, bool first); +QString getUserName(); +QString getFullUsername(); +bool fileExists(QString fileName); +QString getHomeDir(); +QString getPolicyDir(); +QString getPolicyFilePath(QString fileName); +bool policyFileExists(QString fileName); +void createPolicyFiles(); +void createPolicyDir(); +QString readPassFromPassFile(); +bool getAllowed(); + +QString int2String(int intInt); +int string2Int(QString string); +int string2Int(QString string); +//} // end namespace util + +//std::list<VNCConnectInfo*> readFile(char* fileName); +//void makeArgs(char* line, int* count, char** arguments); +//VNCConnectInfo* getConInfo(QString line); + + + + diff --git a/src/util/vncClientThread.cpp b/src/util/vncClientThread.cpp new file mode 100644 index 0000000..bb1d457 --- /dev/null +++ b/src/util/vncClientThread.cpp @@ -0,0 +1,249 @@ +/* + # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of + # Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + # ----------------------------------------------------------------------------- + # vncClientThread.cpp + # - Connection to remove vnc server + # - Emits Qt signal on framebuffer updates + # ----------------------------------------------------------------------------- + */ + +#include "vncClientThread.h" + +VNCClientThread::VNCClientThread(QString host, int port, QString passwd, + int quality, int updatefreq) : + QThread(), _frameBuffer(0) +{ + _host = host; + _port = port; + _passwd = passwd; + _quality = quality; + _updatefreq = updatefreq; + terminate = false; + _client = NULL; + _connected = false; +} + +VNCClientThread::~VNCClientThread() +{ + if (this->isRunning()) this->wait(2000); + if (_frameBuffer) delete[] _frameBuffer; + _frameBuffer = NULL; + if (_client != NULL) + { + ::close(_client->sock); + _client->frameBuffer = NULL; + rfbClientCleanup(_client); + _client = NULL; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Public + +void VNCClientThread::run() +{ + qDebug("[%s] VNC client started.", metaObject()->className()); + qDebug("[%s] Host: '%s' Port: %i Passwd: '%s' Quality: %i", + metaObject()->className(), qPrintable(_host), _port, + qPrintable(_passwd), _quality); + + // setup network + _client = rfbGetClient(8, 3, 4); + _client->MallocFrameBuffer = frameBufferHandler; + _client->canHandleNewFBSize = true; + _client->serverHost = strdup(_host.toUtf8().constData()); + _client->desktopName = NULL; + _client->serverPort = _port; + _client->GetPassword = passwdHandler; + _client->GotFrameBufferUpdate = updateImage; + _client->frameBuffer = NULL; + + // save this instance in vnc-struct for callbacks + rfbClientSetClientData(_client, 0, this); + + // start client + if (!rfbInitClient(_client, NULL, NULL)) + { + _client = NULL; // !!! <- if you don't do this you will get a segfault + return; // later when you try to clean up _client, as rfbInitClient already did so + } + + qDebug("[%s] Connection successful!", metaObject()->className()); + + // Main VNC event loop + while (!terminate) + { + _connected = true; + const int i = WaitForMessage(_client, 500); // its usec, not msec + if (i < 0) + break; + if (i) if (!HandleRFBServerMessage(_client)) + break; + + /* + //work yourself through event queue and fire every event... + while (!_eventQueue.isEmpty()) { + SomeEvent* event = _eventQueue.dequeue(); + event->fire(_client); + delete event; + }*/ + + this->msleep(_updatefreq); + } + + // cleanup + ::close(_client->sock); + + qDebug("[%s] VNC client stopped.", metaObject()->className()); + _connected = false; +} + +QImage VNCClientThread::getImage() +{ + return _img; +} + +QSize VNCClientThread::getSize() +{ + return _clientSize; +} + +int VNCClientThread::getUpdatefreq() +{ + if (_updatefreq > 0) + return _updatefreq; + return 500; +} + +void VNCClientThread::setUpdatefreq(int updatefreq) +{ + _updatefreq = updatefreq; +} + +QString VNCClientThread::getDesktopName() +{ + if (_client == NULL || _client->desktopName == NULL) return QString(); + return QString(_client->desktopName); +} + +char* VNCClientThread::passwdHandler(rfbClient *client) +{ + VNCClientThread* t = (VNCClientThread*) rfbClientGetClientData(client, 0); + return strdup(t->_passwd.toLocal8Bit()); +} + +rfbBool VNCClientThread::frameBufferHandler(rfbClient *client) +{ + VNCClientThread *t = (VNCClientThread*) rfbClientGetClientData(client, 0); + const int width = client->width, height = client->height, depth = + client->format.bitsPerPixel; + const int size = width * height * (depth / 8); + qDebug("[%s] Remote desktop: %ix%ix%i", t->metaObject()->className(), + width, height, depth); + + if (t->_frameBuffer) + delete[] t->_frameBuffer; + + t->_frameBuffer = new uint8_t[size]; + client->frameBuffer = t->_frameBuffer; + memset(client->frameBuffer, '\0', size); + client->format.bitsPerPixel = 32; + client->format.redShift = 16; + client->format.greenShift = 8; + client->format.blueShift = 0; + client->format.redMax = 0xff; + client->format.greenMax = 0xff; + client->format.blueMax = 0xff; + + const int quality = t->_quality; + switch (quality) + { + case VNCClientThread::HIGH: + client->appData.useBGR233 = 0; + client->appData.encodingsString = "copyrect hextile raw"; + client->appData.compressLevel = 0; + client->appData.qualityLevel = 9; + client->appData.scaleSetting = 10; // FIXME: Doesn't work + break; + case VNCClientThread::MEDIUM: + client->appData.useBGR233 = 0; + client->appData.encodingsString + = "tight zrle ultra copyrect hextile zlib corre rre raw"; + client->appData.compressLevel = 5; + client->appData.qualityLevel = 7; + client->appData.scaleSetting = 10; + break; + case VNCClientThread::LOW: + default: + client->appData.useBGR233 = 1; + client->appData.encodingsString + = "tight zrle ultra copyrect hextile zlib corre rre raw"; + client->appData.compressLevel = 9; + client->appData.qualityLevel = 1; + client->appData.scaleSetting = 10; + break; + } + SetFormatAndEncodings(client); + + t->_clientSize = QSize(width, height); + + // If something stops working with VNC images/updates, move these two + // commands back tp updateImage + const QImage img = QImage(client->frameBuffer, client->width, + client->height, QImage::Format_RGB32); + t->_img = img; + // <> + + return true; +} + +void VNCClientThread::updateImage(rfbClient* client, int x, int y, int w, int h) +{ + VNCClientThread* t = (VNCClientThread*) rfbClientGetClientData(client, 0); + emit t->imageUpdated(x, y, w, h); +} + +/* rfbClient* VNCClientThread::getRfbClient(){ + return _client; +}*/ + +SomeEvent::~SomeEvent() +{ +} + +void PointerEvent::fire(rfbClient* cl) +{ + SendPointerEvent(cl, _x, _y, _buttonMask); +} + +void KeyEvent::fire(rfbClient* cl) +{ + SendKeyEvent(cl, _key, _pressed); +} + +void VNCClientThread::mouseEvent(int x, int y, int buttonMask) +{ + //QMutexLocker lock(&mutex); + if (terminate) + return; + + _eventQueue.enqueue(new PointerEvent(x, y, buttonMask)); +} + +void VNCClientThread::keyEvent(int key, bool pressed) +{ + //QMutexLocker lock(&mutex); + if (terminate) + return; + + _eventQueue.enqueue(new KeyEvent(key, pressed)); +} diff --git a/src/util/vncClientThread.h b/src/util/vncClientThread.h new file mode 100644 index 0000000..10980b8 --- /dev/null +++ b/src/util/vncClientThread.h @@ -0,0 +1,114 @@ +/* + # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of + # Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + */ + +#ifndef VNCCLIENTTHREAD_H_ +#define VNCCLIENTTHREAD_H_ + +#include <QtCore> +#include <QtGui/QImage> + +extern "C" +{ +#include <rfb/rfbclient.h> +} + +class SomeEvent +{ +public: + virtual ~SomeEvent(); + + virtual void fire(rfbClient*) = 0; +}; + +class KeyEvent : public SomeEvent +{ +public: + KeyEvent(int key, int pressed) + : _key(key), _pressed(pressed) {} + + void fire(rfbClient*); + +private: + int _key; + int _pressed; +}; + +class PointerEvent : public SomeEvent +{ +public: + PointerEvent(int x, int y, int buttonMask) + : _x(x), _y(y), _buttonMask(buttonMask) {} + + void fire(rfbClient*); + +private: + int _x; + int _y; + int _buttonMask; +}; + +class VNCClientThread: public QThread +{ + Q_OBJECT + +public: + VNCClientThread(QString host, int port, QString passwd, int quality, int updatefreq = 0); + ~VNCClientThread(); + + void run(); + QImage getImage(); + QSize getSize(); + int getUpdatefreq(); + void setUpdatefreq(int updatefreq); + QString getDesktopName(); + void mouseEvent(int x, int y, int buttonMask); + void keyEvent(int key, bool pressed); + bool isConnected() + { + return _connected; + } + + + static void updateImage(rfbClient *client, int x, int y, int w, int h); + static char* passwdHandler(rfbClient *client); + static rfbBool frameBufferHandler(rfbClient *client); + //rfbClient* getRfbClient(); + + bool terminate; + + int const static HIGH = 0; + int const static MEDIUM = 1; + int const static LOW = 2; + +Q_SIGNALS: + void imageUpdated(int x, int y, int w, int h); + +private: + rfbClient *_client; + uint8_t *_frameBuffer; + + QString _host; + int _port; + QString _passwd; + int _quality; + int _updatefreq; + QQueue<SomeEvent* > _eventQueue; + + QImage _img; + QSize _clientSize; + + bool _connected; + +}; + +#endif /* VNCCLIENTTHREAD_H_ */ |