--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/.eric4project/daemon.e4q Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE UserProject SYSTEM "UserProject-4.0.dtd">
+<!-- eric4 user project file for project daemon -->
+<!-- Saved: 2009-10-10, 13:26:41 -->
+<!-- Copyright (C) 2009 Sandro Knauß, bugs@sandroknauss.de -->
+<UserProject version="4.0">
+</UserProject>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/.eric4project/iro.e4p Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE UserProject SYSTEM "UserProject-4.0.dtd">
+<!-- eric4 user project file for project iro -->
+<!-- Saved: 2009-10-10, 13:26:41 -->
+<!-- Copyright (C) 2009 Sandro Knauß, bugs@sandroknauss.de -->
+<UserProject version="4.0">
+</UserProject>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/.eric4project/iro.e4t Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Tasks SYSTEM "Tasks-4.2.dtd">
+<!-- eric4 tasks file for project iro -->
+<!-- Saved: 2009-10-16, 01:34:46 -->
+<Tasks version="4.2">
+</Tasks>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/MyIro_daemon Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,44 @@
+#! /bin/sh
+NAME="IRO"
+DEAMON=/home/sandy/svn/daemon/MyIro
+DEAMON_OPTS=""
+PID=/home/sandy/var/run/$NAME.pid
+
+test -x $DEAMON || exit 0
+
+. /lib/lsb/init-functions
+
+case "$1" in
+ start)
+ log_daemon_msg "Starting $NAME" $NAME
+ if start-stop-daemon --start --quiet --oknodo --pidfile $PID --make-pidfile --background --chuid sandy --group sandy --chdir /home/sandy/svn/iro --startas $DEAMON -- $DEAMON_OPTS; then
+ log_end_msg 0
+ else
+ log_end_msg 1
+ fi
+ ;;
+ stop)
+ log_daemon_msg "Stopping $NAME" $NAME
+ if start-stop-daemon --stop --quiet --oknodo --pidfile $PID; then
+ log_end_msg 0
+ else
+ log_end_msg 1
+ fi
+ ;;
+
+ restart)
+ $0 stop
+ sleep 1
+ $0 start
+ ;;
+
+ status)
+ status_of_proc -p $PID $DEAMON $NAME && exit 0 || exit $?
+ ;;
+
+ *)
+ log_action_msg "Usage: $0 {start|stop|restart|status}"
+ exit 1
+esac
+
+exit 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/__init__.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,1 @@
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/anbieter/FAX_de.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+#Copyright (C) 2009 Sandro Knauß <bugs@sandroknauss.de>
+
+#This program is free software; you can redistribute it and/or modify it under the terms
+#of the GNU General Public License as published by the Free Software Foundation;
+#either version 3 of the License, or any later version.
+#This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+#without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#See the GNU General Public License for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from smtp import SMTP
+from geonet import geonet
+from telnumber import telnumber
+
+class FAX_de(geonet):
+ section="FAX_de"
+ default_conf="iro.conf"
+ max_recipients=50
+
+ def __init__(self):
+ self.smtp=SMTP(self.default_conf,self.section)
+
+ def createMailaddress(produkt,number):
+ try:
+ tel=telnumber(number)
+ return "%s00%s%s@fax.de" %(produkt,tel.land,tel.number)
+ except:
+ return number
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/anbieter/__init__.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+#Copyright (C) 2009 Sandro Knauß <bugs@sandroknauss.de>
+
+#This program is free software; you can redistribute it and/or modify it under the terms
+#of the GNU General Public License as published by the Free Software Foundation;
+#either version 3 of the License, or any later version.
+#This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+#without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#See the GNU General Public License for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from sipgate import sipgate
+from geonet import geonet
+from FAX_de import FAX_de
+from smtp import SMTP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/anbieter/anbieter.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+#Copyright (C) 2009 Sandro Knauß <bugs@sandroknauss.de>
+
+#This program is free software; you can redistribute it and/or modify it under the terms
+#of the GNU General Public License as published by the Free Software Foundation;
+#either version 3 of the License, or any later version.
+#This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+#without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#See the GNU General Public License for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+class anbieter:
+ default_conf = '' # override this
+ section = 'anbieter' # override this
+
+ def sendSMS(self,sms,recipients):
+ pass
+ def sendFAX(self,fax,recipients):
+ pass
+ def sendMail(self,mail,recipients):
+ pass
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/anbieter/geonet.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+#Copyright (C) 2009 Sandro Knauß <bugs@sandroknauss.de>
+
+#This program is free software; you can redistribute it and/or modify it under the terms
+#of the GNU General Public License as published by the Free Software Foundation;
+#either version 3 of the License, or any later version.
+#This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+#without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#See the GNU General Public License for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from smtp import SMTP
+from anbieter import anbieter
+from telnumber import telnumber
+
+from email import Encoders
+from email.MIMEMultipart import MIMEMultipart
+from email.MIMEBase import MIMEBase
+from email.MIMEText import MIMEText
+
+class Mail(MIMEMultipart):
+ def __init__(self,send_from,header,cont,attachments):
+ MIMEMultipart.__init__(self)
+ self['From'] = send_from
+ self['Subject']=header
+ self.attach(MIMEText(cont))
+ for attachment in attachments:
+ part = MIMEBase('application', mimetypes.guess_type(attachment)[0])
+ part.set_payload( open(attachment,"rb").read() )
+ Encoders.encode_base64(part)
+ art.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
+ self.attach(part)
+
+class geonet(anbieter):
+ section="geonet"
+ default_conf="iro.conf"
+ max_recipients=50
+
+ def __init__(self):
+ self.smtp=SMTP(self.default_conf,self.section)
+
+ def createMailaddress(produkt,number):
+ try:
+ tel=telnum(number)
+ return "%s%s@%s.geonet.de" %(tel.land,tel.number,produkt)
+ except:
+ return number
+
+ def sendSMS(self,sms,recipients):
+ recps=[]
+ for recpipient in recipients:
+ recps.append(self.createMailadress(recpipient))
+ self.sendMail(Mail(self.smtp.send_from,sms.content,"",[]),recps)
+
+ def sendFAX(self,fax,recipients):
+ recps=[]
+ for recpipient in recipients:
+ recps.append(self.createMailadress(recpipient))
+ self.sendMail(Mail(self.smtp.send_from,"","",fax.attachments),recps)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/anbieter/sipgate.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,140 @@
+# -*- coding: utf-8 -*-
+#Copyright (C) 2009 Sandro Knauß <bugs@sandroknauss.de>
+
+#This program is free software; you can redistribute it and/or modify it under the terms
+#of the GNU General Public License as published by the Free Software Foundation;
+#either version 3 of the License, or any later version.
+#This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+#without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#See the GNU General Public License for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+
+from anbieter import anbieter
+from telnumber import telnumber, NotATelNumber
+import ConfigParser
+import xmlrpclib
+import base64
+
+class NoValidStatusCode(Exception):
+ pass
+
+class sipgate(anbieter):
+ """
+ s. auch http://www.tuxad.com/sipgate.html
+ und http://lists.sipgate.net/pipermail/sipgate-developers/2007-September/000016.html
+ """
+ section="sipgate"
+ url="https://%s:%s@samurai.sipgate.net/RPC2"
+ def __init__(self,user="",password=""):
+ self.user=user
+ self.password=password
+
+ def read_basic_config(self,filename):
+ """Read basic options from the config file"""
+ cp = ConfigParser.ConfigParser()
+ cp.read([filename])
+ self.user=cp.get(self.section, 'user')
+ self.password=cp.get(self.section, 'password')
+
+ def sendSMS(self,sms,recipients):
+ """send SMS with $sms to $recipients"""
+ args={
+ "TOS" : "text",
+ "Content" : sms.content
+ }
+ self.__send(args,recipients)
+
+ def sendFAX(self,fax,recipients):
+ """send the PDF file $fax to $recipients"""
+ pdf=open(fax.attachments[0],"rb")
+ args={
+ "TOS" : "fax",
+ "Content" : base64.encodestring(pdf.read())
+ }
+ pdf.close()
+ self.__send(args,recipients)
+
+ def __connect(self):
+ """connect to sipgate XMLRPC Server"""
+ self.samurai=xmlrpclib.Server(self.url%(self.user,self.password)).samurai
+ args_identify = {
+ "ClientName" : "anbieter.py",
+ "ClientVersion" : "V1.0",
+ "ClientVendor" : "Sandro Knauss"
+ }
+
+ self.__send_method(self.samurai.ClientIdentify, args_identify)
+
+ def __send_method(self, func, args=None):
+ """execute $func and test weather if the func ran successfully or not"""
+ if args==None:
+ xmlrpc_result = func()
+ else:
+ xmlrpc_result = func(args)
+ if xmlrpc_result['StatusCode'] != 200:
+ raise NoValidStatusCode("There was an error during identification to the server! %d %s"% (xmlrpc_result['StatusCode'], xmlrpc_result['StatusString']))
+
+ return xmlrpc_result
+
+ def __send(self,args,recipients):
+ """main sending method - sending the args to $recipients"""
+ sended=[]
+ self.__connect()
+ for recipient in recipients:
+ try:
+ tel = telnumber(recipient)
+
+ if tel in sended: #only send message once per recipient
+ continue
+ sended.append(tel)
+
+ args["RemoteUri"]="sip:%s%s@sipgate.net"%(tel.land,tel.number)
+ xmlrpc_result = self.__send_method(self.samurai.SessionInitiate, args)
+ self.updateStatus(arranged=recipient)
+ except NotATelNumber,NoValidStatusCode :
+ self.updateStatus(failed=recipient)
+
+ self.__disconnect()
+
+ def updateStatus(self, arranged=None, failed=None):
+ """is a function that is called, if a new SMS/FAX was send
+ -arranged is non None, if SMS/FAX was sended successfully
+ -failed is non None, if SMS/FAX sending failed
+ the content will be the recipent"""
+ pass
+
+ def BalanceGet(self):
+ """get the balance of sipgate"""
+ self.__connect()
+ ret = self.__send_method(self.samurai.BalanceGet )
+ self.__disconnect()
+ return ret['CurrentBalance']
+
+ def getNewMessages(self):
+ """get new messages from inbox"""
+ self.__connect()
+ tmp = self.__send_method(self.samurai.UmSummaryGet)
+ self.__disconnect()
+ tmp=tmp['UmSummary']
+ ret={}
+ for entry in tmp:
+ ret[entry['TOS']]={'read':entry["Read"],'unread':entry["Unread"]}
+ return ret
+
+ def getRecommendedInterval(self,methods):
+ """how often you can call one $methods"""
+ self.__connect()
+ args = {"MethodList" : methods }
+ tmp = self.__send_method(self.samurai.RecommendedIntervalGet, args)
+ self. __disconnect()
+ ret={}
+ for entry in tmp['IntervalList']:
+ ret[entry['MethodName']]=entry['RecommendedInterval']
+ return ret
+
+ def __disconnect(self):
+ """disconnect xmlrpc client"""
+ self.xmlrpc=None
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/anbieter/smtp.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+#Copyright (C) 2009 Sandro Knauß <bugs@sandroknauss.de>
+
+#This program is free software; you can redistribute it and/or modify it under the terms
+#of the GNU General Public License as published by the Free Software Foundation;
+#either version 3 of the License, or any later version.
+#This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+#without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#See the GNU General Public License for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+class anbieter:
+ default_conf = '' # override this
+import smtplib
+import ConfigParser
+
+
+class SMTP():
+ def __init__(self,config_filename=None,section="smtp"):
+ self.config_filename=config_filename
+ self.section=section
+ self.bStart=False
+ self.bTLS=False
+ self.bSSL=False
+ self.max_recipients=1
+
+ def read_basic_config(self,config_filename=None):
+ """Read basic options from the config file"""
+ if not (config_filename is None):
+ self.config_filename=config_filename
+
+ cp = ConfigParser.ConfigParser()
+ cp.read([self.config_filename])
+ self.config_parser = cp
+ self.send_from=cp.get(self.section, 'send_from')
+ self.host=cp.get(self.section, 'host')
+ self.port=cp.get(self.section, 'port')
+ self.user=cp.get(self.section, 'user')
+ self.pw=cp.get(self.section, 'password')
+
+ try:
+ self.bTLS=cp.getboolean(self.section, 'TLS')
+ except ValueError:
+ self.bTLS=False
+
+ try:
+ self.bSSL=cp.getboolean(self.section, 'SSL')
+ except ValueError:
+ self.bSSL=False
+
+
+ def prepareSMTP(self):
+ if self.bSSL:
+ self.smtp = smtplib.SMTP_SSL(self.host,self.port)
+ else:
+ self.smtp = smtplib.SMTP(self.host,self.port)
+
+ if self.bTLS:
+ self.smtp.starttls()
+
+ if not self.user == "":
+ self.smtp.login(self.user,self.pw)
+
+ self.bStart=True
+
+ def sendMail(self,mail,recipients):
+ if not self.bStart:
+ self.prepareSMTP()
+
+ mail.content['From']=self.send_from
+ while len(recipients) > 0:
+ tmp_recipients=recipients[:self.max_recipients]
+ print tmp_recipients
+ self.smtp.sendmail(self.send_from, tmp_recipients, mail.as_string())
+ self.updateStatus( arranged=tmp_recipients)
+ recipients = recipients[self.max_recipients:]
+
+ self.smtp.shutdownSMTP()
+
+
+ def updateStatus(self, arranged=None, failed=None):
+ """is a function that is called, if a new SMS/FAX was send
+ -arranged is non None, if SMS/FAX was sended successfully
+ -failed is non None, if SMS/FAX sending failed
+ the content will be the recipent"""
+ pass
+
+ def shutdownSMTP(self):
+ self.smtp.quit()
+ self.bStart=False
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/anbieter/telnumber.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+#Copyright (C) 2009 Sandro Knauß <bugs@sandroknauss.de>
+
+#This program is free software; you can redistribute it and/or modify it under the terms
+#of the GNU General Public License as published by the Free Software Foundation;
+#either version 3 of the License, or any later version.
+#This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+#without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#See the GNU General Public License for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+class anbieter:
+ default_conf = '' # override this
+import re
+
+class NotATelNumber(Exception):
+ def __init__(self, number):
+ self.number= number
+
+ def __str__(self):
+ return ("This is not a telefonnumber:", selfnumber)
+
+class telnumber:
+ re_telnum=re.compile(r'^\s*(\+)?([0-9\s\-/\(\)])+\s*$')
+ re_land=re.compile(r'^\s*(\+|00)(?P<land>[1-9]{2})')
+ re_number=re.compile(r'[^0-9]')
+ std_land="49"
+
+ def __init__(self,number=None):
+ if not(number is None):
+ self.createNumber(number)
+
+ def createNumber(self, number):
+
+ if not self.re_telnum.match(number):
+ raise NotATelNumber(number)
+
+
+ self.land=self.std_land
+ land=self.re_land.match(number)
+
+ if not(land is None):
+ self.land=land.group("land")
+ number=number[land.end("land"):]
+
+ number=self.re_number.sub('',number)
+
+ if number[0]=="0":
+ number=number[1:]
+
+ self.number = number
+
+ def __eq__(self, y):
+ return ((self.number == y.number) and ( self.land == y.land))
+
+ def __ne__(self, y):
+ return not self.__eq__(y)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/anbieter/test.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+#Copyright (C) 2009 Sandro Knauß <bugs@sandroknauss.de>
+
+#This program is free software; you can redistribute it and/or modify it under the terms
+#of the GNU General Public License as published by the Free Software Foundation;
+#either version 3 of the License, or any later version.
+#This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+#without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#See the GNU General Public License for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+class anbieter:
+ default_conf = '' # override this
+
+import unittest
+import telnumber as tn
+
+class TestTelnumber(unittest.TestCase):
+ def equalNumber(self, tel1, tel2):
+ self.assertEqual(tel1.number, tel2.number)
+ self.assertEqual(tel1.land, tel2.land)
+
+ def testWrongNumber(self):
+ telnum=tn.telnumber()
+ self.assertRaises(tn.NotATelNumber, telnum.createNumber, "hallo")
+ self.assertRaises(tn.NotATelNumber, telnum.createNumber, "0?242")
+
+
+ def testNumber(self):
+ telnum=tn.telnumber("0551-28293640")
+ telnum2=tn.telnumber("+49551/28293640")
+ telnum3=tn.telnumber("00495512829364-0")
+ telnum4=tn.telnumber("+49(0)551-28293640")
+
+ self.assertEqual(telnum.land, "49")
+ self.assertEqual(telnum.number, "55128293640")
+
+ self.equalNumber(telnum, telnum2)
+ self.equalNumber(telnum, telnum3)
+ self.equalNumber(telnum, telnum4)
+
+ def testEqual(self):
+ telnum=tn.telnumber("0551-28293640")
+ telnum2=tn.telnumber("+49551/28293640")
+ li=[]
+ self.assertEqual(telnum == telnum2, True)
+ self.assertEqual(telnum <> telnum2, False)
+ self.assertEqual(telnum, telnum2)
+ self.assertEqual(telnum in li,False)
+ li.append(telnum)
+ self.assertEqual(telnum in li,True)
+ self.assertEqual(telnum in li,True)
+
+if __name__ == "__main__":
+ unittest.main()
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/content.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+#Copyright (C) 2009 Sandro Knauß <bugs@sandroknauss.de>
+
+#This program is free software; you can redistribute it and/or modify it under the terms
+#of the GNU General Public License as published by the Free Software Foundation;
+#either version 3 of the License, or any later version.
+#This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+#without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#See the GNU General Public License for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from email.mime.text import MIMEText
+
+class content:
+ def __init__(self,content):
+ self.content=content
+
+ def sendto(self,anbieter,recipients):
+ pass
+
+class SMS(content):
+ def __init__(self,cont):
+ content.__init__(self,cont)
+
+ def sendto(self,anbieter,recipients):
+ anbieter.sendSMS(self,recipients)
+
+class FAX(content):
+ def __init__(self,header,cont,attachments):
+ content.__init__(self,cont)
+ self.header=header
+ self.attachments=attachments
+
+ def sendto(self,anbieter,recipients):
+ anbieter.sendFAX(self,recipients)
+
+class Mail(content):
+ def __init__(self, subject, body):
+ con=MIMEText(body)
+ con['Subject']=subject
+ content.__init__(self, con)
+
+ def sendto(self,anbieter,recipients):
+ anbieter.sendMail(self,recipients)
+
+ def as_string(self):
+ return self.content.as_string()
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/iro.api Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,162 @@
+iro.anbieter.FAX_de.FAX_de.createMailaddress?4(number)
+iro.anbieter.FAX_de.FAX_de.default_conf?7
+iro.anbieter.FAX_de.FAX_de.max_recipients?7
+iro.anbieter.FAX_de.FAX_de.section?7
+iro.anbieter.FAX_de.FAX_de?1()
+iro.anbieter.anbieter.anbieter.default_conf?7
+iro.anbieter.anbieter.anbieter.section?7
+iro.anbieter.anbieter.anbieter.sendFAX?4(fax, recipients)
+iro.anbieter.anbieter.anbieter.sendMail?4(mail, recipients)
+iro.anbieter.anbieter.anbieter.sendSMS?4(sms, recipients)
+iro.anbieter.geonet.Mail?1(send_from, header, cont, attachments)
+iro.anbieter.geonet.geonet.createMailaddress?4(number)
+iro.anbieter.geonet.geonet.default_conf?7
+iro.anbieter.geonet.geonet.max_recipients?7
+iro.anbieter.geonet.geonet.section?7
+iro.anbieter.geonet.geonet.sendFAX?4(fax, recipients)
+iro.anbieter.geonet.geonet.sendMail?4(mail, recipients)
+iro.anbieter.geonet.geonet.sendSMS?4(sms, recipients)
+iro.anbieter.geonet.geonet?1()
+iro.anbieter.sipgate.sipgate.BalanceGet?4()
+iro.anbieter.sipgate.sipgate.__connect?6()
+iro.anbieter.sipgate.sipgate.__disconnect?6()
+iro.anbieter.sipgate.sipgate.__send?6(args, recipients)
+iro.anbieter.sipgate.sipgate.__send_method?6(func, args=None)
+iro.anbieter.sipgate.sipgate.getNewMessages?4()
+iro.anbieter.sipgate.sipgate.getRecommendedInterval?4(methods)
+iro.anbieter.sipgate.sipgate.read_basic_config?4(filename)
+iro.anbieter.sipgate.sipgate.section?7
+iro.anbieter.sipgate.sipgate.sendFAX?4(fax, recipients)
+iro.anbieter.sipgate.sipgate.sendSMS?4(sms, recipients)
+iro.anbieter.sipgate.sipgate.updateStatus?4(arranged=None, failed=None)
+iro.anbieter.sipgate.sipgate.url?7
+iro.anbieter.sipgate.sipgate?1(user="", password="")
+iro.anbieter.smtp.SMTP.prepareSMTP?4()
+iro.anbieter.smtp.SMTP.read_basic_config?4()
+iro.anbieter.smtp.SMTP.sendMail?4(mail, recipients)
+iro.anbieter.smtp.SMTP.shutdownSMTP?4()
+iro.anbieter.smtp.SMTP?1(config_filename, section)
+iro.anbieter.smtp.anbieter.default_conf?7
+iro.anbieter.telnumber.NotATelNumber.__str__?6()
+iro.anbieter.telnumber.NotATelNumber?1(number)
+iro.anbieter.telnumber.anbieter.default_conf?7
+iro.anbieter.telnumber.telnumber.__eq__?6(y)
+iro.anbieter.telnumber.telnumber.__ne__?6(y)
+iro.anbieter.telnumber.telnumber.createNumber?4(number)
+iro.anbieter.telnumber.telnumber.re_land?7
+iro.anbieter.telnumber.telnumber.re_number?7
+iro.anbieter.telnumber.telnumber.re_telnum?7
+iro.anbieter.telnumber.telnumber.std_land?7
+iro.anbieter.telnumber.telnumber?1(number=None)
+iro.anbieter.test.TestTelnumber.equalNumber?4(tel1, tel2)
+iro.anbieter.test.TestTelnumber.testEqual?4()
+iro.anbieter.test.TestTelnumber.testNumber?4()
+iro.anbieter.test.TestTelnumber.testWrongNumber?4()
+iro.anbieter.test.anbieter.default_conf?7
+iro.content.FAX.sendto?4(anbieter, recipients)
+iro.content.FAX?1(header, cont, attachments)
+iro.content.SMS.sendto?4(anbieter, recipients)
+iro.content.SMS?1(cont)
+iro.content.content.sendto?4(anbieter, recipients)
+iro.content.content?1(content)
+iro.iro.Job.addFailed?4(failed)
+iro.iro.Job.addGood?4(good)
+iro.iro.Job.getName?4()
+iro.iro.Job.getProvider?4()
+iro.iro.Job.getStatus?4(detailed)
+iro.iro.Job.start?4()
+iro.iro.Job.stop?4()
+iro.iro.Job?1(provider, name)
+iro.iro.Jobs.__getitem__?6(key)
+iro.iro.Jobs.__registerJob__?6(job)
+iro.iro.Jobs._createID?5()
+iro.iro.Jobs.newFAX?4(subject, fax, recipients)
+iro.iro.Jobs.newMail?4(subject, body, recipients)
+iro.iro.Jobs.newSMS?4(message, recipients)
+iro.iro.Jobs?1(manager, queue, provider)
+iro.iro.MessageJob.getMessage?4()
+iro.iro.MessageJob.getRecipients?4()
+iro.iro.MessageJob.start?4()
+iro.iro.MessageJob.stop?4()
+iro.iro.MessageJob?1(provider, message, recipients)
+iro.iro.MyManager.certificate?7
+iro.iro.MyManager.userdb?7
+iro.iro.MySipgate.setJob?4(job)
+iro.iro.MySipgate.updateStatus?4(arranged=None, failed=None)
+iro.iro.MySipgate?1(user="", password="")
+iro.iro.MyUserDB.createUser?4(user)
+iro.iro.MyUserDB?1(userlist, jobqueue)
+iro.iro.start?4(userlist)
+iro.test.MyManager.certificate?7
+iro.test.MyManager.userdb?7
+iro.test.StoppableXMLRPCServer.run?4()
+iro.test.StoppableXMLRPCServer.running?7
+iro.test.StoppableXMLRPCServer.stop?4()
+iro.test.StoppableXMLRPCServer?1(*args, **kwargs)
+iro.test.TestServer.admin?7
+iro.test.TestServer.client1?7
+iro.test.TestServer.client2?7
+iro.test.TestServer.client?7
+iro.test.TestServer.id1?7
+iro.test.TestServer.id2?7
+iro.test.TestServer.id?7
+iro.test.TestServer.servstr?7
+iro.test.TestServer.setUp?4()
+iro.test.TestServer.tearDown?4()
+iro.test.TestServer.testLogin?4()
+iro.test.TestServer.testTwoUser?4()
+iro.test.TestServer.testsendSMS?4()
+iro.test.TestServer.u1?7
+iro.test.TestServer.u2?7
+iro.test.init_server?4()
+iro.user.Admin?1(jobqueue)
+iro.user.User.startMail?4(subject, body, recipients)
+iro.user.User.startSMS?4(message, recipients)
+iro.user.User.status?4(id=None, detailed=False)
+iro.user.User.stop?4(id)
+iro.user.User?1(jobqueue)
+iro.worker.Worker.run?4()
+iro.worker.Worker?1(queue)
+iro.xmlrpc.AuthentificateXMLRPCServer.AuthentificateXMLRPCRequestHandler.do_POST?4()
+iro.xmlrpc.AuthentificateXMLRPCServer.AuthentificateXMLRPCRequestHandler.report_401?4()
+iro.xmlrpc.AuthentificateXMLRPCServer.AuthentificateXMLRPCRequestHandler.report_error?4(code)
+iro.xmlrpc.AuthentificateXMLRPCServer.AuthentificateXMLRPCRequestHandler.testUser?4(username, password)
+iro.xmlrpc.AuthentificateXMLRPCServer.test?4()
+iro.xmlrpc.SecureAuthentificateXMLRPCServer.SecureAuthentificateXMLRPCRequestHandler.do_POST?4()
+iro.xmlrpc.SecureAuthentificateXMLRPCServer.test?4()
+iro.xmlrpc.SecureUserdbXMLRPCServer.SecureAuthentificateXMLRPCRequestHandler2.testUser?4(username, password)
+iro.xmlrpc.SecureUserdbXMLRPCServer.SecureUserDBXMLRPCServer.activateUser?4(username, password)
+iro.xmlrpc.SecureUserdbXMLRPCServer.SecureUserDBXMLRPCServer?1(addr, userdb, requestHandler=SecureAuthentificateXMLRPCRequestHandler2, certificate="server.cert", privatekey="server.pem", logRequests=1)
+iro.xmlrpc.SecureUserdbXMLRPCServer.UserDB.__getitem__?6(key)
+iro.xmlrpc.SecureUserdbXMLRPCServer.UserDB.createHash?4(user)
+iro.xmlrpc.SecureUserdbXMLRPCServer.UserDB.createUser?4(user)
+iro.xmlrpc.SecureUserdbXMLRPCServer.UserDB?1(userClass, userlist, jobqueue)
+iro.xmlrpc.SecureXMLRPCServer.SSLWrapper.__getattr__?6(name)
+iro.xmlrpc.SecureXMLRPCServer.SSLWrapper.__setattr__?6(name, value)
+iro.xmlrpc.SecureXMLRPCServer.SSLWrapper.accept?4()
+iro.xmlrpc.SecureXMLRPCServer.SSLWrapper.shutdown?4(how=1)
+iro.xmlrpc.SecureXMLRPCServer.SSLWrapper?1(conn)
+iro.xmlrpc.SecureXMLRPCServer.SecureTCPServer?1(server_address, RequestHandlerClass, certificate, privatekey)
+iro.xmlrpc.SecureXMLRPCServer.SecureXMLRPCRequestHandler.setup?4()
+iro.xmlrpc.SecureXMLRPCServer.SecureXMLRPCServer?1(addr, requestHandler=SecureXMLRPCRequestHandler, certificate="server.cert", privatekey="server.pem", logRequests=1)
+iro.xmlrpc.SecureXMLRPCServer.test?4()
+iro.xmlserver_test.Job.start?4()
+iro.xmlserver_test.Job.stop?4()
+iro.xmlserver_test.Job?1(provider, name)
+iro.xmlserver_test.Jobs.__getitem__?6(key)
+iro.xmlserver_test.Jobs._createID?5()
+iro.xmlserver_test.Jobs.newSMS?4(message, recipients)
+iro.xmlserver_test.Jobs?1(queue, provider)
+iro.xmlserver_test.SMSJob?1(provider, message, recipients)
+iro.xmlserver_test.SecureAuthentificateXMLRPCRequestHandler2.testUser?4(username, password)
+iro.xmlserver_test.SecureUserDBXMLRPCServer.activateUser?4(username, password)
+iro.xmlserver_test.SecureUserDBXMLRPCServer?1(addr, userdb, requestHandler=SecureAuthentificateXMLRPCRequestHandler2, certificate="server.cert", privatekey="server.pem", logRequests=1)
+iro.xmlserver_test.User.startSMS?4(message, recipients)
+iro.xmlserver_test.User.status?4(id=None)
+iro.xmlserver_test.User.stop?4(id)
+iro.xmlserver_test.User?1(jobqueue)
+iro.xmlserver_test.UserDB.__getitem__?6(key)
+iro.xmlserver_test.UserDB.createHash?4(username, password)
+iro.xmlserver_test.UserDB.createUser?4(user)
+iro.xmlserver_test.UserDB?1(userlist, jobqueue)
+iro.xmlserver_test.test?4()
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/iro.conf.inst Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,31 @@
+[geonet]
+host = localhost
+port = 25
+send_from =
+user =
+password =
+
+
+[FAX_de]
+host = localhost
+port = 25
+send_from =
+user =
+password =
+
+[sipgate]
+user =
+password =
+
+[smtp]
+host = localhost
+port = 25
+send_from =
+user =
+password =
+TLS=No
+SSL=No
+
+[server]
+key=
+cert=
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/iro.e4p Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,220 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Project SYSTEM "Project-4.6.dtd">
+<!-- eric4 project file for project iro -->
+<!-- Saved: 2009-10-16, 01:34:46 -->
+<!-- Copyright (C) 2009 Sandro Knauß, bugs@sandroknauss.de -->
+<Project version="4.6">
+ <Language></Language>
+ <ProgLanguage mixed="0">Python</ProgLanguage>
+ <ProjectType>Console</ProjectType>
+ <Description>Ein Daemon zum Senden von Massensms, -faxen und emails</Description>
+ <Version>0.1</Version>
+ <Author>Sandro Knauß</Author>
+ <Email>bugs@sandroknauss.de</Email>
+ <Sources>
+ <Source>iro.py</Source>
+ <Source>content.py</Source>
+ <Source>__init__.py</Source>
+ <Source>xmlrpc/SecureXMLRPCServer.py</Source>
+ <Source>xmlrpc/__init__.py</Source>
+ <Source>xmlrpc/SecureAuthentificateXMLRPCServer.py</Source>
+ <Source>xmlrpc/AuthentificateXMLRPCServer.py</Source>
+ <Source>xmlserver_test.py</Source>
+ <Source>anbieter/smtp.py</Source>
+ <Source>anbieter/geonet.py</Source>
+ <Source>anbieter/__init__.py</Source>
+ <Source>anbieter/FAX_de.py</Source>
+ <Source>anbieter/sipgate.py</Source>
+ <Source>anbieter/anbieter.py</Source>
+ <Source>xmlrpc/SecureUserdbXMLRPCServer.py</Source>
+ <Source>worker.py</Source>
+ <Source>user.py</Source>
+ <Source>anbieter/telnumber.py</Source>
+ <Source>anbieter/test.py</Source>
+ <Source>test.py</Source>
+ </Sources>
+ <Forms>
+ </Forms>
+ <Translations>
+ </Translations>
+ <Resources>
+ </Resources>
+ <Interfaces>
+ </Interfaces>
+ <Others>
+ <Other>iro.conf.inst</Other>
+ </Others>
+ <MainScript>iro.py</MainScript>
+ <Vcs>
+ <VcsType>Subversion</VcsType>
+ <VcsOptions>
+ <dict>
+ <key>
+ <string>add</string>
+ </key>
+ <value>
+ <list>
+ <string></string>
+ </list>
+ </value>
+ <key>
+ <string>checkout</string>
+ </key>
+ <value>
+ <list>
+ <string></string>
+ </list>
+ </value>
+ <key>
+ <string>commit</string>
+ </key>
+ <value>
+ <list>
+ <string></string>
+ </list>
+ </value>
+ <key>
+ <string>diff</string>
+ </key>
+ <value>
+ <list>
+ <string></string>
+ </list>
+ </value>
+ <key>
+ <string>export</string>
+ </key>
+ <value>
+ <list>
+ <string></string>
+ </list>
+ </value>
+ <key>
+ <string>global</string>
+ </key>
+ <value>
+ <list>
+ <string></string>
+ </list>
+ </value>
+ <key>
+ <string>history</string>
+ </key>
+ <value>
+ <list>
+ <string></string>
+ </list>
+ </value>
+ <key>
+ <string>log</string>
+ </key>
+ <value>
+ <list>
+ <string></string>
+ </list>
+ </value>
+ <key>
+ <string>remove</string>
+ </key>
+ <value>
+ <list>
+ <string></string>
+ </list>
+ </value>
+ <key>
+ <string>status</string>
+ </key>
+ <value>
+ <list>
+ <string></string>
+ </list>
+ </value>
+ <key>
+ <string>tag</string>
+ </key>
+ <value>
+ <list>
+ <string></string>
+ </list>
+ </value>
+ <key>
+ <string>update</string>
+ </key>
+ <value>
+ <list>
+ <string></string>
+ </list>
+ </value>
+ </dict>
+ </VcsOptions>
+ <VcsOtherData>
+ <dict>
+ <key>
+ <string>standardLayout</string>
+ </key>
+ <value>
+ <bool>True</bool>
+ </value>
+ </dict>
+ </VcsOtherData>
+ </Vcs>
+ <FiletypeAssociations>
+ <FiletypeAssociation pattern="*.pyw" type="SOURCES" />
+ <FiletypeAssociation pattern="*.idl" type="INTERFACES" />
+ <FiletypeAssociation pattern="*.py" type="SOURCES" />
+ <FiletypeAssociation pattern="*.ptl" type="SOURCES" />
+ </FiletypeAssociations>
+ <Documentation>
+ <DocumentationParams>
+ <dict>
+ <key>
+ <string>ERIC4API</string>
+ </key>
+ <value>
+ <dict>
+ <key>
+ <string>basePackage</string>
+ </key>
+ <value>
+ <unicode>iro</unicode>
+ </value>
+ <key>
+ <string>ignoreFilePatterns</string>
+ </key>
+ <value>
+ <list>
+ <unicode></unicode>
+ </list>
+ </value>
+ <key>
+ <string>includePrivate</string>
+ </key>
+ <value>
+ <bool>True</bool>
+ </value>
+ <key>
+ <string>languages</string>
+ </key>
+ <value>
+ <list>
+ <unicode>Python</unicode>
+ </list>
+ </value>
+ <key>
+ <string>outputFile</string>
+ </key>
+ <value>
+ <unicode>iro.api</unicode>
+ </value>
+ <key>
+ <string>useRecursion</string>
+ </key>
+ <value>
+ <bool>True</bool>
+ </value>
+ </dict>
+ </value>
+ </dict>
+ </DocumentationParams>
+ </Documentation>
+</Project>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/iro.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,230 @@
+# -*- coding: utf-8 -*-
+#Copyright (C) 2009 Sandro Knauß <bugs@sandroknauss.de>
+
+#This program is free software; you can redistribute it and/or modify it under the terms
+#of the GNU General Public License as published by the Free Software Foundation;
+#either version 3 of the License, or any later version.
+#This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+#without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#See the GNU General Public License for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+# Server code
+
+from xmlrpc import SecureUserDBXMLRPCServer,UserDB
+import time, os, md5
+from user import User, Admin
+import content
+import anbieter
+import ConfigParser
+
+class MyUserDB(UserDB):
+ def __init__(self, userlist,jobqueue):
+ UserDB.__init__(self, None,userlist,jobqueue)
+
+ def createUser(self, user):
+ self.userlist[self.createHash(user)]=user["class"](self.jobqueue)
+
+class Job(object):
+ '''
+ Basic class for all jobs
+ '''
+ def __init__(self,provider,name):
+ self.provider=provider
+ self.name=name
+ self.status = "init"
+ self.dStatus={"good":[], "failed":[]}
+
+ def start(self):
+ self.status = "started"
+
+ def stop(self):
+ self.status = "stopped"
+
+ def getStatus(self,detailed):
+ if detailed and self.status == "started" or self.status == "sended":
+ return self.status, self.dStatus
+ return self.status, {}
+
+ def getName(self):
+ return self.name
+
+ def getProvider(self):
+ return self.provider
+
+ def addGood(self, good):
+ if type(good) == list:
+ self.dStatus['good']=self.dStatus['good']+good
+ else:
+ self.dStatus['good'].append(good)
+
+ def addFailed(self, failed):
+ if type(failed) == list:
+ self.dStatus['failed']=self.dStatus['failed']+failed
+ else:
+ self.dStatus['failed'].append(failed)
+
+class MessageJob(Job):
+ '''
+ A specialized class for smsjobs
+ '''
+ def __init__(self,provider,name, message,recipients):
+ self.message=message
+ self.recipients=recipients
+ Job.__init__(self,provider, name)
+
+ def stop(self):
+ pass
+
+ def start(self):
+ Job.start(self)
+ self.provider.setJob(self)
+ self.message.sendto(self.provider, self.recipients)
+ self.status="sended"
+
+ def getMessage(self):
+ return self.message
+
+ def getRecipients(self):
+ return self.recipients
+
+
+class MySipgate(anbieter.sipgate):
+
+ def __init__(self,user="",password="" ):
+ anbieter.sipgate.__init__(self, user, password)
+
+ def setJob(self, job):
+ self.job=job
+
+ def updateStatus(self, arranged=None, failed=None):
+ if arranged:
+ self.job.addGood(arranged)
+
+ if failed:
+ self.job.addFailed(failed)
+
+class MySMTP(anbieter.SMTP):
+
+ def __init__(self,config_filename=None,section="smtp"):
+ anbieter.SMTP.__init__(self,config_filename,section)
+
+ def setJob(self, job):
+ self.job=job
+
+ def updateStatus(self, arranged=None, failed=None):
+ if arranged:
+ self.job.addGood(arranged)
+
+ if failed:
+ self.job.addFailed(failed)
+
+
+class Jobs:
+ '''
+ Providing an list of jobs; each new job gets a hash id
+ '''
+ def __init__(self,manager, queue,provider):
+ self.jobs={}
+ self.manager=manager
+ self.queue=queue
+ self.provider=provider
+
+
+ def __getitem__(self,key):
+ return self.jobs[key]
+
+ def __registerJob__(self, job):
+ id = self._createID()
+ self.jobs[id]=job
+ self.queue.put(job)
+ return id
+
+ def newSMS(self,message,recipients):
+ '''
+ creates a new SMS
+ '''
+ job=self.manager.MessageJob(self.provider["sms"],message, content.SMS(message),recipients)
+ return self.__registerJob__(job)
+
+ def newFAX(self,subject, fax,recipients):
+ '''
+ creates a new Fax
+ '''
+ job=self.manager.MessageJob(self.provider["fax"],subject, content.FAX(subject, fax),recipients)
+ return self.__registerJob__(job)
+
+ def newMail(self,subject, body,recipients):
+ '''
+ creates a new Mail
+ '''
+ job=self.manager.MessageJob(self.provider["mail"],subject, content.Mail(subject, body),recipients)
+ return self.__registerJob__(job)
+
+ def _createID(self):
+ '''
+ creats a random hash id
+ '''
+ while True:
+ m = md5.new()
+ m.update(str(time.time()))
+ m.update(os.urandom(10))
+ if not self.jobs.has_key(m.hexdigest):
+ self.jobs[m.hexdigest()]=None
+ break
+ return m.hexdigest()
+
+def start(userlist):
+ from multiprocessing import Queue
+ from multiprocessing.managers import BaseManager
+
+ class MyManager(BaseManager):
+ pass
+
+ MyManager.register('MessageJob', MessageJob)
+ manager = MyManager()
+ manager.start()
+
+
+ #anbieter erzeugen und konfigurieren
+
+ sip=MySipgate()
+ sip.read_basic_config("iro.conf")
+
+ localhost=MySMTP()
+ localhost.read_basic_config("iro.conf")
+
+ #Benutzerdatenbank erstellen
+ queue = Queue()
+ provider={"sms":sip, "fax":sip, "mail":localhost}
+ jobqueue=Jobs(manager, queue, provider)
+ userdb=MyUserDB(userlist,jobqueue)
+
+ #working thread erstellen
+ from worker import Worker
+ worker=Worker(queue)
+ worker.start()
+
+ #Server starten
+ cp = ConfigParser.ConfigParser()
+ cp.read(["iro.conf"])
+ cert=cp.get('server', 'cert')
+ key=cp.get('server', 'key')
+ server = SecureUserDBXMLRPCServer(addr=("localhost", 8000),
+ userdb=userdb,
+ certificate=cert,privatekey=key)
+ server.relam="xmlrpc"
+
+ print "Server started..."
+ server.serve_forever()
+
+ worker.terminate()
+
+if __name__ == '__main__':
+ userlist=[{"name":"test","password":"test", "class":User},
+ {"name":"test2","password":"test2", "class": Admin}]
+ start(userlist)
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/merlin Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# merlin commando
+#
+# eine überprüfung auf korrekten aufruf findet nicht statt
+#
+# beispiel:
+#
+# ./merlin ./arthur
+#
+# startet programm arthur und wenn er stirbt, wird er sofort
+# wiederbelebt.
+# harmlose magie halt... :-)
+#
+LOG=/home/sandy/var/log/merlin_Iro.log
+while : ; do
+ echo -n "$(date +'%F %T %Z') " >> $LOG
+ $1 status >> $LOG
+ if [ $? -eq 1 ]; then
+ echo $(date +'%F %T %Z') $1 neustarten >> $LOG
+ $1 start >> $LOG
+ fi
+ sleep 60
+done
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/merlin_daemon Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,44 @@
+#! /bin/sh
+NAME="merlin"
+DEAMON=/home/sandy/svn/daemon/$NAME
+DEAMON_OPTS="/home/sandy/svn/iro/MyIro_daemon"
+PID=/home/sandy/var/run/$NAME.pid
+
+test -x $DEAMON || exit 0
+
+. /lib/lsb/init-functions
+
+case "$1" in
+ start)
+ log_daemon_msg "Starting $NAME server" $NAME
+ if start-stop-daemon --start --quiet --oknodo --pidfile $PID --make-pidfile --background --startas $DEAMON -- $DEAMON_OPTS; then
+ log_end_msg 0
+ else
+ log_end_msg 1
+ fi
+ ;;
+ stop)
+ log_daemon_msg "Stopping $NAME server" $NAME
+ if start-stop-daemon --stop --quiet --oknodo --pidfile $PID; then
+ log_end_msg 0
+ else
+ log_end_msg 1
+ fi
+ ;;
+
+ restart)
+ $0 stop
+ sleep 1
+ $0 start
+ ;;
+
+ status)
+ status_of_proc -p $PID $DEAMON $NAME && exit 0 || exit $?
+ ;;
+
+ *)
+ log_action_msg "Usage: $0 {start|stop|restart|status}"
+ exit 1
+esac
+
+exit 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/test.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,107 @@
+# -*- coding: utf-8 -*-
+
+import unittest
+import server
+import threading, xmlrpclib
+from multiprocessing import Queue
+from multiprocessing.managers import BaseManager
+
+class StoppableXMLRPCServer(server.SecureUserDBXMLRPCServer, threading.Thread):
+ running=True
+ def __init__(self, *args, **kwargs):
+ server.SecureUserDBXMLRPCServer.__init__(self, *args, **kwargs)
+ threading.Thread.__init__(self)
+
+
+ def run(self):
+ # *serve_forever* muss in einem eigenen Thread laufen, damit man es
+ # unterbrechen kann!
+ while (self.running):
+ self.handle_request()
+
+
+ def stop(self):
+ self.running=False
+ self.server_close()
+
+
+def init_server():
+ userlist=[{"name":"test","password":"test", "class":server.User},
+ {"name":"test2","password":"test2", "class": server.User},
+ {"name":"admin","password":"admin", "class": server.Admin}]
+
+
+
+ class MyManager(BaseManager):
+ pass
+
+ MyManager.register('MessageJob', server.MessageJob)
+ manager = MyManager()
+ manager.start()
+
+
+ #anbieter erzeugen und konfigurieren
+ import anbieter
+ sip=anbieter.sipgate()
+ sip.read_basic_config("iro.conf")
+ localhost=""
+
+ #Benutzerdatenbank erstellen
+ queue = Queue()
+ provider={"sms":sip, "fax":sip, "mail":localhost}
+ jobqueue=server.Jobs(manager, queue, provider)
+ userdb=server.MyUserDB(userlist,jobqueue)
+
+
+ #Server starten
+ serv = StoppableXMLRPCServer(addr=("localhost", 8000),
+ userdb=userdb,
+ certificate="./certs/test.cert.pem",privatekey="./certs/test.key.pem")
+ serv.relam="xmlrpc"
+ return serv
+
+
+class TestServer(unittest.TestCase):
+
+ def setUp(self):
+ self.serv = init_server()
+ self.serv.start()
+
+ def tearDown(self):
+ self.serv.stop()
+ xmlrpclib.Server("https://test:test@localhost:8000").status() #letzte nachricht abrufen, damit richt geschlossen wird
+
+ def testLogin(self):
+ self.assertEqual(xmlrpclib.Server("https://test:test@localhost:8000").status(), {})
+ self.assertEqual(xmlrpclib.Server("https://test2:test2@localhost:8000").status(), {})
+ self.assertRaises(xmlrpclib.ProtocolError, xmlrpclib.Server("https://test2:test@localhost:8000").status)
+ self.assertRaises(xmlrpclib.ProtocolError,xmlrpclib.Server ("https://test:test2@localhost:8000").status)
+
+ def testsendSMS(self):
+ servstr="https://test:test@localhost:8000"
+ client=xmlrpclib.Server(servstr)
+ id=client.startSMS("test",["01234"] )
+ self.assertEqual(client.status(id),{id: {'status': ['init',{}], 'name': {'content': 'test'}}} )
+
+ def testTwoUser(self):
+ u1="https://test:test@localhost:8000"
+ u2="https://test2:test2@localhost:8000"
+ admin="https://admin:admin@localhost:8000"
+ client1=xmlrpclib.Server(u1)
+ client2=xmlrpclib.Server(u2)
+ admin=xmlrpclib.Server(admin)
+ id1=client1.startSMS("test",["01234"] )
+ self.assertEqual(client2.status(),{} )
+ self.assertEqual(admin.status(id1),{id1: {'status': ['init',{}], 'name': {'content': 'test'}}} )
+ id2=client2.startSMS("test2",["01234"] )
+ self.assertNotEqual(id1, id2)
+ self.assertEqual(client1.status(),{id1: {'status': ['init',{}], 'name': {'content': 'test'}}})
+ self.assertEqual(client2.status(),{id2: {'status': ['init',{}], 'name': {'content': 'test2'}}})
+ self.assertEqual(admin.status(),{id1: {'status': ['init',{}], 'name': {'content': 'test'}},
+ id2: {'status': ['init',{}], 'name': {'content': 'test2'}}} )
+
+ self.assertRaises(xmlrpclib.Fault, client2.status, id1)
+ self.assertRaises(xmlrpclib.Fault, client1.status, id2)
+
+if __name__ == "__main__":
+ unittest.main()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/user.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,69 @@
+# -*- coding: utf-8 -*-
+#Copyright (C) 2009 Sandro Knauß <bugs@sandroknauss.de>
+
+#This program is free software; you can redistribute it and/or modify it under the terms
+#of the GNU General Public License as published by the Free Software Foundation;
+#either version 3 of the License, or any later version.
+#This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+#without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#See the GNU General Public License for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with this program; if not, see <http://www.gnu.org/licenses/>.
+class User:
+ '''
+ class for a xmlrpc user
+ '''
+ def __init__(self,jobqueue):
+ self.jobqueue=jobqueue
+ self.jobs={}
+
+ def status(self,id=None,detailed=False):
+ '''
+ gets the status for a job
+ if the id is None all Jobs of an user are given back
+ '''
+ if id==None:
+ jobs=self.jobs
+ else:
+ try:
+ jobs={id:self.jobs[id]}
+ except:
+ raise String("No Job with ID: %i" %(id))
+ ret={}
+ for key in jobs:
+ job=jobs[key]
+ ret[key]={"name":job.getName(),"status":job.getStatus(detailed)}
+
+ return ret
+
+ def stop(self,id):
+ '''
+ stops an job with id
+ '''
+ try:
+ job=self.jobs[id]
+ job.stop()
+ except:
+ raise String("No Job with ID: %i" %(id))
+ job.stop()
+
+
+ def startSMS(self,message,recipients):
+ '''
+ starts the SMS with message to recipients
+ '''
+ id = self.jobqueue.newSMS(message,recipients)
+ self.jobs[id]=self.jobqueue[id]
+ return id
+
+
+ def startMail(self,subject, body , recipients):
+ id = self.jobqueue.newMail(subject, body ,recipients)
+ self.jobs[id]=self.jobqueue[id]
+ return id
+
+class Admin(User):
+ def __init__(self,jobqueue):
+ User.__init__(self, jobqueue)
+ self.jobs=jobqueue.jobs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/worker.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+# Worker code
+
+from multiprocessing import Process
+import time
+
+class Worker(Process):
+ def __init__(self,queue):
+ Process.__init__(self)
+ self.queue=queue
+
+ def run(self):
+ while 1:
+ job=self.queue.get()
+ if job is None:
+ break # reached end of queue
+ job.start()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/xmlrpc/AuthentificateXMLRPCServer.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,76 @@
+# Server code
+import SimpleXMLRPCServer
+import string,base64
+
+class AuthentificateXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
+ def do_POST(self):
+ try:
+ header = self.headers['Authorization']
+ type, user_passwd = header.split()
+ username, password = string.split(base64.decodestring(user_passwd), ':')
+ if self.testUser(username,password):
+ SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.do_POST(self)
+ else:
+ self.report_error(401)
+ except:
+ self.report_error(401)
+
+ def report_error (self,code):
+ '''
+ Send back an errorcode
+ '''
+ #it is important to read out the complete sended request ,
+ # but throw the data away, because an error should be send back
+ try:
+ max_chunk_size = 10*1024*1024
+ size_remaining = int(self.headers["content-length"])
+ while size_remaining:
+ chunk_size = min(size_remaining, max_chunk_size)
+ size_remaining -= len(self.rfile.read(chunk_size))
+ except:
+ pass
+
+ #now just send the error back
+ special_errors={401:self.report_401,
+ 404:self.report_404}
+ if special_errors.has_key(code):
+ special_errors[code]()
+ else:
+ self.send_response(code)
+ self.end_headers()
+ self.connection.shutdown(1)
+
+ def report_401(self):
+ self.send_response(401)
+ self.send_header("WWW-Authenticate", 'Basic realm="%s"'% self.server.relam)
+ response = 'Unauthorised'
+ self.send_header("Content-type", "text/plain")
+ self.send_header("Content-length", str(len(response)))
+ self.end_headers()
+ self.wfile.write(response)
+ # shut down the connection
+ self.wfile.flush()
+ self.connection.shutdown(1)
+
+ def testUser(self,username,password):
+ """
+ Function for testing authentification
+ """
+ if username=="test" and password=="test":
+ return True
+
+ return False
+
+
+
+def test():
+ server = SimpleXMLRPCServer.SimpleXMLRPCServer(("localhost", 8000),AuthentificateXMLRPCRequestHandler)
+ server.relam="xmlrpc"
+ server.register_introspection_functions()
+ server.register_function(lambda x: x*x, 'square')
+ server.serve_forever()
+
+if __name__ == '__main__':
+ test()
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/xmlrpc/SecureAuthentificateXMLRPCServer.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,20 @@
+# Server code
+import AuthentificateXMLRPCServer
+import SecureXMLRPCServer
+
+class SecureAuthentificateXMLRPCRequestHandler(SecureXMLRPCServer.SecureXMLRPCRequestHandler,AuthentificateXMLRPCServer.AuthentificateXMLRPCRequestHandler):
+ def do_POST(self):
+ AuthentificateXMLRPCServer.AuthentificateXMLRPCRequestHandler.do_POST(self)
+
+
+def test():
+ server = SecureXMLRPCServer.SecureXMLRPCServer(("localhost", 8000),requestHandler=SecureAuthentificateXMLRPCRequestHandler,certificate="./certs/test.cert.pem",privatekey="./certs/test.key.pem")
+ server.relam="xmlrpc"
+ server.register_introspection_functions()
+ server.register_function(lambda x: x*x, 'square')
+ server.serve_forever()
+
+if __name__ == '__main__':
+ test()
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/xmlrpc/SecureUserdbXMLRPCServer.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,63 @@
+from SecureAuthentificateXMLRPCServer import SecureAuthentificateXMLRPCRequestHandler
+from SecureXMLRPCServer import SecureXMLRPCServer
+import os, md5
+
+class UserDB:
+ '''
+ class for managing all xmlrpc users
+ - each user is indyfied via a hash value, which is created out of the username + password
+ '''
+ def __init__(self,userClass, userlist,jobqueue):
+ self.salt=os.urandom(20)
+ self.jobqueue=jobqueue
+ self.userClass=userClass
+ self.userlist={}
+ for user in userlist:
+ self.createUser(user)
+
+ def createHash(self,user):
+ """
+ returns a hash out of username and the password and self.salt
+ user is a directory with two keys: username and password
+ """
+ m=md5.new()
+ m.update(user["name"])
+ m.update(self.salt)
+ m.update(user["password"])
+ return m.hexdigest()
+
+ def createUser(self,user):
+ self.userlist[self.createHash(user)]=self.userClass(self.jobqueue)
+
+ def __getitem__(self,key):
+ return self.userlist[key]
+
+
+class SecureAuthentificateXMLRPCRequestHandler2(SecureAuthentificateXMLRPCRequestHandler):
+ def testUser(self,username,password):
+ """
+ Function for testing authentification
+ """
+ return self.server.activateUser(username,password)
+
+class SecureUserDBXMLRPCServer(SecureXMLRPCServer):
+ def __init__(self, addr, userdb,
+ requestHandler=SecureAuthentificateXMLRPCRequestHandler2,
+ certificate="server.cert", privatekey="server.pem",
+ logRequests=1):
+ SecureXMLRPCServer.__init__(self, addr, requestHandler, certificate, privatekey, logRequests)
+ self.relam="xmlrpc"
+ self.userdb=userdb
+
+ def activateUser(self,username,password):
+ """
+ Function is executed, if someone ant to login
+ -searches for a regular user in the userdb and then put all methods of the user as XMLRPC
+ returns weather a user was found or not
+ """
+ try:
+ user = self.userdb[self.userdb.createHash({"name":username,"password":password})]
+ self.register_instance(user)
+ return True
+ except KeyError:
+ return False
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/xmlrpc/SecureXMLRPCServer.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,113 @@
+"""
+SecureXMLRPCServer module using pyOpenSSL 0.5
+Written 0907.2002
+by Michal Wallace
+http://www.sabren.net/
+
+This acts exactly like SimpleXMLRPCServer
+from the standard python library, but
+uses secure connections. The technique
+and classes should work for any SocketServer
+style server. However, the code has not
+been extensively tested.
+
+This code is in the public domain.
+It is provided AS-IS WITH NO WARRANTY WHATSOEVER.
+"""
+import SocketServer
+import os, socket
+import SimpleXMLRPCServer
+from OpenSSL import SSL
+
+class SSLWrapper:
+ """
+ This whole class exists just to filter out a parameter
+ passed in to the shutdown() method in SimpleXMLRPC.doPOST()
+ """
+ def __init__(self, conn):
+ """
+ Connection is not yet a new-style class,
+ so I'm making a proxy instead of subclassing.
+ """
+ self.__dict__["conn"] = conn
+ def __getattr__(self,name):
+ return getattr(self.__dict__["conn"], name)
+ def __setattr__(self,name, value):
+ setattr(self.__dict__["conn"], name, value)
+ def shutdown(self, how=1):
+ """
+ SimpleXMLRpcServer.doPOST calls shutdown(1),
+ and Connection.shutdown() doesn't take
+ an argument. So we just discard the argument.
+ """
+ self.__dict__["conn"].shutdown()
+ def accept(self):
+ """
+ This is the other part of the shutdown() workaround.
+ Since servers create new sockets, we have to infect
+ them with our magic. :)
+ """
+ c, a = self.__dict__["conn"].accept()
+ return (SSLWrapper(c), a)
+
+
+
+class SecureTCPServer(SocketServer.TCPServer):
+ """
+ Just like TCPServer, but use a socket.
+ This really ought to let you specify the key and certificate files.
+ """
+ def __init__(self, server_address, RequestHandlerClass,certificate,privatekey):
+ SocketServer.BaseServer.__init__(self, server_address, RequestHandlerClass)
+
+ ## Same as normal, but make it secure:
+ ctx = SSL.Context(SSL.SSLv23_METHOD)
+ ctx.set_options(SSL.OP_NO_SSLv2)
+
+ ctx.use_privatekey_file (privatekey)
+ ctx.use_certificate_file(certificate)
+
+ self.socket = SSLWrapper(SSL.Connection(ctx, socket.socket(self.address_family,
+ self.socket_type)))
+ self.server_bind()
+ self.server_activate()
+
+
+class SecureXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
+ def setup(self):
+ """
+ We need to use socket._fileobject Because SSL.Connection
+ doesn't have a 'dup'. Not exactly sure WHY this is, but
+ this is backed up by comments in socket.py and SSL/connection.c
+ """
+ self.connection = self.request # for doPOST
+ self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
+ self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
+
+
+class SecureXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer, SecureTCPServer):
+ def __init__(self, addr,
+ requestHandler=SecureXMLRPCRequestHandler,
+ certificate="server.cert",privatekey="server.pem",
+ logRequests=1):
+ """
+ This is the exact same code as SimpleXMLRPCServer.__init__
+ except it calls SecureTCPServer.__init__ instead of plain
+ old TCPServer.__init__
+ """
+ self.funcs = {}
+ self.logRequests = logRequests
+ self.instance = None
+ SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self,False,None)
+ SecureTCPServer.__init__(self, addr, requestHandler,certificate=certificate,privatekey=privatekey)
+
+
+def test():
+ server = SecureXMLRPCServer.SecureXMLRPCServer(("localhost", 8000),requestHandler=SecureXMLRPCRequestHandler,certificate="./certs/test.cert.pem",privatekey="./certs/test.key.pem")
+ server.register_introspection_functions()
+ server.register_function(lambda x: x*x, 'square')
+ server.serve_forever()
+
+if __name__ == '__main__':
+ test()
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/xmlrpc/__init__.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,4 @@
+from AuthentificateXMLRPCServer import AuthentificateXMLRPCRequestHandler
+from SecureXMLRPCServer import SecureXMLRPCRequestHandler, SecureXMLRPCServer
+from SecureAuthentificateXMLRPCServer import SecureAuthentificateXMLRPCRequestHandler
+from SecureUserdbXMLRPCServer import SecureUserDBXMLRPCServer, UserDB
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/xmlserver_test.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,139 @@
+# Server code
+
+from xmlrpc import SecureXMLRPCServer,SecureAuthentificateXMLRPCRequestHandler
+import md5, time, os
+
+class Job:
+ def __init__(self,provider,name):
+ self.provider=provider
+ self.name=name
+ self.status="stopped"
+
+ def start(self):
+ self.status="started"
+
+ def stop(self):
+ self.status="stopped"
+
+class SMSJob(Job):
+ def __init__(self,provider,message,recipients):
+ self.message=message
+ self.recipients=recipients
+ Job.__init__(self,provider,message)
+
+class Jobs:
+ def __init__(self,queue,provider):
+ self.jobs={}
+ self.queue=queue
+ self.provider=provider
+
+ def __getitem__(self,key):
+ return self.jobs[key]
+
+ def newSMS(self,message,recipients):
+ job=SMSJob(self.provider,message,recipients)
+ id = self._createID()
+ self.jobs[id]=job
+ #self.queue.put(job)
+ return id
+
+ def _createID(self):
+ while True:
+ m = md5.new()
+ m.update(str(time.time()))
+ m.update(os.urandom(10))
+ if not self.jobs.has_key(m.hexdigest):
+ self.jobs[m.hexdigest()]=None
+ break
+ return m.hexdigest()
+
+
+class User:
+ def __init__(self,jobqueue):
+ self.jobqueue=jobqueue
+ self.jobs={}
+
+ def status(self,id=None):
+ if id==None:
+ jobs=self.jobs
+ else:
+ try:
+ jobs={id:self.jobs[id]}
+ except:
+ raise String("No Job with ID: %i" %(id))
+ ret={}
+ for key in jobs:
+ job=jobs[key]
+ ret[key]={"name":job.name,"status":job.status}
+ return ret
+
+ def stop(self,id):
+ try:
+ job=self.jobs[id]
+ except:
+ raise String("No Job with ID: %i" %(id))
+
+ job.stop()
+
+
+ def startSMS(self,message,recipients):
+ id = self.jobqueue.newSMS(message,recipients)
+ self.jobs[id]=self.jobqueue[id]
+ return id
+
+class UserDB:
+ def __init__(self,userlist,jobqueue):
+ self.salt=os.urandom(20)
+ self.jobqueue=jobqueue
+ self.userlist={}
+ for user in userlist:
+ self.createUser(user)
+
+ def createHash(self,username,password):
+ m=md5.new()
+ m.update(self.salt)
+ m.update(username)
+ m.update(password)
+ return m.hexdigest()
+
+ def createUser(self,user):
+ self.userlist[self.createHash(user.username,user.password)]=User(self.jobqueue)
+
+ def __getitem__(self,key):
+ return self.userlist[key]
+
+
+class SecureAuthentificateXMLRPCRequestHandler2(SecureAuthentificateXMLRPCRequestHandler):
+
+ def testUser(self,username,password):
+ return self.server.activateUser(username,password)
+
+class SecureUserDBXMLRPCServer(SecureXMLRPCServer):
+ def __init__(self, addr, userdb,
+ requestHandler=SecureAuthentificateXMLRPCRequestHandler2,
+ certificate="server.cert", privatekey="server.pem",
+ logRequests=1):
+ SecureXMLRPCServer.__init__(self, addr, requestHandler, certificate, privatekey, logRequests)
+ self.userdb=userdb
+
+ def activateUser(self,username,password):
+ try:
+ user = self.userdb[self.userdb.createHash(username,password)]
+ self.register_instance(user)
+ return True
+ except KeyError:
+ return False
+
+
+
+def test():
+ server = SecureXMLRPCServer(("localhost", 8000),requestHandler=SecureAuthentificateXMLRPCRequestHandler,certificate="./certs/test.cert.pem",privatekey="./certs/test.key.pem")
+ server.register_introspection_functions()
+ server.register_instance(StringFunctions())
+ server.register_function(lambda x: x*x, 'square')
+ server.serve_forever()
+
+if __name__ == '__main__':
+ test()
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/setup.py Thu Oct 22 10:00:01 2009 +0200
@@ -0,0 +1,2 @@
+from setuptools import setup
+setup(name="iro",version='0.1',install_requires=[])