# HG changeset patch # User Sandro Knauß # Date 1332544060 -3600 # Node ID 4007b5072c4ae0276c20d090930f67a524547b00 # Parent 62322feaeda40b33d78905009b34c193bb48a7bc# Parent 830204e316cad5327d0f462287e41eb5fe08c0d3 getting old iro.user into actual version diff -r 830204e316ca -r 4007b5072c4a iro/.eric4project/iro.e4p --- a/iro/.eric4project/iro.e4p Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ - - - - - - - diff -r 830204e316ca -r 4007b5072c4a iro/.eric4project/iro.e4q --- a/iro/.eric4project/iro.e4q Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff -r 830204e316ca -r 4007b5072c4a iro/.eric4project/iro.e4t --- a/iro/.eric4project/iro.e4t Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff -r 830204e316ca -r 4007b5072c4a iro/MyIro_daemon.inst --- a/iro/MyIro_daemon.inst Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -#! /bin/sh -NAME="Iro" -USER=sandy -HOMEDIR=/home/${USER} -DEAMON=${HOMEDIR}/bin/MyIro -DEAMON_OPTS="" -PID=${HOMEDIR}/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 --background --oknodo --pidfile $PID --make-pidfile --user ${USER} --group ${USER} --chdir ${HOMEDIR} --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 1 diff -r 830204e316ca -r 4007b5072c4a iro/acounting.py --- a/iro/acounting.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- - -from database import Database -import logging -logger=logging.getLogger("iro.acounting"); - -class Acounting(Database): - def __init__(self,id, connection): - Database.__init__(self,connection) - self.id=id - - def setId(self,id, user): - self.id=id - if user: - self.connect() - self.cursor.execute ("INSERT INTO %s (id,user) VALUES ('%s','%s')" % (self.connection['overview'], self.id, user)) - self.disconnect() - - - def getStatus(self): - self.connect() - self.cursor.execute ("SELECT status,tel FROM %s WHERE id='%s'" % (self.connection['table'], self.id)) - ret= self.cursor.fetchall() - self.disconnect() - return ret - - def addGood(self, good,disconnect=True): - if type(good) == list: - for i in good: - self.addGood(i) - if disconnect: - self.disconnect() - else: - self.connect() - self.cursor.execute("INSERT INTO %s (id,tel,status) VALUES('%s','%s','sended')" % (self.connection['table'], self.id, good)) - if disconnect: - self.disconnect() - - - def addFailed(self, failed,disconnect=True): - if type(failed) == list: - for i in failed: - self.addFailed(i,False) - if disconnect: - self.disconnect() - else: - self.connect() - self.cursor.execute ("INSERT INTO %s (id,tel,status) VALUES('%s','%s','failed')"%(self.connection['table'], self.id, failed)) - if disconnect: - self.disconnect() diff -r 830204e316ca -r 4007b5072c4a iro/anbieter/FAX_de.py --- a/iro/anbieter/FAX_de.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (C) 2009 Sandro Knauß - -#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 . - -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 diff -r 830204e316ca -r 4007b5072c4a iro/anbieter/__init__.py --- a/iro/anbieter/__init__.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (C) 2009 Sandro Knauß - -#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 . - -from sipgate import sipgate -from geonet import geonet -from FAX_de import FAX_de -from smtp import SMTP -from smstrade import smstrade -import content diff -r 830204e316ca -r 4007b5072c4a iro/anbieter/anbieter.py --- a/iro/anbieter/anbieter.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (C) 2009 Sandro Knauß - -#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 . - -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 - - def setJob(self, job): - self.job=job diff -r 830204e316ca -r 4007b5072c4a iro/anbieter/geonet.py --- a/iro/anbieter/geonet.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (C) 2009 Sandro Knauß - -#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 . - -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) diff -r 830204e316ca -r 4007b5072c4a iro/anbieter/gsm0338.py --- a/iro/anbieter/gsm0338.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,192 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -import codecs -import _multibytecodec as mbc - -ENCODING_NAME = "gsm0338" - -decoding_map= { -unichr(0x00):unichr(0x0040), # COMMERCIAL AT -unichr(0x01):unichr(0x00A3), # POUND SIGN -unichr(0x02):unichr(0x0024), # DOLLAR SIGN -unichr(0x03):unichr(0x00A5), # YEN SIGN -unichr(0x04):unichr(0x00E8), # LATIN SMALL LETTER E WITH GRAVE -unichr(0x05):unichr(0x00E9), # LATIN SMALL LETTER E WITH ACUTE -unichr(0x06):unichr(0x00F9), # LATIN SMALL LETTER U WITH GRAVE -unichr(0x07):unichr(0x00EC), # LATIN SMALL LETTER I WITH GRAVE -unichr(0x08):unichr(0x00F2), # LATIN SMALL LETTER O WITH GRAVE -unichr(0x09):unichr(0x00E7), # LATIN SMALL LETTER C WITH CEDILLA -unichr(0x0A):unichr(0x000A), # LINE FEED -unichr(0x0B):unichr(0x00D8), # LATIN CAPITAL LETTER O WITH STROKE -unichr(0x0C):unichr(0x00F8), # LATIN SMALL LETTER O WITH STROKE -unichr(0x0D):unichr(0x000D), # CARRIAGE RETURN -unichr(0x0E):unichr(0x00C5), # LATIN CAPITAL LETTER A WITH RING ABOVE -unichr(0x0F):unichr(0x00E5), # LATIN SMALL LETTER A WITH RING ABOVE -unichr(0x10):unichr(0x0394), # GREEK CAPITAL LETTER DELTA -unichr(0x11):unichr(0x005F), # LOW LINE -unichr(0x12):unichr(0x03A6), # GREEK CAPITAL LETTER PHI -unichr(0x13):unichr(0x0393), # GREEK CAPITAL LETTER GAMMA -unichr(0x14):unichr(0x039B), # GREEK CAPITAL LETTER LAMDA -unichr(0x15):unichr(0x03A9), # GREEK CAPITAL LETTER OMEGA -unichr(0x16):unichr(0x03A0), # GREEK CAPITAL LETTER PI -unichr(0x17):unichr(0x03A8), # GREEK CAPITAL LETTER PSI -unichr(0x18):unichr(0x03A3), # GREEK CAPITAL LETTER SIGMA -unichr(0x19):unichr(0x0398), # GREEK CAPITAL LETTER THETA -unichr(0x1A):unichr(0x039E), # GREEK CAPITAL LETTER XI -unichr(0x1B):unichr(0x00A0), # ESCAPE TO EXTENSION TABLE (or displayed as NBSP, see note above) -unichr(0x1B0A):unichr(0x000C), # FORM FEED -unichr(0x1B14):unichr(0x005E), # CIRCUMFLEX ACCENT -unichr(0x1B28):unichr(0x007B), # LEFT CURLY BRACKET -unichr(0x1B29):unichr(0x007D), # RIGHT CURLY BRACKET -unichr(0x1B2F):unichr(0x005C), # REVERSE SOLIDUS -unichr(0x1B3C):unichr(0x005B), # LEFT SQUARE BRACKET -unichr(0x1B3D):unichr(0x007E), # TILDE -unichr(0x1B3E):unichr(0x005D), # RIGHT SQUARE BRACKET -unichr(0x1B40):unichr(0x007C), # VERTICAL LINE -unichr(0x1B65):unichr(0x20AC), # EURO SIGN -unichr(0x1C):unichr(0x00C6), # LATIN CAPITAL LETTER AE -unichr(0x1D):unichr(0x00E6), # LATIN SMALL LETTER AE -unichr(0x1E):unichr(0x00DF), # LATIN SMALL LETTER SHARP S (German) -unichr(0x1F):unichr(0x00C9), # LATIN CAPITAL LETTER E WITH ACUTE -unichr(0x20):unichr(0x0020), # SPACE -unichr(0x21):unichr(0x0021), # EXCLAMATION MARK -unichr(0x22):unichr(0x0022), # QUOTATION MARK -unichr(0x23):unichr(0x0023), # NUMBER SIGN -unichr(0x24):unichr(0x00A4), # CURRENCY SIGN -unichr(0x25):unichr(0x0025), # PERCENT SIGN -unichr(0x26):unichr(0x0026), # AMPERSAND -unichr(0x27):unichr(0x0027), # APOSTROPHE -unichr(0x28):unichr(0x0028), # LEFT PARENTHESIS -unichr(0x29):unichr(0x0029), # RIGHT PARENTHESIS -unichr(0x2A):unichr(0x002A), # ASTERISK -unichr(0x2B):unichr(0x002B), # PLUS SIGN -unichr(0x2C):unichr(0x002C), # COMMA -unichr(0x2D):unichr(0x002D), # HYPHEN-MINUS -unichr(0x2E):unichr(0x002E), # FULL STOP -unichr(0x2F):unichr(0x002F), # SOLIDUS -unichr(0x30):unichr(0x0030), # DIGIT ZERO -unichr(0x31):unichr(0x0031), # DIGIT ONE -unichr(0x32):unichr(0x0032), # DIGIT TWO -unichr(0x33):unichr(0x0033), # DIGIT THREE -unichr(0x34):unichr(0x0034), # DIGIT FOUR -unichr(0x35):unichr(0x0035), # DIGIT FIVE -unichr(0x36):unichr(0x0036), # DIGIT SIX -unichr(0x37):unichr(0x0037), # DIGIT SEVEN -unichr(0x38):unichr(0x0038), # DIGIT EIGHT -unichr(0x39):unichr(0x0039), # DIGIT NINE -unichr(0x3A):unichr(0x003A), # COLON -unichr(0x3B):unichr(0x003B), # SEMICOLON -unichr(0x3C):unichr(0x003C), # LESS-THAN SIGN -unichr(0x3D):unichr(0x003D), # EQUALS SIGN -unichr(0x3E):unichr(0x003E), # GREATER-THAN SIGN -unichr(0x3F):unichr(0x003F), # QUESTION MARK -unichr(0x40):unichr(0x00A1), # INVERTED EXCLAMATION MARK -unichr(0x41):unichr(0x0041), # LATIN CAPITAL LETTER A -unichr(0x42):unichr(0x0042), # LATIN CAPITAL LETTER B -unichr(0x43):unichr(0x0043), # LATIN CAPITAL LETTER C -unichr(0x44):unichr(0x0044), # LATIN CAPITAL LETTER D -unichr(0x45):unichr(0x0045), # LATIN CAPITAL LETTER E -unichr(0x46):unichr(0x0046), # LATIN CAPITAL LETTER F -unichr(0x47):unichr(0x0047), # LATIN CAPITAL LETTER G -unichr(0x48):unichr(0x0048), # LATIN CAPITAL LETTER H -unichr(0x49):unichr(0x0049), # LATIN CAPITAL LETTER I -unichr(0x4A):unichr(0x004A), # LATIN CAPITAL LETTER J -unichr(0x4B):unichr(0x004B), # LATIN CAPITAL LETTER K -unichr(0x4C):unichr(0x004C), # LATIN CAPITAL LETTER L -unichr(0x4D):unichr(0x004D), # LATIN CAPITAL LETTER M -unichr(0x4E):unichr(0x004E), # LATIN CAPITAL LETTER N -unichr(0x4F):unichr(0x004F), # LATIN CAPITAL LETTER O -unichr(0x50):unichr(0x0050), # LATIN CAPITAL LETTER P -unichr(0x51):unichr(0x0051), # LATIN CAPITAL LETTER Q -unichr(0x52):unichr(0x0052), # LATIN CAPITAL LETTER R -unichr(0x53):unichr(0x0053), # LATIN CAPITAL LETTER S -unichr(0x54):unichr(0x0054), # LATIN CAPITAL LETTER T -unichr(0x55):unichr(0x0055), # LATIN CAPITAL LETTER U -unichr(0x56):unichr(0x0056), # LATIN CAPITAL LETTER V -unichr(0x57):unichr(0x0057), # LATIN CAPITAL LETTER W -unichr(0x58):unichr(0x0058), # LATIN CAPITAL LETTER X -unichr(0x59):unichr(0x0059), # LATIN CAPITAL LETTER Y -unichr(0x5A):unichr(0x005A), # LATIN CAPITAL LETTER Z -unichr(0x5B):unichr(0x00C4), # LATIN CAPITAL LETTER A WITH DIAERESIS -unichr(0x5C):unichr(0x00D6), # LATIN CAPITAL LETTER O WITH DIAERESIS -unichr(0x5D):unichr(0x00D1), # LATIN CAPITAL LETTER N WITH TILDE -unichr(0x5E):unichr(0x00DC), # LATIN CAPITAL LETTER U WITH DIAERESIS -unichr(0x5F):unichr(0x00A7), # SECTION SIGN -unichr(0x60):unichr(0x00BF), # INVERTED QUESTION MARK -unichr(0x61):unichr(0x0061), # LATIN SMALL LETTER A -unichr(0x62):unichr(0x0062), # LATIN SMALL LETTER B -unichr(0x63):unichr(0x0063), # LATIN SMALL LETTER C -unichr(0x64):unichr(0x0064), # LATIN SMALL LETTER D -unichr(0x65):unichr(0x0065), # LATIN SMALL LETTER E -unichr(0x66):unichr(0x0066), # LATIN SMALL LETTER F -unichr(0x67):unichr(0x0067), # LATIN SMALL LETTER G -unichr(0x68):unichr(0x0068), # LATIN SMALL LETTER H -unichr(0x69):unichr(0x0069), # LATIN SMALL LETTER I -unichr(0x6A):unichr(0x006A), # LATIN SMALL LETTER J -unichr(0x6B):unichr(0x006B), # LATIN SMALL LETTER K -unichr(0x6C):unichr(0x006C), # LATIN SMALL LETTER L -unichr(0x6D):unichr(0x006D), # LATIN SMALL LETTER M -unichr(0x6E):unichr(0x006E), # LATIN SMALL LETTER N -unichr(0x6F):unichr(0x006F), # LATIN SMALL LETTER O -unichr(0x70):unichr(0x0070), # LATIN SMALL LETTER P -unichr(0x71):unichr(0x0071), # LATIN SMALL LETTER Q -unichr(0x72):unichr(0x0072), # LATIN SMALL LETTER R -unichr(0x73):unichr(0x0073), # LATIN SMALL LETTER S -unichr(0x74):unichr(0x0074), # LATIN SMALL LETTER T -unichr(0x75):unichr(0x0075), # LATIN SMALL LETTER U -unichr(0x76):unichr(0x0076), # LATIN SMALL LETTER V -unichr(0x77):unichr(0x0077), # LATIN SMALL LETTER W -unichr(0x78):unichr(0x0078), # LATIN SMALL LETTER X -unichr(0x79):unichr(0x0079), # LATIN SMALL LETTER Y -unichr(0x7A):unichr(0x007A), # LATIN SMALL LETTER Z -unichr(0x7B):unichr(0x00E4), # LATIN SMALL LETTER A WITH DIAERESIS -unichr(0x7C):unichr(0x00F6), # LATIN SMALL LETTER O WITH DIAERESIS -unichr(0x7D):unichr(0x00F1), # LATIN SMALL LETTER N WITH TILDE -unichr(0x7E):unichr(0x00FC), # LATIN SMALL LETTER U WITH DIAERESIS -unichr(0x7F):unichr(0x00E0), # LATIN SMALL LETTER A WITH GRAVE -} - -encoding_map=dict([(v,k) for (k,v) in decoding_map.items()]) - -class Codec(codecs.Codec): - def encode(self,input,errors='strict'): - ret="" - for i in input: - ret+=encoding_map[i] - return (ret,len(ret)) - def decode(self,input,errors='strict'): - ret="" - for i in input: - ret+=decoding_map[i] - return (ret,len(ret)) - - - -class StreamWriter(Codec,mbc.MultibyteStreamWriter,codecs.StreamWriter): - pass - -class StreamReader(Codec,mbc.MultibyteStreamReader,codecs.StreamReader): - pass - -### encodings module API - -def getregentry(): - return (Codec().encode,Codec().decode,StreamReader,StreamWriter) - - -def gsm_search(encoding): - if not encoding == ENCODING_NAME: - return - return getregentry() - -# Register our codec when we load the module -codecs.register(gsm_search) - -if __name__ == "__main__": - text = "€öäüß" - text2 = unicode(text,"utf-8").encode("gsm0338") - assert(text2==u"\u1B65\x7C\x7B\x7E\x1E") - text="" - text2 = unicode(text,"utf-8").encode("gsm0338") - assert(text==text2) - diff -r 830204e316ca -r 4007b5072c4a iro/anbieter/sipgate.py --- a/iro/anbieter/sipgate.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (C) 2009 Sandro Knauß - -#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 . - - -from anbieter import anbieter -from telnumber import telnumber, InvalidTel -import ConfigParser -import xmlrpclib -import logging -logger=logging.getLogger("sipgate") - -class NoValidStatusCode(Exception): - def __init__(self, value): - self.value = value - - def __str__(self): - return repr(self.value) - -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,filenames): - """Read basic options from the config file""" - cp = ConfigParser.ConfigParser() - cp.read(filenames) - 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""" - logger.debug('sipgate.sendSMS(%s,%s)'%(sms.getContent(), str(recipients))) - args={ - "TOS" : "text", - "Content" : sms.getContent() - } - self.__send(args,recipients) - - def sendFAX(self,fax,recipients): - """send the PDF file $fax to $recipients""" - logger.debug('sipgate.sendFAX(%s,%s)'%(fax, str(recipients))) - args={ - "TOS" : "fax", - "Content" : xmlrpclib.Binary(fax.getAttachment(0)), - } - self.__send(args,recipients) - - def __connect(self): - """connect to sipgate XMLRPC Server""" - logger.debug("sipgate.__connect()-"+self.url%(self.user,"XXXXXXXX")) - - self.serv=xmlrpclib.ServerProxy(self.url%(self.user,self.password)) - self.samurai=self.serv.samurai - - args_identify = { - "ClientName" : "anbieter.py", - "ClientVersion" : "V1.0", - "ClientVendor" : "Sandro Knauss" - } - self.__send_method(self.samurai.ClientIdentify, args_identify) - return self.serv - - def __send_method(self, func, args=None): - """execute $func and test weather if the func ran successfully or not""" - logger.debug("sipgate.__send_method(func,%s)"%( args)) - - 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'])) - logger.debug("sipgate.__send_method(..):ok"); - return xmlrpc_result - - def __send(self,args,recipients): - """main sending method - sending the args to $recipients""" - sended=[] - - serv=self.__connect() - logger.debug('sipgate.__send(%s,%s)'%(args, recipients)) - 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) - self.__send_method(serv.samurai.SessionInitiate, args) - self.updateStatus(arranged=recipient) - - except (InvalidTel, 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""" - logger.debug('sipgate.__disconnect()') - self.samurai=None - self.serv=None - self.xmlrpc=None diff -r 830204e316ca -r 4007b5072c4a iro/controller/task.py --- a/iro/controller/task.py Sat Mar 24 00:02:42 2012 +0100 +++ b/iro/controller/task.py Sat Mar 24 00:07:40 2012 +0100 @@ -1,5 +1,6 @@ from functools import partial +from twisted.python import log from twisted.internet.defer import inlineCallbacks, returnValue, maybeDeferred, Deferred from ..error import NoRouteForTask, RejectRecipient @@ -44,15 +45,16 @@ offer = os.next() d = maybeDeferred(offers[offer],self.recipient,self.job.message) d.addCallback(self.d.callback) - d.addErrback(addErr) + d.addErrback(addErr,offer) d.addErrback(self.d.errback) return d except StopIteration: self.d.errback(NoRouteForTask()) - def addErr(failure): - failure.trap(RejectRecipient) - return n() + def addErr(failure, offer): + if not isinstance(failure.value, RejectRecipient): + log.err(_why="Job(%s): Send to '%s' failed via '%s'"%(self.job.dbjob, self.recipient, offer),_stuff=failure) + n() n() diff -r 830204e316ca -r 4007b5072c4a iro/database.py --- a/iro/database.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import MySQLdb -import sqlite3 -class Database(object): - def __init__(self,connection): - self.conn=None - self.cursor=None - self.connection=connection - self.testConnection() - - def testConnection(self): - self.connect() - self.disconnect() - - def getConn(self): - return self.conn - - def getCursor(self): - return self.cursor - - def connect(self): - if not self.getConn(): - if (self.connection['type']=='mysql'): - self.conn=MySQLdb.connect( - host = self.connection["host"], - db = self.connection["db"], - user = self.connection["user"], - passwd = self.connection["passwd"], - ) - if (self.connection['type']=='sqlite'): - self.conn=sqlite3.connect(self.connection['path']) - - if not self.getCursor(): - self.cursor = self.conn.cursor() - - def disconnect(self): - if self.getCursor(): - self.cursor.close() - self.cursor=None - if self.getConn(): - self.conn.close() - self.conn=None - - diff -r 830204e316ca -r 4007b5072c4a iro/install.py --- a/iro/install.py Sat Mar 24 00:02:42 2012 +0100 +++ b/iro/install.py Sat Mar 24 00:07:40 2012 +0100 @@ -1,3 +1,5 @@ +# -*- test-case-name: iro.tests.test_install -*- + from twisted.python import log import logging from sqlalchemy import create_engine @@ -70,7 +72,8 @@ try: ret["orphand"].remove(Offer.get(session, provider, r, t).name) except: - session.add(Offer(provider=provider,route=r,typ=t,name='%s_%s_%s'%(provider,t,r))) + if write: + session.add(Offer(provider=provider,route=r,typ=t,name='%s_%s_%s'%(provider,t,r))) ret["added"].add("%s_%s_%s"%(provider,t,r)) return ret diff -r 830204e316ca -r 4007b5072c4a iro/iro.api --- a/iro/iro.api Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -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.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.smstrade.InternetConnectionError.__str__?6() -iro.anbieter.smstrade.InternetConnectionError?1(url) -iro.anbieter.smstrade.__send?6(self, key, route, to, message, from_=None, timestamp=None) -iro.anbieter.smstrade.sendSMS?4(self, sms, recipients) -iro.anbieter.smstrade.smstrade.read_basic_config?4(filename) -iro.anbieter.smstrade.smstrade.section?7 -iro.anbieter.smstrade.smstrade.url?7 -iro.anbieter.smstrade.smstrade?1() -iro.anbieter.smstrade.updateStatus?4(self, arranged=None, failed=None) -iro.anbieter.smtp.SMTP.prepareSMTP?4() -iro.anbieter.smtp.SMTP.read_basic_config?4(config_filename=None) -iro.anbieter.smtp.SMTP.sendMail?4(mail, recipients) -iro.anbieter.smtp.SMTP.shutdownSMTP?4() -iro.anbieter.smtp.SMTP.updateStatus?4(arranged=None, failed=None) -iro.anbieter.smtp.SMTP?1(config_filename=None, section="smtp") -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.Mail.as_string?4() -iro.content.Mail.sendto?4(anbieter, recipients) -iro.content.Mail?1(subject, body) -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.MyManager.certificate?7 -iro.iro.MyManager.userdb?7 -iro.iro.MySMTP.setJob?4(job) -iro.iro.MySMTP.updateStatus?4(arranged=None, failed=None) -iro.iro.MySMTP?1(config_filename=None, section="smtp") -iro.iro.MySipgate.setJob?4(job) -iro.iro.MySipgate.updateStatus?4(arranged=None, failed=None) -iro.iro.MySipgate?1(user="", password="") -iro.iro.MySmstrade.setJob?4(job) -iro.iro.MySmstrade.updateStatus?4(arranged=None, failed=None) -iro.iro.MySmstrade?1() -iro.iro.MyUserDB.createUser?4(user) -iro.iro.MyUserDB?1(userlist, jobqueue) -iro.iro.start?4(userlist) -iro.job.Job.addFailed?4(failed) -iro.job.Job.addGood?4(good) -iro.job.Job.getName?4() -iro.job.Job.getProvider?4() -iro.job.Job.getStatus?4(detailed) -iro.job.Job.start?4() -iro.job.Job.stop?4() -iro.job.Job?1(provider, name) -iro.job.MessageJob.getMessage?4() -iro.job.MessageJob.getRecipients?4() -iro.job.MessageJob.start?4() -iro.job.MessageJob.stop?4() -iro.job.MessageJob?1(provider, name, message, recipients) -iro.joblist.Joblist.__getitem__?6(key) -iro.joblist.Joblist.__registerJob__?6(job) -iro.joblist.Joblist._createID?5() -iro.joblist.Joblist.newFAX?4(subject, fax, recipients) -iro.joblist.Joblist.newMail?4(subject, body, recipients) -iro.joblist.Joblist.newSMS?4(message, recipients) -iro.joblist.Joblist?1(manager, queue, providerlist) -iro.providerlist.Providerlist.add?4(name, provider, typeslist) -iro.providerlist.Providerlist.getDefault?4(stype) -iro.providerlist.Providerlist.getProvider?4(stype, name="default") -iro.providerlist.Providerlist.getProviderlist?4(stype) -iro.providerlist.Providerlist.setDefault?4(stype, name) -iro.providerlist.Providerlist?1() -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.setUp?4() -iro.test.TestServer.tearDown?4() -iro.test.TestServer.testGetDefault?4() -iro.test.TestServer.testGetProvider?4() -iro.test.TestServer.testLogin?4() -iro.test.TestServer.testTwoUser?4() -iro.test.TestServer.testsendSMS?4() -iro.test.init_server?4() -iro.user.Admin?1(jobqueue) -iro.user.NotSupportedFeature.__str__?6() -iro.user.NotSupportedFeature?1(name) -iro.user.User.getDefaultProvider?4(name) -iro.user.User.getProvider?4(name) -iro.user.User.startFAX?4() -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() \ No newline at end of file diff -r 830204e316ca -r 4007b5072c4a iro/iro.e4p --- a/iro/iro.e4p Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,225 +0,0 @@ - - - - - - - - Python - Console - Ein Daemon zum Senden von Massensms, -faxen und emails - 0.1 - Sandro Knauß - bugs@sandroknauss.de - - iro.py - __init__.py - xmlrpc/SecureXMLRPCServer.py - xmlrpc/__init__.py - xmlrpc/SecureAuthentificateXMLRPCServer.py - xmlrpc/AuthentificateXMLRPCServer.py - xmlrpc/SecureUserdbXMLRPCServer.py - worker.py - user.py - test.py - providerlist.py - joblist.py - job.py - anbieter/smtp.py - anbieter/geonet.py - anbieter/content.py - anbieter/__init__.py - anbieter/telnumber.py - anbieter/test.py - anbieter/FAX_de.py - anbieter/sipgate.py - anbieter/gsm0338.py - anbieter/anbieter.py - anbieter/smstrade.py - - - - - - - - - - - iro.conf.inst - iro.conf - - iro.py - - None - - - - add - - - - - - - - checkout - - - - - - - - commit - - - - - - - - diff - - - - - - - - export - - - - - - - - global - - - - - - - - history - - - - - - - - log - - - - - - - - remove - - - - - - - - status - - - - - - - - tag - - - - - - - - update - - - - - - - - - - - - standardLayout - - - True - - - - - - - - - - - - - - - ERIC4API - - - - - basePackage - - - iro - - - ignoreFilePatterns - - - - - - - - includePrivate - - - True - - - languages - - - - Python - - - - outputFile - - - iro.api - - - useRecursion - - - True - - - - - - - \ No newline at end of file diff -r 830204e316ca -r 4007b5072c4a iro/iro.py --- a/iro/iro.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (C) 2009 Sandro Knauß - -#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 . - -import multiprocessing, logging -#logging anfangen -logger=logging.getLogger("iro") -logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)s(%(processName)s)-%(levelname)s: %(message)s') - - -# Server code -from xmlrpc import SecureUserDBXMLRPCServer,UserDB - -from user import User, Admin -import anbieter -import ConfigParser - -from job import SMSJob, FAXJob, MailJob -from joblist import Joblist -from providerlist import Providerlist -from acounting import Acounting - -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"](user["name"],self.jobqueue) - - - - -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 MySmstrade(anbieter.smstrade): - - def __init__(self ): - anbieter.smstrade.__init__(self ) - - 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) - - - -def start(userlist): - from multiprocessing import Queue - from multiprocessing.managers import BaseManager - - - class MyManager(BaseManager): - pass - - MyManager.register('SMSJob', SMSJob) - MyManager.register('FaxJob', FAXJob) - MyManager.register('MailJob',MailJob) - MyManager.register('Providerlist',Providerlist) - MyManager.register('Acounting',Acounting) - manager = MyManager() - manager.start() - - - conf=["iro.conf", "~/iro.conf","/etc/iro/iro.conf"] - - #anbieter erzeugen und konfigurieren - - sip=MySipgate() - sip.read_basic_config(conf) - - localhost=MySMTP() - localhost.read_basic_config(conf) - - smstrade=MySmstrade() - smstrade.read_basic_config(conf) - - cp = ConfigParser.ConfigParser() - cp.read(conf) - dbconn={'type':cp.get('db', 'type'), - 'host':cp.get('db', 'host'), - 'db':cp.get('db', 'db'), - 'user':cp.get('db', 'user'), - 'passwd':cp.get('db', 'passwd'), - 'table':cp.get('db', 'table'), - } - - - #Benutzerdatenbank erstellen - queue = Queue() - provider=manager.Providerlist() - provider.add("sipgate", sip, ["sms", "fax", ]) - provider.add("smstrade", smstrade, ["sms", ]) - #provider.add("geonet", None, ["sms", "fax", ]) - #provider.add("fax.de", None, ["sms", "fax", ]) - provider.add("localhost", localhost, ["mail", ]) - provider.setDefault("sms","smstrade") - provider.setDefault("fax","sipgate") - provider.setDefault("mail","localhost") - jobqueue=Joblist(manager, queue, provider,dbconn) - - userdb=MyUserDB(userlist,jobqueue) - - #working thread erstellen - from worker import Worker - worker=Worker(queue) - worker.start() - - #Server starten - cp = ConfigParser.ConfigParser() - cp.read(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" - - logger.info('Server gestartet...') - try: - server.serve_forever() - except KeyboardInterrupt: - pass - except: - logger.exception('Äh, ein Fehler ist aufgetreten') - finally: - logger.info('Server wird beendet...') - queue.close() - worker.terminate() - -if __name__ == '__main__': - userlist=[{"name":"test","password":"test", "class":User}, - {"name":"test2","password":"test2", "class": Admin}] - start(userlist) - - diff -r 830204e316ca -r 4007b5072c4a iro/job.py --- a/iro/job.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,121 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (C) 2009 Sandro Knauß - -#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 . - -class Job(object): - ''' - Basic class for all jobs - ''' - def __init__(self,providerlist,provider, name): - self.providerlist=providerlist - self.provider=provider - self.name=name - self.status = "init" - self.dStatus={"good":[], "failed":[]} - self.id=None - self.acounting=None - - def setAcounting(self,ac): - self.acounting=ac - - def setId(self, id): - self.id=id - if self.acounting: - self.acounting.setId(id) - - def start(self,indifier=None): - self.indifier=indifier - self.status = "started" - - def stop(self): - self.status = "stopped" - - def setLog(self,log): - self.log=log - - def getStatus(self,detailed=False): - if detailed and self.status == "started" or self.status == "sended": - return self.status, self.dStatus - return self.status,{} - - def setStatus(self,status): - self.status=status - - def getName(self): - return self.name - - def getProvider(self): - return None - - def addGood(self, good): - if self.acounting: - self.acounting.addGood(good) - if type(good) == list: - self.dStatus['good']=self.dStatus['good']+good - else: - self.dStatus['good'].append(good) - - def addFailed(self, failed): - if self.acounting: - self.acounting.addFailed(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,providerlist,provider, name, message,recipients): - self.message=message - self.recipients=recipients - Job.__init__(self,providerlist,provider, name) - - def stop(self): - pass - - def start(self, id=None): - Job.start(self,id) - self.getProvider().setJob(self) - self.message.sendto(self.getProvider(), self.recipients) - self.status="sended" - - def getMessage(self): - return self.message - - def getRecipients(self): - return self.recipients - - -class SMSJob(MessageJob): - def __init__(self,providerlist,provider, name, message,recipients): - MessageJob.__init__(self,providerlist,provider, name, message,recipients) - - def getProvider(self): - return self.providerlist.getProvider("sms", self.provider) - -class FAXJob(MessageJob): - def __init__(self,providerlist,provider, name, message,recipients): - MessageJob.__init__(self,providerlist,provider, name, message,recipients) - - def getProvider(self): - return self.providerlist.getProvider("fax", self.provider) - -class MailJob(MessageJob): - def __init__(self,providerlist,provider, name, message,recipients): - MessageJob.__init__(self,providerlist,provider, name, message,recipients) - - def getProvider(self): - return self.providerlist.getProvider("mail", self.provider) - - diff -r 830204e316ca -r 4007b5072c4a iro/joblist.py --- a/iro/joblist.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (C) 2009 Sandro Knauß - -#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 . - -from anbieter import content -import hashlib, os, time -import logging -logger=logging.getLogger("iro.joblist"); - -class Joblist: - ''' - Providing an list of jobs; each new job gets a hash id - ''' - def __init__(self,manager, queue,providerlist,dbconn=None): - self.jobs={} - self.manager=manager - self.queue=queue - self.providerlist=providerlist - self.dbconn=dbconn - - - def __getitem__(self,key): - return self.jobs[key] - - def __registerJob__(self, job, user): - id = self._createID() - if self.dbconn: - job.setAcounting(self.manager.Acounting(id,self.dbconn)) - job.setId(id, user) - self.jobs[id]=job - self.queue.put(job) - return id - - def newSMS(self, message, recipients, provider="default", user=None): - ''' - creates a new SMS - ''' - job=self.manager.SMSJob(self.providerlist, provider,message, content.SMS(message),recipients) - return self.__registerJob__(job,user) - - def newFAX(self,subject, fax,recipients,provider="default",user=None): - ''' - creates a new Fax - ''' - job=self.manager.FaxJob(self.providerlist, provider,subject, content.FAX(subject,'' ,fax),recipients) - return self.__registerJob__(job,user) - - def newMail(self, subject, body, recipients, frm, provider="default",user=None): - ''' - creates a new Mail - ''' - job=self.manager.MailJob(self.providerlist, provider,subject, content.Mail(subject, body, frm),recipients) - return self.__registerJob__(job,user) - - def _createID(self): - ''' - creats a random hash id - ''' - while True: - m = hashlib.sha1() - m.update(str(time.time())) - m.update(os.urandom(10)) - if not self.jobs.has_key(m.hexdigest): - if not self.dbconn: - self.jobs[m.hexdigest()]=None - break - if not self.manager.Acounting(m.hexdigest(),self.dbconn).getStatus(): - self.jobs[m.hexdigest()]=None - break - return m.hexdigest() diff -r 830204e316ca -r 4007b5072c4a iro/model/job.py --- a/iro/model/job.py Sat Mar 24 00:02:42 2012 +0100 +++ b/iro/model/job.py Sat Mar 24 00:07:40 2012 +0100 @@ -1,5 +1,4 @@ -from twisted.python import log -from twisted.python import threadable +from twisted.python import log, threadable from datetime import datetime from collections import MutableMapping @@ -21,6 +20,7 @@ self.tasks={} self.c = 0 self.status = "started" + log.msg("Job(%s) created."%(self.dbjob)) def addTask(self,task): self.tasks[task.recipient] = task @@ -37,6 +37,7 @@ return job.status = status self.status = status + log.msg("Job(%s) status changed to: %s."%(self.dbjob, status)) session.commit() @dbdefer @@ -44,10 +45,10 @@ c = self.incStatus() job = schema.Job.get(session, self.dbjob) - if job.status in ["started","init"]: - self._status(session,"sending") if c == len(self.recipients): self._status(session,"sended") + elif job.status in ["started","init"]: + self._status(session,"sending") if status.costs > 0: o = schema.Offer.get(session, status.provider.name, status.route, self.message.typ) diff -r 830204e316ca -r 4007b5072c4a iro/model/message.py --- a/iro/model/message.py Sat Mar 24 00:02:42 2012 +0100 +++ b/iro/model/message.py Sat Mar 24 00:07:40 2012 +0100 @@ -21,16 +21,12 @@ class SMS(Message): def __init__(self, cont, from_ = None): - Message.__init__(self, cont, typ="sms") + Message.__init__(self, cont.encode("utf-8"), typ="sms") self.from_ = from_ - def sendto(self,anbieter,recipients): - anbieter.sendSMS(self,recipients) - - class Fax(Message): def __init__(self,header,cont,attachments=[]): - Message.__init__(self,cont, typ="fax") + Message.__init__(self,cont.encode("utf-8"),typ="fax") self.header=header self.attachments=attachments diff -r 830204e316ca -r 4007b5072c4a iro/newinterface.py --- a/iro/newinterface.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,269 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (C) 2009 Sandro Knauß - -#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 . -from twisted.web import soap, xmlrpc, resource, server -import logging -logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)s(%(processName)s)-%(levelname)s: %(message)s') - - -class User(object): - def __init__(self,name,userhash): - self.name=name - self.userhash=userhash - - def __repr__(self): - return"User<'%s','%s'>"%(self.name,self.userhash) - -users={"1":User("spam","1"), - "2":User("foo","2") -} - -def getuser(userhash): - try: - return users[userhash] - except KeyError: - raise UserNotFound() - -def with_user(f): - def new_f(*args,**kargs): - args=list(args) - logging.debug("Entering %s"%f.__name__) - try: - kargs["user"]=getuser(kargs["apikey"]) - del kargs["apikey"] - except KeyError: - kargs["user"]=getuser(args[1]) - del args[1] - ret=f(*args,**kargs) - logging.debug("Exited %s"%f.__name__) - return ret - new_f.__name__ = f.__name__ - return new_f - - -class InterfaceException(Exception): - def __init__(self, code=999, msg="Unbekannter Fehler."): - self.code=code - self.msg=msg - - def dict(self): - return {"code":self.code, - "msg":self.msg, - } - def __str__(self): - return "%i:%s"%(self.code,self.msg) - -class UserNotFound(InterfaceException): - def __init__(self): - InterfaceException.__init__(self, 901, "Der API-Key ist ungültig.") - -class ExternalException(InterfaceException): - def __init__(self): - InterfaceException.__init__(self, 950, "Fehler in externer API.") - - -class Interface(object): - '''class for a xmlrpc user - ''' - - @with_user - def status(self, user, id=None, detailed=False): - '''Gibt den aktuellen Status eines Auftrages oder Mehreren zurück. - - Keywords: - apikey[string]: Der API Key - id[hash]: Eine Auftragsnummer - detailed[boolean]: Details ausgeben - - Return: - jobs[list]: Eine Liste der Aufträge. - job.name[string]: Angebener Name - job.status[string]: Status des Auftrages - - - ''' - #return user.status(id,detailed) - return "" - - @with_user - def stop(self, user, id): - '''Stoppt den angegeben Auftrag. - - Keywords: - apikey[string]: Der API Key - id[hash]: Eine Auftragsnummer - - Return: - - ''' - return "" - - @with_user - def sms(self, user, message, recipients, route="default"): - '''Versendet eine SMS. - - Keywords: - apikey[string]: Der API Key - message[string]: Nachricht - recipients[list]: eine Liste von Emfänger-Nummern (gemäß ITU-T E.123) - route[string|list]: Route über den geschickt werden soll, - oder eine Liste von Routen, um Fallbacks anzugeben - - Return: - id[hash]: Die ID des Auftrages - - ''' - return "" - - @with_user - def fax(self, user, subject, fax, recipients, route="default"): - '''Versendet ein FAX. - - Keywords: - apikey[string]: Der API Key - subject[string]: Der Betreff - fax[string]: Das PDF base64 kodiert - recipients[list]: Eine Liste von Emfänger-Nummern (gemäß ITU-T E.123) - route[string|list]: Route über den geschickt werden soll, - oder eine Liste von Routen, um Fallbacks anzugeben - - Return: - id[hash]: Die ID des Auftrages - - ''' - return "" - - @with_user - def mail(self, user, subject, body, recipients, frm, route="default"): - '''Versendet eine Email. - - Keywords: - apikey[string]: Der API Key - subject[string]: Der Betreff - body[string]: Der Email Body - recipients[list]: Eine Liste von Emailadressen - frm[string]: Die Absender Emailadresse - route[string|list]: Route über den geschickt werden soll, - oder eine Liste von Routen, um Fallbacks anzugeben - - Return: - id[hash]: Die ID des Auftrages - - ''' - return "" - - @with_user - def routes(self, user, typ): - '''Gibt eine Liste aller verfügbaren Provider zurück. - - Keywords: - apikey[string]: Der API Key - typ[string]: Der Typ zu dem die Providerloste ausgeben werden soll - Einer der Liste ["sms","fax","mail"] - - Return: - providerlist[list]: Eine Liste aller möglichen Provider - - ''' - return "" - - @with_user - def defaultRoute(self, user, typ): - '''Gibt den Standardprovider zurück. - - Keywords: - apikey[string]: Der API Key - typ[string]: Der Typ zu dem die Providerloste ausgeben werden soll - Einer der Liste ["sms","fax","mail"] - - Return: - provider[string]: Der Standardprovider für den angeben Typ - - - ''' - return "" - - @with_user - def statistic(self, user): - '''Gibt eine Statik zurück über die versendendeten Nachrichten und des Preises. - - Keywords: - apikey[string]: Der API Key - - Return: - statistic[list]: Eine Liste nach Nachrichtentypen - ''' - return "" - - def listMethods(self): - """Since we override lookupProcedure, its suggested to override - listProcedures too. - """ - return self.listProcedures() - - - def listProcedures(self): - """Since we override lookupProcedure, its suggested to override - listProcedures too. - """ - return ['listMethods','status','stop','sms','fax','mail','routes','defaultRoute','statistic'] - - -class XMLRPCInterface(Interface,xmlrpc.XMLRPC): - def __init__(self): - xmlrpc.XMLRPC.__init__(self) - Interface.__init__(self) - - def lookupProcedure(self, procedurePath): - logging.debug("lookupProcedure('%s')"%procedurePath) - if procedurePath not in self.listProcedures(): - raise xmlrpc.NoSuchFunction(self.NOT_FOUND, - "procedure %s not found" % procedurePath) - try: - return getattr(self,procedurePath) - except KeyError: - raise xmlrpc.NoSuchFunction(self.NOT_FOUND, - "procedure %s not found" % procedurePath) - -class SOAPInterface(Interface,soap.SOAPPublisher): - def __init__(self): - soap.SOAPPublisher.__init__(self) - Interface.__init__(self) - - def lookupFunction(self, functionName): - """Lookup published SOAP function. - - Override in subclasses. Default behaviour - publish methods - starting with soap_, if they have true attribute useKeywords - they are expected to accept keywords. - - @return: tuple (callable, useKeywords), or (None, None) if not found. - """ - if functionName in self.listProcedures(): - function = getattr(self, functionName, None) - if function: - return function, getattr(function, "useKeywords", False) - return None - else: - return None - - -def main(): - from twisted.internet import reactor - root = resource.Resource() - root.putChild('RPC2', XMLRPCInterface()) - root.putChild('SOAP', SOAPInterface()) - reactor.listenTCP(7080, server.Site(root)) - reactor.run() - -if __name__ == '__main__': - main() diff -r 830204e316ca -r 4007b5072c4a iro/offer/smstrade.py --- a/iro/offer/smstrade.py Sat Mar 24 00:02:42 2012 +0100 +++ b/iro/offer/smstrade.py Sat Mar 24 00:07:40 2012 +0100 @@ -112,7 +112,7 @@ parameters= {"key": self.key, "route": route, "to": to, - "message": sms.content.encode("utf-8"), + "message": sms.content, "charset":"utf-8", "debug": self.testmode, "message_id":True, @@ -127,7 +127,7 @@ length=len(sms.content) for s in doubleChar: - length += sms.content.encode("utf-8").count(s) + length += sms.content.count(s) parameters["concat_sms"] = True if length > 160 else False ps={} diff -r 830204e316ca -r 4007b5072c4a iro/providerlist.py --- a/iro/providerlist.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (C) 2009 Sandro Knauß - -#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 . - -class Providerlist: - def __init__(self): - self.provider={} - self.types={} - self.defaults={} - - def add(self, name, provider, typeslist): - self.provider[name]={"name":name, "class":provider, "types":typeslist} - for stype in typeslist: - try: - self.types[stype].append(self.provider[name]) - except KeyError: - self.types[stype]=[self.provider[name]] - - - def setDefault(self, stype, name): - self.defaults[stype]=self.provider[name] - - def getDefault(self, stype): - return self.defaults[stype] - - def getProviderlist(self, stype): - llist=[ provider["name"] for provider in self.types[stype] ] - llist.sort() - return llist - - def status(self): - ret="provider:%s"%self.provider - ret +="\ntypes:%s"%self.types - return ret+"\ndefaults:%s"%self.defaults - - def getProvider(self, stype, name="default"): - if name=="default": - return self.getDefault(stype)["class"] - - if not stype in self.provider[name] ["types"]: - raise Exception("argh") - - return self.provider[name]["class"] diff -r 830204e316ca -r 4007b5072c4a iro/test_helpers/dbtestcase.py --- a/iro/test_helpers/dbtestcase.py Sat Mar 24 00:02:42 2012 +0100 +++ b/iro/test_helpers/dbtestcase.py Sat Mar 24 00:07:40 2012 +0100 @@ -13,6 +13,8 @@ from iro.controller.pool import dbPool +from .utils import DummyObserver + class DBTestCase(unittest.TestCase): '''a TestCase with DB connection you have to set self.session manually in setUp''' @@ -22,8 +24,11 @@ def setUp(self): md.setUp() + self.log = DummyObserver() + self.log.start() def tearDown(self): + self.log.stop() self.__cleanDB() def session(self,autocommit=True): diff -r 830204e316ca -r 4007b5072c4a iro/test_helpers/utils.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/iro/test_helpers/utils.py Sat Mar 24 00:07:40 2012 +0100 @@ -0,0 +1,18 @@ +from twisted.python import log + +class DummyObserver(object): + def __init__(self): + self.e=[] + + def start(self): + log.addObserver(self.emit) + + def stop(self): + log.removeObserver(self.emit) + + def emit(self, eventDict): + self.e.append(eventDict) + +class DummyPool(): + def run(self, f,*a,**k): + return f(*a,**k) diff -r 830204e316ca -r 4007b5072c4a iro/tests/install.py --- a/iro/tests/install.py Sat Mar 24 00:02:42 2012 +0100 +++ b/iro/tests/install.py Sat Mar 24 00:07:40 2012 +0100 @@ -1,28 +1,17 @@ #from mock import patch, Mock from twisted.trial import unittest -from twisted.python import log from sqlalchemy import create_engine +from sets import Set +import io import os from iro import install from iro import config -from iro.model.schema import Base - +from iro.model.schema import Base, Offer +from iro.model.utils import WithSession +from iro.offer.provider import providers, Provider from ..test_helpers.dbtestcase import md, SampleDatabase - -class DummyObserver(object): - def __init__(self): - self.e=[] - - def start(self): - log.addObserver(self.emit) - - def stop(self): - log.removeObserver(self.emit) - - def emit(self, eventDict): - self.e.append(eventDict) - +from ..test_helpers.utils import DummyObserver class TestInstallation(unittest.TestCase): '''test install script''' @@ -105,6 +94,70 @@ self.assertEqual(len(self.log.e),1) self.assertEqual(self.log.e[0]['message'], ("iro.conf exists and will not be overwritten.",)) - def testCheck(self): - pass - testCheck.todo = "to implement" + def testGetAllRoutesNone(self): + config.main.dburl=md.dburl2 + install.createDatabase() + self.assertEqual(install.getAllRoutes([]),{"orphand":Set(),"added":Set()}) + + def testGetAllRoutesOrphand(self): + config.main.dburl=md.dburl2 + install.createDatabase() + self.engine = create_engine(md.dburl2) + with WithSession(self.engine,True) as session: + session.add(Offer(provider="p",route="r",typ="t",name="test")) + session.add(Offer(provider="p",route="r2",typ="t",name="test2")) + self.assertEqual(install.getAllRoutes([]),{"orphand":Set(["test","test2"]),"added":Set()}) + + def testGetAllRoutesAdded(self): + config.main.dburl=md.dburl2 + install.createDatabase() + self.engine = create_engine(md.dburl2) + class TestProvider(Provider): + def __init__(self, name): + Provider.__init__(self, name, {"r":["1","2","3"]}) + providers["test"]=TestProvider + sample_config = """[p] +typ= test +test= foo +""" + config.configParser.readfp(io.BytesIO(sample_config)) + self.assertEqual(install.getAllRoutes(["p"]),{"orphand":Set(),"added":Set(["p_r_1","p_r_2","p_r_3"])}) + + #test writing + self.assertEqual(install.getAllRoutes(["p"],True),{"orphand":Set(),"added":Set(["p_r_1","p_r_2","p_r_3"])}) + with WithSession(self.engine,True) as session: + o = Set([i[0] for i in session.query(Offer.name).all()]) + self.assertEqual(o,Set(["p_r_1","p_r_2","p_r_3"])) + + #nothing to do anymore + self.assertEqual(install.getAllRoutes(["p"]),{"orphand":Set(),"added":Set()}) + + def testGetAllRoutesOaA(self): + config.main.dburl=md.dburl2 + install.createDatabase() + self.engine = create_engine(md.dburl2) + class TestProvider(Provider): + def __init__(self, name): + Provider.__init__(self, name, {"r":["1","2","3"]}) + providers["test"]=TestProvider + sample_config = """[p] +typ= test +test= foo +""" + config.configParser.readfp(io.BytesIO(sample_config)) + + with WithSession(self.engine,True) as session: + session.add(Offer(provider="q",route="r",typ="t",name="test")) + session.add(Offer(provider="q",route="r2",typ="t",name="test2")) + session.add(Offer(provider="p",route="1",typ="r",name="foo")) + self.assertEqual(install.getAllRoutes(["p"]),{"orphand":Set(["test","test2"]),"added":Set(["p_r_2","p_r_3"])}) + + #test writing + self.assertEqual(install.getAllRoutes(["p"],True),{"orphand":Set(["test","test2"]),"added":Set(["p_r_2","p_r_3"])}) + with WithSession(self.engine,True) as session: + o = Set([i[0] for i in session.query(Offer.name).all()]) + self.assertEqual(o,Set(["test","test2","foo","p_r_2","p_r_3"])) + + self.assertEqual(install.getAllRoutes(["p"]),{"orphand":Set(["test","test2"]),"added":Set()}) + + diff -r 830204e316ca -r 4007b5072c4a iro/tests/job.py --- a/iro/tests/job.py Sat Mar 24 00:02:42 2012 +0100 +++ b/iro/tests/job.py Sat Mar 24 00:07:40 2012 +0100 @@ -16,25 +16,7 @@ from iro.validate import vInteger from ..test_helpers.dbtestcase import DBTestCase - -class DummyPool(): - def run(self, f,*a,**k): - return f(*a,**k) - -from twisted.python import log - -class DummyObserver(object): - def __init__(self): - self.e=[] - - def start(self): - log.addObserver(self.emit) - - def stop(self): - log.removeObserver(self.emit) - - def emit(self, eventDict): - self.e.append(eventDict) +from ..test_helpers.utils import DummyPool class JobTestCase(DBTestCase): def setUp(self): @@ -70,6 +52,7 @@ self.assertEqual(j,[(job.dbjob,)]) self.assertEqual(exJobs[job.dbjob],job) + self.assertEqual(self.log.e[0]['message'], ("Job(%s) created."%job.dbjob,)) def testCreate2(self): with self.session() as session: @@ -114,8 +97,6 @@ class StatiTest(JobTestCase): def setUp(self): JobTestCase.setUp(self) - self.log = DummyObserver() - self.log.start() with self.session() as session: u = User(name='test',apikey='abcdef123456789') @@ -130,7 +111,6 @@ self.job = exJobs.create(u, [Telnumber('123456789')], SMS('test'), []) def tearDown(self): - self.log.stop() JobTestCase.tearDown(self) @@ -138,7 +118,8 @@ self.job.setError(Task(Telnumber('123456789'),self),Exception("muhaha")) errors = self.flushLoggedErrors(Exception) self.assertEqual(len(errors), 1) - self.assertEqual(self.log.e[0]['why'], "Error: Job(%s) to '0049123456789' failed."%self.job.dbjob) + self.assertEqual(self.log.e[1]['message'], ("Job(%s) status changed to: error."%self.job.dbjob,)) + self.assertEqual(self.log.e[2]['why'], "Error: Job(%s) to '0049123456789' failed."%self.job.dbjob) with self.session() as session: u = session.merge(self.user) @@ -150,7 +131,8 @@ status = Status(self.provider,"a") self.job.setStatus(task, status) - self.assertEqual(self.log.e[0]['message'], ("Job(%s) to '0049123456789' ended sucecessfully via bla:a."%self.job.dbjob,)) + self.assertEqual(self.log.e[1]['message'], ("Job(%s) status changed to: sended."%self.job.dbjob,)) + self.assertEqual(self.log.e[2]['message'], ("Job(%s) to '0049123456789' ended sucecessfully via bla:a."%self.job.dbjob,)) with self.session() as session: u = session.merge(self.user) diff -r 830204e316ca -r 4007b5072c4a iro/tests/model_validate.py --- a/iro/tests/model_validate.py Sat Mar 24 00:02:42 2012 +0100 +++ b/iro/tests/model_validate.py Sat Mar 24 00:07:40 2012 +0100 @@ -5,10 +5,7 @@ from iro.error import ValidateException from ..test_helpers.dbtestcase import DBTestCase - -class DummyPool(): - def run(self, f,*a,**k): - return f(*a,**k) +from ..test_helpers.utils import DummyPool class ModelVaidatorTest(DBTestCase): """tests for the model vaidators""" diff -r 830204e316ca -r 4007b5072c4a iro/tests/offer_integrated.py --- a/iro/tests/offer_integrated.py Sat Mar 24 00:02:42 2012 +0100 +++ b/iro/tests/offer_integrated.py Sat Mar 24 00:07:40 2012 +0100 @@ -15,33 +15,14 @@ from iro.offer import Smstrade, SMTP, Offer from iro.offer.smstrade import SmstradeException, StatusCode +from iro.error import NoRouteForTask from ..test_helpers.dbtestcase import DBTestCase - -class DummyPool(): - def run(self, f,*a,**k): - return f(*a,**k) +from ..test_helpers.utils import DummyPool def run( f,*a,**k): return f(*a,**k) -from twisted.python import log - -class DummyObserver(object): - def __init__(self): - self.e=[] - - def start(self): - log.addObserver(self.emit) - - def stop(self): - log.removeObserver(self.emit) - - def emit(self, eventDict): - self.e.append(eventDict) - - - class IntegratedOfferTests(DBTestCase): def setUp(self): DBTestCase.setUp(self) @@ -51,11 +32,7 @@ self.taskPool = taskPool.run taskPool.run = run - self.log = DummyObserver() - self.log.start() - def tearDown(self): - self.log.stop() exJobs.clear() data.pool = self.pool self.pool = None @@ -89,7 +66,7 @@ t = Task(Telnumber("0123456789"),j) yield t.start() - self.assertEqual(self.log.e[0]['message'], ("Job(%s) to '0049123456789' ended sucecessfully via bla:basic."%j.dbjob,)) + self.assertEqual(self.log.e[2]['message'], ("Job(%s) to '0049123456789' ended sucecessfully via bla:basic."%j.dbjob,)) with self.session() as session: u = session.merge(u) @@ -132,10 +109,13 @@ errors = self.flushLoggedErrors(SmstradeException) self.assertEqual(len(errors), 1) - self.assertEqual(self.log.e[0]['why'], "Error: Job(%s) to '0049123456789' failed."%j.dbjob) + errors = self.flushLoggedErrors(NoRouteForTask) + self.assertEqual(len(errors), 1) + self.assertEqual(self.log.e[1]['why'], "Job(%s): Send to '0049123456789' failed via 's'"%j.dbjob) + self.assertEqual(self.log.e[3]['why'], "Error: Job(%s) to '0049123456789' failed."%j.dbjob) self.assertEqual(t.error, True) - self.assertEqual(str(t.status.value),str(SmstradeException(StatusCode(703)))) + self.assertEqual(str(self.log.e[1]['failure'].value),str(SmstradeException(StatusCode(703)))) with self.session() as session: u = session.merge(u) @@ -166,7 +146,7 @@ t = Task("t@test.de",j) yield t.start() - self.assertEqual(self.log.e[0]['message'], ("Job(%s) to 't@test.de' ended sucecessfully via bla:None."%j.dbjob,)) + self.assertEqual(self.log.e[2]['message'], ("Job(%s) to 't@test.de' ended sucecessfully via bla:None."%j.dbjob,)) with self.session() as session: u = session.merge(u) @@ -199,12 +179,14 @@ t = Task("t@test.de",j) yield t.start() + errors = self.flushLoggedErrors(NoRouteForTask) + self.assertEqual(len(errors), 1) errors = self.flushLoggedErrors(IOError) self.assertEqual(len(errors), 1) - self.assertEqual(self.log.e[0]['why'], "Error: Job(%s) to 't@test.de' failed."%j.dbjob -) + self.assertEqual(self.log.e[1]['why'], "Job(%s): Send to 't@test.de' failed via 's'"%j.dbjob) + self.assertEqual(self.log.e[3]['why'], "Error: Job(%s) to 't@test.de' failed."%j.dbjob) self.assertEqual(t.error, True) - self.assertEqual(str(t.status.value),str(IOError(111,"Connection refused"))) + self.assertEqual(str(self.log.e[1]['failure'].value),str(IOError(111,"Connection refused"))) with self.session() as session: u = session.merge(u) diff -r 830204e316ca -r 4007b5072c4a iro/tests/pool.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/iro/tests/pool.py Sat Mar 24 00:07:40 2012 +0100 @@ -0,0 +1,21 @@ +from twisted.trial import unittest +from mock import Mock +import copy + +from iro.controller import pool + +class PoolTestCase(unittest.TestCase): + + def setUp(self): + self._pools = copy.copy(pool.pools) + + def tearDown(self): + del pool.pools[:] + pool.pools.extend(self._pools) + + def testStartPool(self): + del pool.pools[:] + pool.pools.extend([Mock(),Mock()]) + pool.startPool("blafo") + for i in pool.pools: + i.start.assert_called_with("blafo") diff -r 830204e316ca -r 4007b5072c4a iro/tests/task.py --- a/iro/tests/task.py Sat Mar 24 00:02:42 2012 +0100 +++ b/iro/tests/task.py Sat Mar 24 00:07:40 2012 +0100 @@ -113,6 +113,45 @@ d.addCallback(c) return d + def testChaining(self): + with self.session() as session: + u = User(name='test',apikey='abcdef123456789') + session.add(u) + o=DBOffer(name="test", provider="bla", route="basic", typ="sms") + u.rights.append(Userright(o)) + o=DBOffer(name="test2", provider="bla", route="basic2", typ="sms") + u.rights.append(Userright(o)) + + p=Provider(name="p", typs={"sms":["basic","basic2"]}) + def send(typ,route,recipient,message): + if route=="basic": + raise Exception("oh my god an exception") + return Status(p,route) + p.send=send + offers["test"] = Offer("test",provider=p, route="basic", typ="sms") + offers["test2"] = Offer("test2",provider=p, route="basic2", typ="sms") + + def c(exjob): + task = Task(Telnumber('123456789'), exjob) + task.d = Deferred() + task.d.addCallback(stat, task) + task._run() + return task.d + + def stat(status, task): + errors = self.flushLoggedErrors(Exception) + self.assertEqual(len(errors), 1) + self.assertEqual(self.log.e[1]['why'], "Job(%s): Send to '0049123456789' failed via 'test'"% task.job.dbjob) + self.assertIsInstance(status, Status) + self.assertEqual(status.provider, p) + self.assertEqual(status.route, "basic2") + + d = exJobs.create(u, [Telnumber('123456789')], SMS('test'), ['test','test2']) + d.addCallback(c) + return d + + + def testSetStatus(self): task=Task(Telnumber('123456789'), None) self.assertEqual(task.status,None) diff -r 830204e316ca -r 4007b5072c4a iro/tests/viewinterface.py --- a/iro/tests/viewinterface.py Sat Mar 24 00:02:42 2012 +0100 +++ b/iro/tests/viewinterface.py Sat Mar 24 00:07:40 2012 +0100 @@ -1,6 +1,7 @@ from twisted.internet.defer import inlineCallbacks from datetime import datetime from Queue import deque +from mock import patch from iro.model.schema import User, Offer, Userright, Job, Message from iro.controller.viewinterface import Interface @@ -14,10 +15,7 @@ import iro.error as IroError from ..test_helpers.dbtestcase import DBTestCase - -class DummyPool(): - def run(self, f,*a,**k): - return f(*a,**k) +from ..test_helpers.utils import DummyPool class ViewInterfaceTest(DBTestCase): """tests for the xmlrpc interface""" @@ -214,8 +212,10 @@ self.assertEqual(taskPool.pool.q.qsize(),1) + @patch("iro.model.message.formatdate") @inlineCallbacks - def testMail(self): + def testMail(self,mock_f): + mock_f.return_value="Wed, 21 Mar 2012 17:16:11 +0100" with self.session() as session: u = User(name='test',apikey='abcdef123456789') o = Offer(name='loc',provider="localhost",route="",typ="mail") @@ -231,8 +231,10 @@ self.assertEqual(exJob.message,Mail("sub",'hey body!','frm@t.de')) self.assertEqual(taskPool.pool.q.qsize(),1) + @patch("iro.model.message.formatdate") @inlineCallbacks - def testMailFrmNone(self): + def testMailFrmNone(self,mock_f): + mock_f.return_value="Wed, 21 Mar 2012 17:16:11 +0100" with self.session() as session: u = User(name='test',apikey='abcdef123456789') o = Offer(name='loc',provider="localhost",route="",typ="mail") diff -r 830204e316ca -r 4007b5072c4a iro/tests/xmlrpc_client.py --- a/iro/tests/xmlrpc_client.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -from multiprocessing.pool import ThreadPool -import xmlrpclib -import timeit - - -def x(i): - xmlrpclib.ServerProxy('http://192.168.56.101:7080/RPC2').status('abcdef123456789') - -pool=ThreadPool(50) - -print min(timeit.repeat(lambda:pool.map(x,range(51)),number=1,repeat=1)) - diff -r 830204e316ca -r 4007b5072c4a iro/worker.py --- a/iro/worker.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- -# Worker code - -from multiprocessing import Process -import logging -logger = logging.getLogger("iro.worker") - -class Worker(Process): - def __init__(self,queue): - Process.__init__(self) - self.queue=queue - - def run(self): - logger.info('Workerprocess läuft nun...') - indifier=0 - while 1: - job=self.queue.get() - if job is None: - break # reached end of queue - indifier+=1 - logger.info('ein neuer Job(%d)' %(indifier)) - try: - job.start(indifier) - logger.info('Job(%d) fertig ;)'%(indifier)) - except: - job.setStatus("error") - logger.exception('Job(%d) fehlgeschlagen :('%(indifier)) - diff -r 830204e316ca -r 4007b5072c4a iro/xmlrpc/AuthentificateXMLRPCServer.py --- a/iro/xmlrpc/AuthentificateXMLRPCServer.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -# 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() - - diff -r 830204e316ca -r 4007b5072c4a iro/xmlrpc/SecureAuthentificateXMLRPCServer.py --- a/iro/xmlrpc/SecureAuthentificateXMLRPCServer.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -# 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() - - diff -r 830204e316ca -r 4007b5072c4a iro/xmlrpc/SecureUserdbXMLRPCServer.py --- a/iro/xmlrpc/SecureUserdbXMLRPCServer.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -from SecureAuthentificateXMLRPCServer import SecureAuthentificateXMLRPCRequestHandler -from SecureXMLRPCServer import SecureXMLRPCServer -import os, hashlib - -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=hashlib.sha512() - 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(user["name"],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 diff -r 830204e316ca -r 4007b5072c4a iro/xmlrpc/SecureXMLRPCServer.py --- a/iro/xmlrpc/SecureXMLRPCServer.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -""" -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() - diff -r 830204e316ca -r 4007b5072c4a iro/xmlrpc/__init__.py --- a/iro/xmlrpc/__init__.py Sat Mar 24 00:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -from AuthentificateXMLRPCServer import AuthentificateXMLRPCRequestHandler -from SecureXMLRPCServer import SecureXMLRPCRequestHandler, SecureXMLRPCServer -from SecureAuthentificateXMLRPCServer import SecureAuthentificateXMLRPCRequestHandler -from SecureUserdbXMLRPCServer import SecureUserDBXMLRPCServer, UserDB