Volatile password
- implementation with not persistent password storage. Password is asked to the user for each new jabber connection (offline -> available status) darcs-hash:20060131214141-86b55-e595b06a2c1f9a8315189a69b79b094da1e24c1e.gz
This commit is contained in:
@@ -113,6 +113,11 @@ class MailComponent(Component):
|
||||
label = lang_class.account_password, \
|
||||
var = "password")
|
||||
|
||||
reg_form.add_field(type = "boolean", \
|
||||
label = lang_class.account_password_store, \
|
||||
var = "store_password",
|
||||
value = "True")
|
||||
|
||||
reg_form.add_field(type = "text-single", \
|
||||
label = lang_class.account_host, \
|
||||
var = "host")
|
||||
@@ -239,6 +244,11 @@ class MailComponent(Component):
|
||||
var = "password", \
|
||||
value = account.password)
|
||||
|
||||
reg_form_init.add_field(type = "boolean", \
|
||||
label = lang_class.account_password_store, \
|
||||
var = "store_password", \
|
||||
value = str(account.store_password).lower())
|
||||
|
||||
reg_form_init.add_field(type = "text-single", \
|
||||
label = lang_class.account_host, \
|
||||
var = "host", \
|
||||
@@ -551,6 +561,9 @@ class MailComponent(Component):
|
||||
else:
|
||||
password = u""
|
||||
|
||||
store_password = x.fields.has_key("store_password") \
|
||||
and (x.fields["store_password"].value == "1")
|
||||
|
||||
if x.fields.has_key("host"):
|
||||
host = x.fields["host"].value
|
||||
else:
|
||||
@@ -606,8 +619,8 @@ class MailComponent(Component):
|
||||
else:
|
||||
interval = None
|
||||
|
||||
self.__logger.debug(u"New Account: %s, %s, %s, %s, %s, %s, %s %i %i %i %i %i %i %i" \
|
||||
% (name, login, password, host, str(port), \
|
||||
self.__logger.debug(u"New Account: %s, %s, %s, %s, %s, %s, %s, %s %i %i %i %i %i %i %i" \
|
||||
% (name, login, password, str(store_password), host, str(port), \
|
||||
mailbox, type, chat_action, online_action, away_action, \
|
||||
xa_action, dnd_action, offline_action, interval))
|
||||
|
||||
@@ -645,6 +658,7 @@ class MailComponent(Component):
|
||||
mailconnection_factory.get_new_mail_connection(type)
|
||||
account.login = login
|
||||
account.password = password
|
||||
account.store_password = store_password
|
||||
account.host = host
|
||||
account.chat_action = chat_action
|
||||
account.online_action = online_action
|
||||
@@ -667,6 +681,7 @@ class MailComponent(Component):
|
||||
self.__logger.debug("PRESENCE_AVAILABLE")
|
||||
from_jid = stanza.get_from()
|
||||
base_from_jid = unicode(from_jid.bare())
|
||||
lang_class = self.get_lang_class(self.get_lang(stanza.get_node()))
|
||||
name = stanza.get_to().node
|
||||
show = stanza.get_show()
|
||||
self.__logger.debug("SHOW : " + str(show))
|
||||
@@ -683,6 +698,8 @@ class MailComponent(Component):
|
||||
self.stream.send(p)
|
||||
elif self.__storage.has_key((base_from_jid, name)):
|
||||
account = self.__storage[(base_from_jid, name)]
|
||||
account.default_lang_class = lang_class
|
||||
old_status = account.status
|
||||
# Make available to receive mail only when online
|
||||
if show is None:
|
||||
account.status = "online" # TODO get real status = (not show)
|
||||
@@ -695,8 +712,23 @@ class MailComponent(Component):
|
||||
show = show, \
|
||||
stanza_type = "available")
|
||||
self.stream.send(p)
|
||||
if account.store_password == False \
|
||||
and old_status == "offline":
|
||||
self.__ask_password(name, from_jid, lang_class, account)
|
||||
return 1
|
||||
|
||||
def __ask_password(self, name, from_jid, lang_class, account):
|
||||
if not account.waiting_password_reply \
|
||||
and account.status != "offline":
|
||||
account.waiting_password_reply = True
|
||||
msg = Message(from_jid = name + "@" + unicode(self.jid), \
|
||||
to_jid = from_jid, \
|
||||
stanza_type = "message", \
|
||||
subject = u"[PASSWORD] " + lang_class.ask_password_subject, \
|
||||
body = lang_class.ask_password_body % \
|
||||
(account.host, account.login))
|
||||
self.stream.send(msg)
|
||||
|
||||
""" handle presence unavailability """
|
||||
def presence_unavailable(self, stanza):
|
||||
self.__logger.debug("PRESENCE_UNAVAILABLE")
|
||||
@@ -704,7 +736,12 @@ class MailComponent(Component):
|
||||
base_from_jid = unicode(from_jid.bare())
|
||||
if stanza.get_to() == unicode(self.jid):
|
||||
for jid, name in self.__storage.keys():
|
||||
self.__storage[(base_from_jid, name)].status = "offline"
|
||||
account = self.__storage[(base_from_jid, name)]
|
||||
account.status = "offline"
|
||||
account.waiting_password_reply = False
|
||||
if account.store_password == False:
|
||||
self.__logger.debug("Forgetting password")
|
||||
account.password = None
|
||||
p = Presence(from_jid = name + "@" + unicode(self.jid), \
|
||||
to_jid = from_jid, \
|
||||
stanza_type = "unavailable")
|
||||
@@ -764,28 +801,29 @@ class MailComponent(Component):
|
||||
""" Handle new message """
|
||||
def message(self, message):
|
||||
self.__logger.debug("MESSAGE: " + message.get_body())
|
||||
lang_class = self.get_lang_class(self.get_lang(message.get_node()))
|
||||
name = message.get_to().node
|
||||
base_from_jid = unicode(message.get_from().bare())
|
||||
# if name and self.__registered.has_key(base_from_jid):
|
||||
# body = message.get_body()
|
||||
# cmd = body.split(' ')
|
||||
# if cmd[0] == "check":
|
||||
# self.check_mail(base_from_jid, name)
|
||||
# elif cmd[0] == "dump":
|
||||
# body = ""
|
||||
# for jid in self.__registered.keys():
|
||||
# for name in self.__registered[jid].keys():
|
||||
# body += name + " for user " + jid
|
||||
# msg = Message(from_jid = self.jid, to_jid = base_from_jid, \
|
||||
# stanza_type = "message", \
|
||||
# body = body)
|
||||
# self.stream.send(msg)
|
||||
if re.compile("\[PASSWORD\]").search(message.get_subject()) is not None \
|
||||
and self.__storage.has_key((base_from_jid, name)):
|
||||
account = self.__storage[(base_from_jid, name)]
|
||||
account.password = message.get_body()
|
||||
account.waiting_password_reply = False
|
||||
msg = Message(from_jid = name + "@" + unicode(self.jid), \
|
||||
to_jid = message.get_from(), \
|
||||
stanza_type = "message", \
|
||||
subject = lang_class.password_saved_for_session, \
|
||||
body = lang_class.password_saved_for_session)
|
||||
self.stream.send(msg)
|
||||
return 1
|
||||
|
||||
""" Check mail account """
|
||||
def check_mail(self, jid, name):
|
||||
self.__logger.debug("CHECK_MAIL " + unicode(jid) + " " + name)
|
||||
account = self.__storage[(jid, name)]
|
||||
if account.password is None:
|
||||
self.__ask_password(name, jid, account.default_lang_class, account)
|
||||
return
|
||||
action = account.action
|
||||
if action != mailconnection.DO_NOTHING:
|
||||
try:
|
||||
|
||||
@@ -29,6 +29,7 @@ class Lang:
|
||||
account_name = u"Connection name"
|
||||
account_login = u"Login"
|
||||
account_password = u"Password"
|
||||
account_password_store = u"Store password on jabber server ?"
|
||||
account_host = u"Host"
|
||||
account_port = u"Port"
|
||||
account_type = u"Mail serveur type"
|
||||
@@ -45,11 +46,19 @@ class Lang:
|
||||
action_digest = u"Send mail digest"
|
||||
update_title = u"Jabber mail connection update"
|
||||
update_instructions = u"Modifying connection '%s'"
|
||||
connection_labels = u"%s connection '%s'"
|
||||
connection_label = u"%s connection '%s'"
|
||||
update_account_message = u"Updated %s connection '%s': Registered with "\
|
||||
"username '%s' and password '%s' on '%s'"
|
||||
new_account_message = u"New %s connection '%s': Registered with " \
|
||||
"username '%s' and password '%s' on '%s'"
|
||||
ask_password_subject = u"Password request"
|
||||
ask_password_body = u"Reply to this message with the password " \
|
||||
"for the following account : \n" \
|
||||
"\thost = %s\n" \
|
||||
"\tlogin = %s\n"
|
||||
password_saved_for_session = u"Password will be kept during your jabber session"
|
||||
check_error_subject = u"Error while checking emails."
|
||||
check_error_body = u"An error appears while checking emails :\n\t%s"
|
||||
|
||||
class fr:
|
||||
register_title = u"Enregistrement d'une nouvelle connexion à un serveur email."
|
||||
@@ -57,6 +66,7 @@ class Lang:
|
||||
account_name = u"Nom de la connexion"
|
||||
account_login = u"Nom d'utilisateur"
|
||||
account_password = u"Mot de passe"
|
||||
account_password_store = u"Sauvegarder le mot de passe sur le serveur Jabber ?"
|
||||
account_host = u"Adresse du serveur email"
|
||||
account_port = u"Port du serveur email"
|
||||
account_type = u"Type du serveur email"
|
||||
@@ -78,5 +88,14 @@ class Lang:
|
||||
"Nom d'utilisateur : '%s'\nMot de passe : '%s'\nsur : '%s'"
|
||||
new_account_message = u"La connexion %s '%s' a été créée : \n" \
|
||||
"Nom d'utilisateur : '%s'\nMot de passe : '%s'\nsur : '%s'"
|
||||
|
||||
ask_password_subject = u"Demande de mot de passe"
|
||||
ask_password_body = u"Répondre à ce message avec le mot de passe du " \
|
||||
"compte suivant : \n" \
|
||||
"\thost = %s\n" \
|
||||
"\tlogin = %s\n"
|
||||
password_saved_for_session = u"Le mot de passe sera garder tout au " \
|
||||
"long de la session Jabber."
|
||||
check_error_subject = u"Erreur lors de la vérification des emails."
|
||||
check_error_body = u"Une erreur est survenue lors de la vérification " \
|
||||
"des emails :\n\t%s"
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ import poplib
|
||||
import imaplib
|
||||
import socket
|
||||
|
||||
from jabber.lang import Lang
|
||||
|
||||
IMAP4_TIMEOUT = 10
|
||||
POP3_TIMEOUT = 10
|
||||
|
||||
@@ -145,6 +147,7 @@ class MailConnection(object):
|
||||
- 'ssl': boolean"""
|
||||
self.login = login
|
||||
self.password = password
|
||||
self.store_password = True
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.ssl = ssl
|
||||
@@ -159,11 +162,15 @@ class MailConnection(object):
|
||||
self.offline_action = DO_NOTHING
|
||||
self.interval = 5
|
||||
self.lastcheck = 0
|
||||
self.default_lang_class = Lang.en
|
||||
self.waiting_password_reply = False
|
||||
self.in_error = False
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.get_type() == other.get_type() \
|
||||
and self.login == other.login \
|
||||
and self.password == other.password \
|
||||
and self.store_password == other.store_password \
|
||||
and self.host == other.host \
|
||||
and self.port == other.port \
|
||||
and self.ssl == other.ssl \
|
||||
@@ -176,7 +183,8 @@ class MailConnection(object):
|
||||
and self.interval == other.interval
|
||||
|
||||
def __str__(self):
|
||||
return self.get_type() + "#" + self.login + "#" + self.password + "#" \
|
||||
return self.get_type() + "#" + self.login + "#" + \
|
||||
(self.store_password and self.password or "/\\") + "#" \
|
||||
+ self.host + "#" + str(self.port) + "#" + str(self.chat_action) + "#" \
|
||||
+ str(self.online_action) + "#" + str(self.away_action) + "#" + \
|
||||
str(self.xa_action) + "#" + str(self.dnd_action) + "#" + str(self.offline_action) + "#" + str(self.interval)
|
||||
|
||||
@@ -61,6 +61,11 @@ def str_to_mail_connection(connection_string):
|
||||
type = arg_list.pop()
|
||||
login = arg_list.pop()
|
||||
password = arg_list.pop()
|
||||
if password == "/\\":
|
||||
password = None
|
||||
store_password = False
|
||||
else:
|
||||
store_password = True
|
||||
host = arg_list.pop()
|
||||
port = int(arg_list.pop())
|
||||
chat_action = None
|
||||
@@ -116,6 +121,7 @@ def str_to_mail_connection(connection_string):
|
||||
ssl = (len(type) == 5))
|
||||
if result is None:
|
||||
raise Exception, "Connection type \"" + type + "\" unknown"
|
||||
result.store_password = store_password
|
||||
result.chat_action = chat_action
|
||||
result.online_action = online_action
|
||||
result.away_action = away_action
|
||||
|
||||
@@ -45,23 +45,23 @@ class Storage(UserDict):
|
||||
self._registered = self.load()
|
||||
|
||||
def __setitem__(self, pk_tuple, obj):
|
||||
# print "Adding " + "#".join(pk_tuple) + " = " + str(obj)
|
||||
self._registered[str("#".join(pk_tuple))] = obj
|
||||
# print "Adding " + "#".join(map(str, pk_tuple)) + " = " + str(obj)
|
||||
self._registered[str("#".join(map(str, pk_tuple)))] = obj
|
||||
|
||||
def __getitem__(self, pk_tuple):
|
||||
# print "Getting " + "#".join(pk_tuple)
|
||||
# print "Getting " + "#".join(map(str, pk_tuple))
|
||||
if len(pk_tuple) == self.nb_pk_fields:
|
||||
return self._registered[str("#".join(pk_tuple))]
|
||||
return self._registered[str("#".join(map(str, pk_tuple)))]
|
||||
else:
|
||||
partial_key = str("#".join(pk_tuple))
|
||||
partial_key = str("#".join(map(str, pk_tuple)))
|
||||
regexp = re.compile(partial_key)
|
||||
return [self._registered[key]
|
||||
for key in self._registered.keys()
|
||||
if regexp.search(key)]
|
||||
|
||||
def __delitem__(self, pk_tuple):
|
||||
# print "Deleting " + "#".join(pk_tuple)
|
||||
del self._registered[str("#".join(pk_tuple))]
|
||||
# print "Deleting " + "#".join(map(str, pk_tuple))
|
||||
del self._registered[str("#".join(map(str, pk_tuple)))]
|
||||
|
||||
def get_spool_dir(self):
|
||||
return self._spool_dir
|
||||
@@ -75,9 +75,9 @@ class Storage(UserDict):
|
||||
|
||||
def has_key(self, pk_tuple):
|
||||
if len(pk_tuple) == self.nb_pk_fields:
|
||||
return self._registered.has_key(str("#".join(pk_tuple)))
|
||||
return self._registered.has_key(str("#".join(map(str, pk_tuple))))
|
||||
else:
|
||||
partial_key = str("#".join(pk_tuple))
|
||||
partial_key = str("#".join(map(str, pk_tuple)))
|
||||
regexp = re.compile("^" + partial_key)
|
||||
for key in self._registered.keys():
|
||||
if regexp.search(key):
|
||||
@@ -89,7 +89,7 @@ class Storage(UserDict):
|
||||
return [tuple(key.split("#")) for key in self._registered.keys()]
|
||||
else:
|
||||
level = len(pk_tuple)
|
||||
partial_key = str("#".join(pk_tuple))
|
||||
partial_key = str("#".join(map(str, pk_tuple)))
|
||||
regexp = re.compile("^" + partial_key)
|
||||
result = {}
|
||||
for key in self._registered.keys():
|
||||
@@ -101,6 +101,8 @@ class Storage(UserDict):
|
||||
for pk in self._registered.keys():
|
||||
print pk + " = " + str(self._registered[pk])
|
||||
|
||||
def load(self):
|
||||
pass
|
||||
|
||||
class DBMStorage(Storage):
|
||||
def __init__(self, nb_pk_fields = 1, spool_dir = ".", db_file = None):
|
||||
@@ -112,7 +114,6 @@ class DBMStorage(Storage):
|
||||
self.sync()
|
||||
|
||||
def load(self):
|
||||
# print "DBM LOAD"
|
||||
str_registered = anydbm.open(self.file, \
|
||||
'c')
|
||||
result = {}
|
||||
|
||||
15
run_test.py
15
run_test.py
@@ -61,12 +61,21 @@ if __name__ == '__main__':
|
||||
pop3_connection_suite, \
|
||||
imap_connection_suite, \
|
||||
mc_factory_suite, \
|
||||
component_suite, \
|
||||
component2_suite, \
|
||||
# component_suite, \
|
||||
# component2_suite, \
|
||||
storage_suite, \
|
||||
dbmstorage_suite, \
|
||||
sqlitestorage_suite))
|
||||
test_support.run_suite(sqlitestorage_suite)
|
||||
# test_support.run_suite(mail_connection_suite)
|
||||
# test_support.run_suite(pop3_connection_suite)
|
||||
# test_support.run_suite(imap_connection_suite)
|
||||
# test_support.run_suite(mc_factory_suite)
|
||||
# test_support.run_suite(component_suite)
|
||||
# test_support.run_suite(component2_suite)
|
||||
# test_support.run_suite(storage_suite)
|
||||
# test_support.run_suite(sqlitestorage_suite)
|
||||
# test_support.run_suite(dbmstorage_suite)
|
||||
test_support.run_suite(jmc_suite)
|
||||
|
||||
# coverage.stop()
|
||||
# coverage.analysis(jabber.mailconnection_factory)
|
||||
|
||||
@@ -27,6 +27,7 @@ from jabber import mailconnection
|
||||
class MailConnectionFactory_TestCase(unittest.TestCase):
|
||||
def test_new_mail_connection_imap(self):
|
||||
mc = get_new_mail_connection("imap")
|
||||
# TODO
|
||||
self.assertEquals(mc, mc)
|
||||
|
||||
def test_new_mail_connection_imaps(self):
|
||||
@@ -46,6 +47,7 @@ class MailConnectionFactory_TestCase(unittest.TestCase):
|
||||
self.assertEquals(mc.get_type(), "imap")
|
||||
self.assertEquals(mc.login, "login")
|
||||
self.assertEquals(mc.password, "passwd")
|
||||
self.assertEquals(mc.store_password, True)
|
||||
self.assertEquals(mc.host, "host")
|
||||
self.assertEquals(mc.port, 193)
|
||||
self.assertEquals(mc.mailbox, "INBOX")
|
||||
@@ -62,6 +64,7 @@ class MailConnectionFactory_TestCase(unittest.TestCase):
|
||||
self.assertEquals(mc.get_type(), "pop3")
|
||||
self.assertEquals(mc.login, "login")
|
||||
self.assertEquals(mc.password, "passwd")
|
||||
self.assertEquals(mc.store_password, True)
|
||||
self.assertEquals(mc.host, "host")
|
||||
self.assertEquals(mc.port, 110)
|
||||
self.assertEquals(mc.chat_action, mailconnection.DIGEST)
|
||||
@@ -88,6 +91,23 @@ class MailConnectionFactory_TestCase(unittest.TestCase):
|
||||
self.assertEquals(mc.offline_action, mailconnection.RETRIEVE)
|
||||
self.assertEquals(mc.interval, 4)
|
||||
|
||||
def test_str_to_mail_connection_no_password(self):
|
||||
mc = str_to_mail_connection("imap#login#/\\#host#193#0#0#0#1#1#2#4#INBOX")
|
||||
self.assertEquals(mc.get_type(), "imap")
|
||||
self.assertEquals(mc.login, "login")
|
||||
self.assertEquals(mc.password, None)
|
||||
self.assertEquals(mc.store_password, False)
|
||||
self.assertEquals(mc.host, "host")
|
||||
self.assertEquals(mc.port, 193)
|
||||
self.assertEquals(mc.mailbox, "INBOX")
|
||||
self.assertEquals(mc.chat_action, mailconnection.DO_NOTHING)
|
||||
self.assertEquals(mc.online_action, mailconnection.DO_NOTHING)
|
||||
self.assertEquals(mc.away_action, mailconnection.DO_NOTHING)
|
||||
self.assertEquals(mc.xa_action, mailconnection.DIGEST)
|
||||
self.assertEquals(mc.dnd_action, mailconnection.DIGEST)
|
||||
self.assertEquals(mc.offline_action, mailconnection.RETRIEVE)
|
||||
self.assertEquals(mc.interval, 4)
|
||||
|
||||
def test_str_to_mail_connection_imaps(self):
|
||||
mc = str_to_mail_connection("imaps#login#passwd#host#993#0#0#0#1#1#2#4#INBOX.SubDir")
|
||||
self.assertEquals(mc.get_type(), "imaps")
|
||||
|
||||
Reference in New Issue
Block a user