From 240faf6f2024313d913db5d758d9178ea4806603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Mechnich?= Date: Thu, 16 Aug 2018 17:37:01 +0200 Subject: [PATCH 1/9] monitor: use utf-8 encoding explicitly --- monitor/monitor | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/monitor/monitor b/monitor/monitor index 45312f9..5892b21 100755 --- a/monitor/monitor +++ b/monitor/monitor @@ -24,12 +24,12 @@ if path is None: frags =[ i for i in path.split('/') if i and len(i) ] if len(frags) != 2: error("Malformed payload in URL: %s" % path) - -action = base64.b64decode(frags.pop()).decode('utf-8') + +action = base64.b64decode(frags.pop()).decode('utf-8').strip() palma_host = frags.pop() if not os.path.isdir(logdir): os.mkdir(logdir) logfile = palma_host + '.log' -with open(os.path.join(logdir,logfile), 'a') as f: +with open(os.path.join(logdir,logfile), 'a', encoding='utf-8') as f: print(timestamp(), action, file=f) From 535a9d70b6e2d02c62c194b98b893bffc19e3fd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Mechnich?= Date: Thu, 16 Aug 2018 17:37:31 +0200 Subject: [PATCH 2/9] added example Xorg config for HiDPI monitor --- examples/90-monitor.conf | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 examples/90-monitor.conf diff --git a/examples/90-monitor.conf b/examples/90-monitor.conf new file mode 100644 index 0000000..6ea8eed --- /dev/null +++ b/examples/90-monitor.conf @@ -0,0 +1,4 @@ +Section "Monitor" + Identifier "" + DisplaySize 677 381 # In millimeters +EndSection From a43943eff5dbba51fa15bc3730bc0e813b636494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Mechnich?= Date: Thu, 16 Aug 2018 17:38:09 +0200 Subject: [PATCH 3/9] initial version of palma_analyze --- monitor/palma_analyze | 104 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100755 monitor/palma_analyze diff --git a/monitor/palma_analyze b/monitor/palma_analyze new file mode 100755 index 0000000..5bcb187 --- /dev/null +++ b/monitor/palma_analyze @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 + +import argparse, datetime, os, re, sys +from enum import Enum + +class States(Enum): + NONE = 0 + CONNECTED = 1 + IDLE = 2 + +parser = argparse.ArgumentParser( + description=os.path.basename(sys.argv[0]) + + ' - analyze PalMA monitoring log files', +) +parser.add_argument("logfile", nargs='+', + help="at least one log file") + +args = parser.parse_args() + +def print_error_and_exit(error): + print(line) + print(error) + print(lastsession) + sys.exit(1) + +alldata = {} +for l in args.logfile: + with open(l,'r') as f: + print("Processing", l) + filedata = {} + state = States.NONE + lastsession = "" + currentsession = None + lasttimestamp = None + timestamp = None + for line in f.readlines(): + if not len(line.strip()): continue + timestamp = datetime.datetime.strptime( + line.split()[0], "%Y-%m-%dT%H:%M:%S" + ) + if lasttimestamp: + if (timestamp - lasttimestamp).seconds > 60*60*6: + if state is States.CONNECTED: + if currentsession: + currentsession["end"] = lasttimestamp + filedata[currentsession["start"]] = currentsession + currentsession = None + state = States.IDLE + lastsession = "" + lasttimestamp = timestamp + + if re.search(r"connecting first user",line): + if state is States.CONNECTED: + print_error_and_exit("Parse error: already connected") + else: + state = States.CONNECTED + lastsession = line + currentsession = { + "start": timestamp, + "nuser": 1, + } + elif re.search(r"logout.php: logout",line): + if not state is States.CONNECTED: + pass #print_error_and_exit("Parse error: 'logout.php: logout', but noone connected") + if currentsession: + currentsession["end"] = timestamp + filedata[currentsession["start"]] = currentsession + currentsession = None + state = States.IDLE + lastsession = "" + elif re.search(r"timeout reached",line): + if not state is States.CONNECTED: + pass #print_error_and_exit("Parse error: timeout reached, but noone connected") + if currentsession: + currentsession["end"] = timestamp + filedata[currentsession["start"]] = currentsession + currentsession = None + state = States.IDLE + lastsession = "" + elif re.search(r"last user disconnected",line): + if not state is States.CONNECTED: + pass #print_error_and_exit("Parse error: last user disconnected, but noone connected") + if currentsession: + currentsession["end"] = timestamp + filedata[currentsession["start"]] = currentsession + currentsession = None + state = States.IDLE + lastsession = "" + elif re.search(r"access granted for user",line): + if state is States.CONNECTED: + currentsession['nuser'] = currentsession['nuser'] + 1 + else: + if state is States.CONNECTED: + lastsession += line + alldata[l] = filedata.copy() + +print() +for station,data in sorted(alldata.items()): + print(station) + for k,v in sorted(data.items(),key=lambda item: item[1]['start']): + length = v['end']-v['start'] + print(" %s length: %s %d user(s)" % (k,length,v['nuser'])) + #print(" ", v) + print() From 981ac75d67b7e496cd4c99a19a53301e4eb1fd80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Mechnich?= Date: Thu, 4 Oct 2018 18:17:31 +0200 Subject: [PATCH 4/9] major overhaul of palma_analyze --- monitor/palma_analyze | 252 +++++++++++++++++++++++++++--------------- 1 file changed, 161 insertions(+), 91 deletions(-) diff --git a/monitor/palma_analyze b/monitor/palma_analyze index 5bcb187..0037a30 100755 --- a/monitor/palma_analyze +++ b/monitor/palma_analyze @@ -7,98 +7,168 @@ class States(Enum): NONE = 0 CONNECTED = 1 IDLE = 2 + -parser = argparse.ArgumentParser( - description=os.path.basename(sys.argv[0]) + - ' - analyze PalMA monitoring log files', -) -parser.add_argument("logfile", nargs='+', - help="at least one log file") - -args = parser.parse_args() - -def print_error_and_exit(error): - print(line) - print(error) - print(lastsession) - sys.exit(1) +class PalmaSession(object): + def __init__(self, start): + self.__dict__ = { + 'start': start, + 'end': None, + 'nuser': 0, + } + + +class PalmaLogfile(object): + def __init__(self, filename): + self.__dict__ = { + 'filename': filename, + 'data': {}, + 'lstamp': None, + 'timeout': 60*60*6, + 'state': States.IDLE, + 'current': None, + 'logtext': '', + } + + + def gapDetected(self, timestamp): + """handle big gaps in logfiles ( > 6 hrs).""" + return self.lstamp and (timestamp - self.lstamp).total_seconds() > self.timeout + -alldata = {} -for l in args.logfile: - with open(l,'r') as f: - print("Processing", l) - filedata = {} - state = States.NONE - lastsession = "" - currentsession = None - lasttimestamp = None - timestamp = None - for line in f.readlines(): - if not len(line.strip()): continue - timestamp = datetime.datetime.strptime( - line.split()[0], "%Y-%m-%dT%H:%M:%S" - ) - if lasttimestamp: - if (timestamp - lasttimestamp).seconds > 60*60*6: - if state is States.CONNECTED: - if currentsession: - currentsession["end"] = lasttimestamp - filedata[currentsession["start"]] = currentsession - currentsession = None - state = States.IDLE - lastsession = "" - lasttimestamp = timestamp + def newSession(self, timestamp): + if self.state is States.CONNECTED: + self.error(timestamp, "Parse error: already connected") + self.endSession() + self.current = PalmaSession(timestamp) + self.state = States.CONNECTED + self.addUser() + + + def addUser(self): + if not self.state is States.CONNECTED: + return + if not self.current: + return + self.current.nuser += 1 + + + def endSession(self, timestamp=None, ignoreState=False): + if timestamp is None: + timestamp = self.lstamp + else: + if self.gapDetected(timestamp): + timestamp = self.lstamp + if not self.state is States.CONNECTED and not ignoreState: + return + if self.current: + self.current.end = timestamp + self.data[self.current.start] = self.current + self.current = None + self.state = States.IDLE + + + def error(self, timestamp, error): + print(self.filename, timestamp, error) + sys.exit(1) + + + def addLine(self, line): + if self.state is States.CONNECTED: + self.logtext += line + - if re.search(r"connecting first user",line): - if state is States.CONNECTED: - print_error_and_exit("Parse error: already connected") + def printDetails(self,indent=" "*2): + for k,v in sorted(self.data.items(),key=lambda item: item[1].start): + length = v.end-v.start + print("%s%s length: %s %d user(s)" % (indent,k,length,v.nuser)) + + + def printSummary(self): + totLength = datetime.timedelta() + totUsers = 0 + for k,v in self.data.items(): + totLength += v.end-v.start + totUsers += v.nuser + print("%-40s %8s %5d %20s" % + (os.path.basename(self.filename), len(self.data), + totUsers, totLength) + ) + + +class PalmaAnalyzer(object): + def __init__(self): + self.__dict__ = { + 'alldata': {}, + } + + + def parseCmdLine(self): + parser = argparse.ArgumentParser( + description=os.path.basename(sys.argv[0]) + + ' - analyze PalMA monitoring log files', + ) + parser.add_argument("-s", "--summary", action="store_true", + help="print summary") + parser.add_argument("logfile", nargs='+', + help="at least one log file") + self.args = parser.parse_args() + + + def processFile(self,filename): + with open(filename,'r') as f: + print("Processing", filename) + logfile = PalmaLogfile(filename) + for line in f.readlines(): + # skip empty lines + if not len(line.strip()): continue + + tstamp = datetime.datetime.strptime( + line.split()[0], "%Y-%m-%dT%H:%M:%S" + ) + if logfile.gapDetected(tstamp): + logfile.endSession() + + if re.search(r"connecting first user",line): + logfile.newSession(tstamp) + elif re.search(r"logout.php: logout",line): + logfile.endSession(tstamp, ignoreState=True) + elif re.search(r"timeout reached",line): + logfile.endSession(tstamp, ignoreState=True) + elif re.search(r"last user disconnected",line): + logfile.endSession(tstamp, ignoreState=True) + elif re.search(r"bash_startx: starting login screen",line): + logfile.endSession(tstamp, ignoreState=True) + elif re.search(r"access granted for user",line): + logfile.addUser() else: - state = States.CONNECTED - lastsession = line - currentsession = { - "start": timestamp, - "nuser": 1, - } - elif re.search(r"logout.php: logout",line): - if not state is States.CONNECTED: - pass #print_error_and_exit("Parse error: 'logout.php: logout', but noone connected") - if currentsession: - currentsession["end"] = timestamp - filedata[currentsession["start"]] = currentsession - currentsession = None - state = States.IDLE - lastsession = "" - elif re.search(r"timeout reached",line): - if not state is States.CONNECTED: - pass #print_error_and_exit("Parse error: timeout reached, but noone connected") - if currentsession: - currentsession["end"] = timestamp - filedata[currentsession["start"]] = currentsession - currentsession = None - state = States.IDLE - lastsession = "" - elif re.search(r"last user disconnected",line): - if not state is States.CONNECTED: - pass #print_error_and_exit("Parse error: last user disconnected, but noone connected") - if currentsession: - currentsession["end"] = timestamp - filedata[currentsession["start"]] = currentsession - currentsession = None - state = States.IDLE - lastsession = "" - elif re.search(r"access granted for user",line): - if state is States.CONNECTED: - currentsession['nuser'] = currentsession['nuser'] + 1 - else: - if state is States.CONNECTED: - lastsession += line - alldata[l] = filedata.copy() - -print() -for station,data in sorted(alldata.items()): - print(station) - for k,v in sorted(data.items(),key=lambda item: item[1]['start']): - length = v['end']-v['start'] - print(" %s length: %s %d user(s)" % (k,length,v['nuser'])) - #print(" ", v) - print() + logfile.addLine(line) + logfile.lstamp = tstamp + self.alldata[filename] = logfile + + + def run(self): + for logfile in self.args.logfile: + self.processFile(logfile) + + + def print(self): + if self.args.summary: + print("%-40s %-8s %-5s %-20s" % + ("Station", "Sessions", "Users", "Total Time") + ) + for station,logfile in sorted(self.alldata.items()): + logfile.printSummary() + else: + print() + for station,logfile in sorted(self.alldata.items()): + print(station) + logfile.printDetails() + print() + + +if __name__ == '__main__': + analyzer = PalmaAnalyzer() + analyzer.parseCmdLine() + analyzer.run() + analyzer.print() From 9eb251afc9f3311a1319aab9fcd9397c61859923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Mechnich?= Date: Thu, 15 Nov 2018 18:03:10 +0100 Subject: [PATCH 5/9] corrected namespaces in SSVNCDaemon.php --- SSVNCDaemon.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SSVNCDaemon.php b/SSVNCDaemon.php index af4027b..cb99791 100644 --- a/SSVNCDaemon.php +++ b/SSVNCDaemon.php @@ -197,7 +197,7 @@ protected function sendVncWindowToNuc($id, $vncclient) $vnc_id = $vncclient["hostname"] . "-" . $id; - $db = new palma\DBConnector(); + $db = new DBConnector(); // already existing in db? $clients_in_db = array(); @@ -227,7 +227,7 @@ protected function sendVncWindowToNuc($id, $vncclient) if (!(in_array($vnc_id, $clients_in_db))) { // print("\n[Daemon]: insert $vnc_id into db"); - $dt = new DateTime(); + $dt = new \DateTime(); $date = $dt->format('Y-m-d H:i:s'); $window = array( From 743cc8a04b0f07dd1ab22803bb2ab1249d5afae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Mechnich?= Date: Thu, 15 Nov 2018 18:03:37 +0100 Subject: [PATCH 6/9] updated Debian package dependencies --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index c2df6dd..f168b46 100644 --- a/debian/control +++ b/debian/control @@ -8,7 +8,7 @@ Homepage: https://github.com/UB-Mannheim/PalMA Package: palma Architecture: all -Depends: ${misc:Depends}, palma-nginx | palma-apache, midori | dwb, feh, libreoffice, ssvnc, x11vnc, zathura, wmctrl, xdotool, openbox, sqlite3, php, php-curl, php-gd, php-intl, php-sqlite3, php-mbstring, gettext, libavcodec-extra, xserver-xorg, unclutter +Depends: ${misc:Depends}, palma-nginx | palma-apache, midori | dwb, feh, libreoffice, ssvnc, x11vnc, zathura, wmctrl, xdotool, openbox, sqlite3, php, php-curl, php-gd, php-intl, php-sqlite3, php-mbstring, gettext, libavcodec-extra | libavcodec58 , xserver-xorg, unclutter Description: PalMA – share a team monitor PalMA enables people to share several contents on one monitor. Users can display PDF files, office files, images, videos, websites and or From 090e8782cf0072c08f8c771e196a7b1e8a7e00bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Mechnich?= Date: Thu, 15 Nov 2018 18:03:56 +0100 Subject: [PATCH 7/9] fixed timeout issues with nginx --- debian/palma-apache.postinst | 2 ++ debian/palma-nginx.postinst | 3 +++ examples/palma.nginx.conf | 1 + examples/palma.php.ini | 2 ++ 4 files changed, 8 insertions(+) diff --git a/debian/palma-apache.postinst b/debian/palma-apache.postinst index 8e6f723..2092a32 100644 --- a/debian/palma-apache.postinst +++ b/debian/palma-apache.postinst @@ -28,6 +28,8 @@ case "$1" in cat > $confdir/palma.ini < $confdir/palma.ini < Date: Thu, 15 Nov 2018 18:44:05 +0100 Subject: [PATCH 8/9] forcefully overwrite PalMA configuration files for apache, nginx and php --- debian/palma-apache.postinst | 8 ++------ debian/palma-nginx.postinst | 14 +++----------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/debian/palma-apache.postinst b/debian/palma-apache.postinst index 2092a32..970420a 100644 --- a/debian/palma-apache.postinst +++ b/debian/palma-apache.postinst @@ -23,17 +23,13 @@ case "$1" in # create php configuration for PalMA confdir=/etc/php/${php_vers}/apache2/conf.d - if [ ! -e $confdir/palma.ini ]; then - mkdir -p $confdir - cat > $confdir/palma.ini < $confdir/palma.ini < $confdir/palma.ini < $confdir/palma.ini < $confdir/palma < $confdir/palma < Date: Thu, 15 Nov 2018 19:25:32 +0100 Subject: [PATCH 9/9] updated debian/changelog to v1.4.2 --- debian/changelog | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/debian/changelog b/debian/changelog index b293f4e..399b816 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +palma (1.4.2) unstable; urgency=medium + + * forcefully overwrite PalMA configuration files for apache, nginx and php + * fixed timeout issues with nginx + * updated Debian package dependencies + * corrected namespaces in SSVNCDaemon.php + + -- Jörg Mechnich Thu, 15 Nov 2018 18:27:42 +0100 + palma (1.4.1) unstable; urgency=medium * fixed last_activity monitoring