--- /dev/null
+from twisted.internet.protocol import DatagramProtocol
+from twisted.internet import reactor
+from twisted.internet import reactor
+from time import strftime, strptime, localtime
+from os import uname
+
+from Screens.MessageBox import MessageBox
+from Tools import Notifications
+
+from GrowleeConnection import emergencyDisable
+from . import NOTIFICATIONID
+
+SYSLOG_UDP_PORT = 514
+
+FACILITY = {
+ 'kern': 0, 'user': 1, 'mail': 2, 'daemon': 3,
+ 'auth': 4, 'syslog': 5, 'lpr': 6, 'news': 7,
+ 'uucp': 8, 'cron': 9, 'authpriv': 10, 'ftp': 11,
+ 'local0': 16, 'local1': 17, 'local2': 18, 'local3': 19,
+ 'local4': 20, 'local5': 21, 'local6': 22, 'local7': 23,
+}
+
+SEVERITY = {
+ 'emerg': 0, 'alert':1, 'crit': 2, 'err': 3,
+ 'warning': 4, 'notice': 5, 'info': 6, 'debug': 7
+}
+
+reverse = lambda map: dict(zip(map.values(), map.keys()))
+
+SEVERITYMAP = {
+ MessageBox.TYPE_YESNO: SEVERITY['debug'],
+ MessageBox.TYPE_INFO: SEVERITY['info'],
+ MessageBox.TYPE_WARNING: SEVERITY['warning'],
+ MessageBox.TYPE_ERROR: SEVERITY['err'],
+}
+
+class SyslogNetworkProtocol(DatagramProtocol):
+ addr = None
+ def __init__(self, host):
+ self.host = host
+
+ def gotIP(self, ip):
+ self.addr = (ip, SYSLOG_UDP_PORT)
+
+ def noIP(self, error):
+ print "--------------------------------", error
+ emergencyDisable()
+
+ def startProtocol(self):
+ reactor.resolve(self.host.address.value).addCallback(self.gotIP).addErrback(self.noIP)
+
+ def sendNotification(self, title='No title.', description='No message.', priority=0):
+ if not self.transport or not self.addr or not self.host.enable_outgoing.value:
+ return
+
+ ltime = localtime()
+ day = strftime("%d", ltime)
+ if day[0] == "0":
+ day = " " + day[1:]
+ value = strftime("%b %%s %H:%M:%S", ltime)
+ timestamp = value % (day,)
+ payload = "<%d>%s %s growlee: (%s) %s" % (FACILITY['local0'] * 8 + SEVERITYMAP[priority], timestamp, uname()[1], title, description.replace('\n', ' '),)
+ self.transport.write(payload, self.addr)
+
+ def datagramReceived(self, data, addr):
+ if not self.host.enable_incoming.value:
+ return
+
+ Len = len(data)
+ if Len > 1024: # invalid according to rfc
+ return
+
+ # read prio field
+ prio, data = data.split('>', 1)
+ prio = int(prio[1:])
+ facility, severity = divmod(prio, 8) # just the ids
+ #facility = reverse(FACILITY)[facility]
+ type = reverse(SEVERITYMAP).get(severity, MessageBox.TYPE_ERROR)
+
+ # parse remaining header
+ try:
+ # try to parse timestamp to determine validity
+ timestamp = strptime(payload[:15], '%b %d %H:%M:%S')
+ except ValueError:
+ message = payload
+ else:
+ hostname, payload = payload[16:].split(' ', 1)
+ # NOTE: we could re-process timestamp to get a customized display format,
+ # but lets just keep this for now
+ message = hostname + '@' + payload[:15] + ':' + payload
+
+ Notifications.AddNotificationWithID(
+ NOTIFICATIONID,
+ MessageBox,
+ text = message,
+ type = type,
+ timeout = 10, # XXX: un-hardcode timeout?
+ close_on_any_key = True,
+ )
+
+class SyslogAbstraction:
+ def __init__(self, host):
+ self.syslog = SyslogNetworkProtocol(host)
+ self.serverPort = reactor.listenUDP(SYSLOG_UDP_PORT, self.syslog)
+
+ def sendNotification(self, title='No title.', description='No description.', priority=-1, timeout=-1):
+ self.syslog.sendNotification(title=title, description=description, priority=priority)
+
+ def stop(self):
+ return self.serverPort.stopListening()
s.enable_outgoing = ConfigYesNo(default=False)
s.address = ConfigText(fixed_size=False)
s.password = ConfigPassword()
- s.protocol = ConfigSelection(default="growl", choices=[("growl", "Growl"), ("snarl", "Snarl"), ("prowl", "Prowl")])
+ s.protocol = ConfigSelection(default="growl", choices=[("growl", "Growl"), ("snarl", "Snarl"), ("prowl", "Prowl"), ("syslog", "Syslog UDP")])
s.level = ConfigSelection(default="-1", choices=[("-1", _("Low (Yes/No)")), ("0", _("Normal (Information)")), ("1", _("High (Warning)")), ("2", _("Highest (Emergency)"))])
s.blacklist = ConfigSet(choices=[])
config.plugins.growlee.hosts.append(s)