def sendSMS(self, number, text, masterKey, senderName): #Spedisco il messaggio: inizializzo il PreferenceManager #ed il CodingManager p = PreferenceManager.getInstance() cm = CodingManager.getInstance() #Se necessario, cerco il nome in rubrica #Inizializzo il sender e mando il messaggio senderName = senderName.title() if number.isdigit() == False: number = p.lookup(number) if Sender.getPlugins().has_key(senderName) == False: print "Sito "+senderName+" non riconosciuto." else: reg = {} s = Sender.getPlugins()[senderName] if s.requiresRegistration: try: for i in s.requiresRegistration: reg[i] = p.getAccount(senderName, i, masterKey) except PreferenceManagerError: for i in s.requiresRegistration: p.addAccount(i, cm.unicodeStdin( raw_input("Immetti il dato "+i+": ")), senderName, masterKey) for i in s.requiresRegistration: reg[i] = p.getAccount(senderName, i, masterKey) s.send(number, text, reg) print "Spedito!"
def sendSMS(self, number, text, senderName): #Spedisco il messaggio: inizializzo il PreferenceManager #ed il CodingManager p = PreferenceManager.getInstance() cm = CodingManager.getInstance() masterKey = None if p.isEncryptionEnabled(): keyValid = False while keyValid == False: masterKey = raw_input("Inserisci la Master Password:"******"Sito "+senderName+" non riconosciuto." else: reg = {} s = Sender.getPlugins()[senderName] if s.requiresRegistration: try: for i in s.requiresRegistration: reg[i] = p.getAccount(senderName, i, masterKey) except PreferenceManagerError: for i in s.requiresRegistration: p.addAccount(i, cm.unicodeStdin( raw_input("Immetti il dato "+i+": ")), senderName, masterKey) for i in s.requiresRegistration: reg[i] = p.getAccount(senderName, i, masterKey) s.sendOne(number, text, reg) print "Spedito!"
def sendSMS(self, number, text, masterKey, senderName): #Spedisco il messaggio: inizializzo il PreferenceManager #ed il CodingManager p = PreferenceManager.getInstance() cm = CodingManager.getInstance() #Se necessario, cerco il nome in rubrica #Inizializzo il sender e mando il messaggio senderName = senderName.title() if number.isdigit() == False: number = p.lookup(number) if Sender.getPlugins().has_key(senderName) == False: print "Sito " + senderName + " non riconosciuto." else: reg = {} s = Sender.getPlugins()[senderName] if s.requiresRegistration: try: for i in s.requiresRegistration: reg[i] = p.getAccount(senderName, i, masterKey) except PreferenceManagerError: for i in s.requiresRegistration: p.addAccount( i, cm.unicodeStdin( raw_input("Immetti il dato " + i + ": ")), senderName, masterKey) for i in s.requiresRegistration: reg[i] = p.getAccount(senderName, i, masterKey) s.send(number, text, reg) print "Spedito!"
def run(self): """Avvia questa interfaccia.""" exitCode = 0 try: p = PreferenceManager.getInstance() cm = CodingManager.getInstance() masterKey = None print "(Questo programma funziona anche dalla linea di comando, \ vedi LEGGIMI)" masterKey = None if p.isEncryptionEnabled(): keyValid = False while keyValid == False: masterKey = raw_input("Inserisci la Master Password:"******"Immetti il numero del destinatario e \ premi INVIO: ") number = cm.unicodeStdin(number) text = cm.unicodeStdin( raw_input("Immetti il testo e premi INVIO: ")) print "Siti disponibili per l'invio:" plugins = Sender.getPlugins().keys() for i in plugins: print i print "Immetti il nome del sito. Le maiuscole non fanno differenza." sender = raw_input("Premi solo INVIO per " + plugins[0] + ":") sender = cm.unicodeStdin(sender) if (sender == ""): sender = plugins[0] proxy = "" if p.isProxyEnabled(): print "Proxy attualmente configurato: " + p.getProxy() proxy = raw_input("(INVIO per confermare, \"no\" per " + "disabilitare o nuovo indirizzo:)") if proxy == "no": p.unsetProxy() elif proxy != "": p.setProxy(proxy) else: print "Immetti l'indirizzo e la porta del proxy:" proxy = raw_input( "(se non sai cosa sono o non li usi premi INVIO)") if proxy != "": p.setProxy(proxy) if p.isProxyEnabled() == True: os.environ["http_proxy"] = p.getProxy() self.sendSMS(number, text, masterKey, sender) except NotFoundError, e: print cm.encodeStdout(e.__str__()) exitCode = 1
def run(self): """Avvia questa interfaccia.""" exitCode = 0 try: p = PreferenceManager.getInstance() cm = CodingManager.getInstance() masterKey = None print "(Questo programma funziona anche dalla linea di comando, \ vedi LEGGIMI)" masterKey = None if p.isEncryptionEnabled(): keyValid = False while keyValid == False: masterKey = raw_input("Inserisci la Master Password:"******"Immetti il numero del destinatario e \ premi INVIO: ") number = cm.unicodeStdin(number) text = cm.unicodeStdin( raw_input("Immetti il testo e premi INVIO: ")) print "Siti disponibili per l'invio:" plugins = Sender.getPlugins().keys() for i in plugins: print i print "Immetti il nome del sito. Le maiuscole non fanno differenza." sender = raw_input("Premi solo INVIO per "+plugins[0]+":") sender = cm.unicodeStdin(sender) if (sender == ""): sender = plugins[0] proxy = "" if p.isProxyEnabled(): print "Proxy attualmente configurato: " + p.getProxy() proxy = raw_input("(INVIO per confermare, \"no\" per " + "disabilitare o nuovo indirizzo:)") if proxy == "no": p.unsetProxy() elif proxy != "": p.setProxy(proxy) else: print "Immetti l'indirizzo e la porta del proxy:" proxy = raw_input("(se non sai cosa sono o non li usi premi INVIO)") if proxy != "": p.setProxy(proxy) if p.isProxyEnabled() == True: os.environ["http_proxy"] = p.getProxy() self.sendSMS(number, text, masterKey, sender) except NotFoundError, e: print cm.encodeStdout(e.__str__()) exitCode = 1
class PreferenceManager(Singleton): """Gestisce username, password e rubrica dell'utente.""" c = CaseSensitiveConfigParser() """Gestore del file di configurazione.""" logFileName = 'logsms.txt' """ Info x logger """ configBaseFileName = "config.ini" """Path completo e nome del file di configurazione.""" configDirBaseName = ".ermesms" """Nome della cartella contenente i file di configurazione.""" configDirName = "" """Path completo della cartella con i file di configurazione.""" configFileName = "" """Path completo e nome del file di configurazione.""" cm = CodingManager.getInstance() """Gestore della codifica dei caratteri.""" paddingChar = "\n" """Carattere utilizzato per rendere la lunghezza dei valori crittati multipla di 8.""" version = "1.0" """Versione del programma""" def __init__(self): """Inizializza i campi di quest'oggetto.""" self.configDirName = os.path.join(self.getSaveDir(), self.configDirBaseName) self.configFileName = os.path.join(self.configDirName, self.configBaseFileName) self.c.read([self.configFileName]) def getVersion(self): """Ritorna la versione del programma.""" return self.version def getAccount(self, sender, chiave, key=None): """Legge la chiave dal file di configurazione e lo ritorna.""" if self.isEncryptionEnabled(): return self.getEncryptedField("login"+sender, "e"+chiave, key) else: return self.getField("login"+sender,chiave) def getLastUsed(self, key): """Ritorna un valore LRU.""" return self.getField("lastused", key) def getlogFileName(self): """Ritorna il percorso completo del file di log""" return os.path.join(self.getSaveDir(), self.configDirBaseName, self.logFileName) def getContactSender(self, key): """Ritorna il valore del sender associato al nome in rubrica""" return self.getField("ContactSender", key) def getSentSender(self, key): """Ritorna il numero di messaggi inviati oggi""" return self.getField("SentSender", key) def getSenderList(self): """Ritorna la lista dei sender utilizzati""" items = self.c.items("SenderList") senderList = [] for sender, state in items: if state == 'True': senderList.append(sender) return senderList def getContacts(self): """Ritorna un dizionario con tutti i contatti in rubrica.""" result = {} if self.c.has_section("contacts") == True: items = self.c.items("contacts") for name, number in items: name = self.cm.unQuoteUnicode(name) number = self.cm.unQuoteUnicode(number) result[name] = number return result def isLastUsedAvailable(self, key): """Ritorna True se esiste una chiave LRU.""" return self.hasField("lastused", key) def isEncryptionEnabled(self): """Ritorna true se le password sono crittate""" if self.hasField("encryption", "enabled"): return self.getField("encryption", "enabled") == "true" else: return False def isEncryptionSpecified(self): """Ritorna True se è specificato un qualche valore per la crittografia (abilitata o disabilitata).""" return self.hasField("encryption", "enabled") def isSentSenderAvailable(self, key): """Ritorna True se esiste il numero di messaggi inviati oggi.""" return self.hasField("SentSender", key) def isSenderListAvailable(self, senderList): """Ritorna la lista dei sender utilizzati""" esito = True for sender in senderList: if self.hasField('SenderList',sender) == False: esito = False if self.c.has_section('SenderList'): items = self.c.items("SenderList") for sender, i in items: if senderList.count(sender) != 1: esito = False if esito == False: self.c.remove_section('SenderList') return esito def isContactSenderAvailable(self, key): """Ritorna True se esiste una chiave LRU.""" return self.hasField("ContactSender", key) def checkSentSender(self): """Controlla che i dati siano aggiornati a oggi""" if self.isSentSenderAvailable('Reset'): lastreset = self.getSentSender('Reset') if time.strftime('%d/%m/%y') != lastreset: self.c.remove_section('SentSender') self.setSentSender('Reset',time.strftime('%d/%m/%y')) else: self.setSentSender('Reset',time.strftime('%d/%m/%y')) def logSMS(self, sender, dest, text): """Prepara il salvataggio dei dati""" if not os.path.isfile(self.getlogFileName()): if not os.path.isdir(self.configDirName): os.makedirs(self.configDirName) logfile = open(self.getlogFileName(), 'w+') else: logfile = open(self.getlogFileName(), 'a+') self.writeLogData(logfile, time.strftime('%y%m%d'), time.strftime('%X'), sender, dest, text) logfile.close() def writeLogData(self, logfile, data, ora, sender, dest, text):# '''Scrive i dati nel file di log''' logdata = 'data='+data+\ '\nora='+ora+\ '\nsender='+self.cm.quoteUnicode(sender)+\ '\ndest='+self.cm.quoteUnicode(dest)+\ '\ntext='+self.cm.quoteUnicode(text)+\ '\n---\n' logfile.write(logdata) def lookup(self, name): """Cerca un nome nella rubrica.""" try: return self.getField("contacts", name) except (NoSectionError, NoOptionError, PreferenceManagerError): raise NotFoundError(name) def lookupNumber(self, number): """Cerca un numero nella rubrica.""" number = self.cm.quoteUnicode(number) #Decisamente non il modo migliore, ma funziona. contacts = self.getContacts() inverseContacts = dict([[v, k] for k, v in contacts.items()]) try: return inverseContacts[number] except KeyError: if number[:3]=="+39": number = number[3:] else: number = "+39"+number try: return inverseContacts[number] except KeyError: raise NotFoundError(number) def isInContacts(self, name): """Ritorna True se un contatto è presente in rubrica.""" try: self.lookup(name) return True except NotFoundError: return False def isNumberInContacts(self, number): """Ritorna True se il numero di un contatto è presente in rubrica.""" try: self.lookupNumber(number) return True except NotFoundError: #ricerca alternativa if number[:3]=="+39": number = number[3:] else: number = "+39"+number try: self.lookupNumber(number) return True except NotFoundError: return False def isProxyEnabled(self): """Ritorna True se un proxy è configurato.""" return self.hasField("proxy", "url") def getProxy(self): """Ritorna l'url del proxy server per questo computer.""" return self.getField("proxy", "url") def addAccount(self, chiave, valore, sender, key=None): """Salva una chiave nel file di configurazione, opzionalmente crittato (se key è specificato e non è None).""" if self.isEncryptionEnabled(): self.setEncryptedField("login"+sender, "e"+chiave, valore, key) else: self.setField("login"+sender, chiave, valore) def clearAccount(self,sender): if self.c.has_section("login"+sender): self.c.remove_section("login"+sender) def clearContacts(self): if self.c.has_section("contacts"): self.c.remove_section("contacts") def enableEncryption(self, key): """Abilita la cifratura di nomi utenti e password e cifra quelli esistenti.""" for section in self.c.sections(): if section[:5]=="login": for option in self.c.options(section): value = self.getField(section,option) self.setEncryptedField(section, "e"+option, value, key) self.unsetField(section, option) self.setField("encryption", "enabled", "true") self.setField("encryption", "keyhash", self.cm.quoteBase64(hashlib.sha1(key).digest())) def checkEncryptionKey(self, key): """Ritorna True se la chiave passata corrisponde con la chiave utilizzata per la cifratura.""" keyHash1 = hashlib.sha1(key).digest() keyHash2 = self.cm.unQuoteBase64(self.getField("encryption", "keyhash")) return keyHash1 == keyHash2 def disableEncryption(self): """Disabilita la crittografia, eliminando ogni eventuale voce crittata.""" self.setField("encryption", "enabled", "false") for i in self.c.sections(): if i[:5]=="login": self.c.remove_section(i) def addContact(self, name, number): """Aggiunge un contatto alla rubrica.""" self.setField("contacts", name, number) def setLastUsed(self, key, value): """Setta una coppia chiave-valore LRU.""" self.setField("lastused", key, value) def setProxy(self, url): """Setta il proxy server per questo computer.""" self.setField("proxy", "url", url) def setSenderList(self, senderList, totalSender): """Ritorna la lista dei sender utilizzati""" for sender in totalSender: if senderList.count(sender) == 1: self.setField("SenderList", sender, 'True') else: self.setField("SenderList", sender, 'False') def setContactSender(self, key, value): """Associa a un utente in rubrica in sender.""" self.setField("ContactSender", key, value) def setSentSender(self, key, value): """Associa a un utente in rubrica in sender.""" self.setField("SentSender", key, value) def unsetProxy(self): """Rimuovi il proxy server per questo computer.""" self.unsetField("proxy", "url") def deleteContact(self, name): """Toglie un contatto dalla rubrica.""" self.unsetField("contacts", name) if self.isContactSenderAvailable(name) : self.unsetField("ContactSender",name) def clear(self): """Azzera la configurazione.""" self.c = ConfigParser() def getConfigFileName(self): """Ritorna il path completo del file di configurazione.""" return self.configFileName #metodi privati def getField(self, section, key): """Ritorna il valore corrispondente a key nella sezione section.""" try: section = self.cm.quoteUnicode(section) key = self.cm.quoteUnicode(key) result = self.c.get(section, key) result = self.cm.unQuoteUnicode(result) except (NoSectionError, NoOptionError): raise PreferenceManagerError(u"Non trovo la chiave: " + key + u" nella sezione: "+ section) return result def setField(self, section, key, value): """Setta una coppia chiave-valore corrispondente nella sezione section.""" if key == "": raise PreferenceManagerError(u"Specificare un valore.") section = self.cm.quoteUnicode(section) key = self.cm.quoteUnicode(key) value = self.cm.quoteUnicode(value) if not self.c.has_section(section): self.c.add_section(section) self.c.set(section, key, value) def unsetField(self, section, key): """Rimuove una coppia chiave-valore dalla sezione section.""" section = self.cm.quoteUnicode(section) key = self.cm.quoteUnicode(key) if self.c.has_section(section): if self.c.has_option(section, key): self.c.remove_option(section, key) if len(self.c.items(section))==0: self.c.remove_section(section) def hasField(self, section, key): """Ritorna True se la sezione ha la chiave specificata.""" section = self.cm.quoteUnicode(section) key = self.cm.quoteUnicode(key) return self.c.has_section(section) and \ self.c.has_option(section, key) def getEncryptedField(self, section, key, encryptionKey): """Ritorna il valore corrispondente a key nella sezione section, decrittandolo con la chiave encryptionKey.""" r = rijndael(hashlib.md5(encryptionKey).digest()) encryptedValue = self.cm.unQuoteBase64(self.getField(section, key)) cleartextValue = "" for i in range(len(encryptedValue)/16): cleartextValue += r.decrypt(encryptedValue[i*16:(i+1)*16]) #Rimuovo il padding while cleartextValue[-1] == self.paddingChar: cleartextValue = cleartextValue[:-1] return cleartextValue def setEncryptedField(self, section, key, value, encryptionKey): """Setta una coppia chiave-valore corrispondente nella sezione section crittando key con la chiave encryptionKey.""" r = rijndael(hashlib.md5(encryptionKey).digest()) paddedValue = value + (16 - (len(value) % 16)) * self.paddingChar encryptedValue = "" for i in range(len(paddedValue)/16): encryptedValue += r.encrypt(paddedValue[i*16:(i+1)*16]) encryptedValue = self.cm.quoteBase64(encryptedValue) self.setField(section, key, encryptedValue) def getSaveDir(self): """Ritorna la directory in cui salvare il file di configurazione.""" if "portable" not in self.version: #Caso normale: cerco la home dell'utente try: if os.path.exists(os.environ["USERPROFILE"]): return os.environ["USERPROFILE"] except Exception: pass try: if os.path.exists(os.path.expanduser("~")): return os.path.expanduser("~") except Exception: pass try: if os.path.exists(os.environ["HOME"]): return os.environ["HOME"] except Exception: pass return os.getcwd() else: #Versione "portable": salvo nella directory del programma return os.getcwd() def writeConfigFile(self): """Salva su file le impostazioni.""" # se occorre, crea la directory if os.path.isdir(self.configDirName) == False: os.makedirs(self.configDirName) self.c.write(file(self.configFileName,"w"))
def showFatalException(self, message): """Questo metodo viene richiamato nel caso in cui venga catturata un'eccezione non gestita nel programma principale.""" sys.stdout.write('\a')#Beep sys.stdout.flush() print CodingManager.getInstance().encodeStdout(message)
def run(self): """Avvia questa interfaccia.""" na = len(sys.argv) - 1 exitCode = 0 p = PreferenceManager.getInstance() cm = CodingManager.getInstance() try: if (na == 1): #Un solo argomento, lista rubrica o help arg1 = cm.unicodeArgv(sys.argv[1]) if (arg1 == "-m" or arg1 == "--mostra"): for name, number in p.getContacts().iteritems(): print cm.encodeStdout(name)+": "+cm.encodeStdout(number) else: HelpUI.getInstance().run() elif (na == 2): #Due argomenti, numero e testo arg1 = cm.unicodeArgv(sys.argv[1]) arg2 = cm.unicodeArgv(sys.argv[2]) self.sendSMS(arg1, arg2, Sender.getPlugins().keys()[0]) elif (na == 3): #Tre argomenti. Tre casi: "-a nome numero" #oppure "numero testo sender" arg1 = cm.unicodeArgv(sys.argv[1]) arg2 = cm.unicodeArgv(sys.argv[2]) arg3 = cm.unicodeArgv(sys.argv[3]) if (arg1 == "-a" or arg1 == "--add"): p.addContact(arg2, arg3) print "Aggiunto!" else: if p.isProxyEnabled() == True: os.environ["http_proxy"] = p.getProxy() self.sendSMS(arg1, arg2, arg3) elif (na == 4): #numero testo -p proxy arg1 = cm.unicodeArgv(sys.argv[1]) arg2 = cm.unicodeArgv(sys.argv[2]) arg3 = cm.unicodeArgv(sys.argv[3]) arg4 = cm.unicodeArgv(sys.argv[4]) if (arg3=="-p" or arg3=="--proxy"): if arg4 != "no": p.setProxy(arg4) else: p.unsetProxy() if p.isProxyEnabled() == True: os.environ["http_proxy"] = p.getProxy() self.sendSMS(arg1, arg2, Sender.getPlugins().keys()[0]) else: HelpUI.getInstance().run() elif (na == 5): #numero testo sender -p proxy arg1 = cm.unicodeArgv(sys.argv[1]) arg2 = cm.unicodeArgv(sys.argv[2]) arg3 = cm.unicodeArgv(sys.argv[3]) arg4 = cm.unicodeArgv(sys.argv[4]) arg5 = cm.unicodeArgv(sys.argv[5]) if (arg4=="-p" or arg4=="--proxy"): if arg5 != "no": p.setProxy(arg5) else: p.unsetProxy() if p.isProxyEnabled() == True: os.environ["http_proxy"] = p.getProxy() self.sendSMS(arg1, arg2, arg3) else: HelpUI.getInstance().run() else: HelpUI.getInstance().run() except NotFoundError, e: print cm.encodeStdout(e.__str__()) exitCode = 1
def showFatalException(self, message): """Questo metodo viene richiamato nel caso in cui venga catturata un'eccezione non gestita nel programma principale.""" sys.stdout.write('\a') #Beep sys.stdout.flush() print CodingManager.getInstance().encodeStdout(message)