[svn r93] creating iro package branch
authorSandro Knauß <knauss@netzguerilla.net>
Thu, 22 Oct 2009 10:00:01 +0200
changeset 0 a3b6e531f0d2
child 1 18918fbc397c
[svn r93] creating iro package branch
iro/.eric4project/daemon.e4q
iro/.eric4project/iro.e4p
iro/.eric4project/iro.e4t
iro/MyIro_daemon
iro/__init__.py
iro/anbieter/FAX_de.py
iro/anbieter/__init__.py
iro/anbieter/anbieter.py
iro/anbieter/geonet.py
iro/anbieter/sipgate.py
iro/anbieter/smtp.py
iro/anbieter/telnumber.py
iro/anbieter/test.py
iro/content.py
iro/iro.api
iro/iro.conf.inst
iro/iro.e4p
iro/iro.py
iro/merlin
iro/merlin_daemon
iro/test.py
iro/user.py
iro/worker.py
iro/xmlrpc/AuthentificateXMLRPCServer.py
iro/xmlrpc/SecureAuthentificateXMLRPCServer.py
iro/xmlrpc/SecureUserdbXMLRPCServer.py
iro/xmlrpc/SecureXMLRPCServer.py
iro/xmlrpc/__init__.py
iro/xmlserver_test.py
setup.py
--- /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=[])