new account registration wizard that follow XEP 77 better. fixes #2700 too (advanced options available while creation an account)

This commit is contained in:
Yann Leboulanger 2007-05-31 21:49:49 +00:00
parent b11ad2e5ac
commit 0e3c634ff2
5 changed files with 1078 additions and 1361 deletions

File diff suppressed because it is too large Load diff

View file

@ -206,30 +206,15 @@ class Connection(ConnectionHandlers):
# it's a new account # it's a new account
if not data[1]: # wrong answer if not data[1]: # wrong answer
self.dispatch('ACC_NOT_OK', ( self.dispatch('ACC_NOT_OK', (
_('Transport %s answered wrongly to register request: %s')\ _('Server %s answered wrongly to register request: %s')\
% (data[0], data[3]))) % (data[0], data[3])))
return return
req = data[1].asDict() is_form = data[2]
req['username'] = self.new_account_info['name'] if is_form:
req['password'] = self.new_account_info['password'] conf = data[1]
def _on_register_result(result): else:
if not common.xmpp.isResultNode(result): conf = data[1].asDict()
self.dispatch('ACC_NOT_OK', (result.getError())) self.dispatch('NEW_ACC_CONNECTED', (conf, is_form))
return
self.password = self.new_account_info['password']
if USE_GPG:
self.gpg = GnuPG.GnuPG(gajim.config.get('use_gpg_agent'))
gajim.config.set('usegpg', True)
else:
gajim.config.set('usegpg', False)
gajim.connections[self.name] = self
self.dispatch('ACC_OK', (self.new_account_info))
self.new_account_info = None
if self.connection:
self.connection.UnregisterDisconnectHandler(self._on_new_account)
self.disconnect(on_purpose=True)
common.xmpp.features_nb.register(self.connection, data[0],
req, _on_register_result)
return return
if not data[1]: # wrong answer if not data[1]: # wrong answer
self.dispatch('ERROR', (_('Invalid answer'), self.dispatch('ERROR', (_('Invalid answer'),
@ -1014,12 +999,46 @@ class Connection(ConnectionHandlers):
self.connection.getRoster().setItem(jid = jid, name = name, self.connection.getRoster().setItem(jid = jid, name = name,
groups = groups) groups = groups)
def send_new_account_infos(self, form, is_form):
def _on_register_result(result):
if not common.xmpp.isResultNode(result):
self.dispatch('ACC_NOT_OK', (result.getError()))
return
if USE_GPG:
self.gpg = GnuPG.GnuPG(gajim.config.get('use_gpg_agent'))
gajim.config.set('usegpg', True)
else:
gajim.config.set('usegpg', False)
gajim.connections[self.name] = self
self.dispatch('ACC_OK', (self.new_account_info))
self.new_account_info = None
if self.connection:
self.connection.UnregisterDisconnectHandler(self._on_new_account)
self.disconnect(on_purpose=True)
if is_form:
# Get username and password and put them in new_account_info
for field in self._data_form.iter_fields():
if field.var == 'username':
self.new_account_info['name'] = field.value
if field.var == 'password':
self.new_account_info['password'] = field.value
iq=Iq('set', NS_REGISTER, to = self._hostname)
iq.setTag('query').addChild(node = form)
self.connection.SendAndCallForResponse(iq, _on_register_result)
else:
# Get username and password and put them in new_account_info
if form.has_key('username'):
self.new_account_info['name'] = form['username']
if form.has_key('password'):
self.new_account_info['password'] = form['password']
common.xmpp.features_nb.register(self.connection, self._hostname,
form, _on_register_result)
def new_account(self, name, config, sync = False): def new_account(self, name, config, sync = False):
# If a connection already exist we cannot create a new account # If a connection already exist we cannot create a new account
if self.connection: if self.connection:
return return
self._hostname = config['hostname'] self._hostname = config['hostname']
self.server_resource = config['resource']
self.new_account_info = config self.new_account_info = config
self.name = name self.name = name
self.on_connect_success = self._on_new_account self.on_connect_success = self._on_new_account
@ -1028,13 +1047,11 @@ class Connection(ConnectionHandlers):
def _on_new_account(self, con = None, con_type = None): def _on_new_account(self, con = None, con_type = None):
if not con_type: if not con_type:
self.dispatch('ACC_NOT_OK', self.dispatch('NEW_ACC_NOT_CONNECTED',
(_('Could not connect to "%s"') % self._hostname)) (_('Could not connect to "%s"') % self._hostname))
return return
self.on_connect_failure = None self.on_connect_failure = None
self.connection = con self.connection = con
#if con:
# con.RegisterDisconnectHandler(self._on_new_account)
common.xmpp.features_nb.getRegInfo(con, self._hostname) common.xmpp.features_nb.getRegInfo(con, self._hostname)
def account_changed(self, new_name): def account_changed(self, new_name):

View file

@ -143,7 +143,6 @@ def _ReceivedRegInfo(con, resp, agent):
def register(disp, host, info, cb): def register(disp, host, info, cb):
""" Perform registration on remote server with provided info. """ Perform registration on remote server with provided info.
disp must be connected dispatcher instance. disp must be connected dispatcher instance.
Returns true or false depending on registration result.
If registration fails you can get additional info from the dispatcher's owner If registration fails you can get additional info from the dispatcher's owner
attributes lastErrNode, lastErr and lastErrCode. attributes lastErrNode, lastErr and lastErrCode.
""" """

View file

@ -2097,7 +2097,7 @@ class FakeDataForm(gtk.Table, object):
self._draw_table() self._draw_table()
def _draw_table(self): def _draw_table(self):
'''Draw the table in the window''' '''Draw the table'''
nbrow = 0 nbrow = 0
if self.infos.has_key('instructions'): if self.infos.has_key('instructions'):
nbrow = 1 nbrow = 1
@ -2778,13 +2778,21 @@ class AccountCreationWizardWindow:
'account_creation_wizard_window.glade') 'account_creation_wizard_window.glade')
self.window = self.xml.get_widget('account_creation_wizard_window') self.window = self.xml.get_widget('account_creation_wizard_window')
completion = gtk.EntryCompletion()
# Connect events from comboboxentry.child # Connect events from comboboxentry.child
server_comboboxentry = self.xml.get_widget('server_comboboxentry') server_comboboxentry = self.xml.get_widget('server_comboboxentry')
entry = server_comboboxentry.child entry = server_comboboxentry.child
entry.connect('key_press_event', entry.connect('key_press_event',
self.on_server_comboboxentry_key_press_event) self.on_server_comboboxentry_key_press_event, server_comboboxentry)
completion = gtk.EntryCompletion()
entry.set_completion(completion) entry.set_completion(completion)
# Do the same for the other server comboboxentry
server_comboboxentry1 = self.xml.get_widget('server_comboboxentry1')
entry = server_comboboxentry1.child
entry.connect('key_press_event',
self.on_server_comboboxentry_key_press_event, server_comboboxentry1)
entry.set_completion(completion)
self.update_proxy_list()
# parse servers.xml # parse servers.xml
servers_xml = os.path.join(gajim.DATA_DIR, 'other', 'servers.xml') servers_xml = os.path.join(gajim.DATA_DIR, 'other', 'servers.xml')
@ -2800,6 +2808,8 @@ class AccountCreationWizardWindow:
# Put servers into comboboxentries # Put servers into comboboxentries
server_comboboxentry.set_model(servers_model) server_comboboxentry.set_model(servers_model)
server_comboboxentry.set_text_column(0) server_comboboxentry.set_text_column(0)
server_comboboxentry1.set_model(servers_model)
server_comboboxentry1.set_text_column(0)
# Generic widgets # Generic widgets
self.notebook = self.xml.get_widget('notebook') self.notebook = self.xml.get_widget('notebook')
@ -2838,28 +2848,18 @@ class AccountCreationWizardWindow:
self.window.destroy() self.window.destroy()
def on_back_button_clicked(self, widget): def on_back_button_clicked(self, widget):
if self.notebook.get_current_page() == 1: if self.notebook.get_current_page() in (1, 2):
self.notebook.set_current_page(0) self.notebook.set_current_page(0)
self.back_button.set_sensitive(False) self.back_button.set_sensitive(False)
elif self.notebook.get_current_page() == 3: # finish page elif self.notebook.get_current_page() == 3:
self.notebook.set_current_page(2)
self.xml.get_widget('form_vbox').remove(self.data_form_widget)
elif self.notebook.get_current_page() == 5: # finish page
self.forward_button.show() self.forward_button.show()
self.notebook.set_current_page(1) # Goto parameters page if self.modify:
self.notebook.set_current_page(1) # Go to parameters page
def get_widgets(self): else:
widgets = {} self.notebook.set_current_page(2) # Go to server page
for widget in (
'username_entry',
'server_comboboxentry',
'pass1_entry',
'pass2_entry',
'save_password_checkbutton',
'proxyhost_entry',
'proxyport_entry',
'proxyuser_entry',
'proxypass_entry',
'jid_label'):
widgets[widget] = self.xml.get_widget(widget)
return widgets
def on_forward_button_clicked(self, widget): def on_forward_button_clicked(self, widget):
cur_page = self.notebook.get_current_page() cur_page = self.notebook.get_current_page()
@ -2868,74 +2868,64 @@ class AccountCreationWizardWindow:
widget = self.xml.get_widget('use_existing_account_radiobutton') widget = self.xml.get_widget('use_existing_account_radiobutton')
if widget.get_active(): if widget.get_active():
self.modify = True self.modify = True
self.xml.get_widget('server_features_button').hide() self.notebook.set_current_page(1)
self.xml.get_widget('pass2_entry').hide()
self.xml.get_widget('pass2_label').hide()
else: else:
self.modify = False self.modify = False
self.xml.get_widget('server_features_button').show() self.notebook.set_current_page(2)
self.xml.get_widget('pass2_entry').show()
self.xml.get_widget('pass2_label').show()
self.notebook.set_current_page(1)
self.back_button.set_sensitive(True) self.back_button.set_sensitive(True)
return return
widgets = self.get_widgets() elif cur_page == 1:
username = widgets['username_entry'].get_text().decode('utf-8') # We are adding an existing account
if not username: username = self.xml.get_widget('username_entry').get_text().decode(
pritext = _('Invalid username') 'utf-8')
sectext = _('You must provide a username to configure this account.') if not username:
dialogs.ErrorDialog(pritext, sectext) pritext = _('Invalid username')
return sectext = _(
server = widgets['server_comboboxentry'].child.get_text().decode('utf-8') 'You must provide a username to configure this account.')
savepass = widgets['save_password_checkbutton'].get_active() dialogs.ErrorDialog(pritext, sectext)
password = widgets['pass1_entry'].get_text().decode('utf-8') return
server = self.xml.get_widget('server_comboboxentry').child.get_text().\
decode('utf-8')
savepass = self.xml.get_widget('save_password_checkbutton').\
get_active()
password = self.xml.get_widget('password_entry').get_text().decode(
'utf-8')
if not self.modify: jid = username + '@' + server
if password == '': # check if jid is conform to RFC and stringprep it
dialogs.ErrorDialog(_('Invalid password'), try:
_('You must enter a password for the new account.')) jid = helpers.parse_jid(jid)
except helpers.InvalidFormat, s:
pritext = _('Invalid Jabber ID')
dialogs.ErrorDialog(pritext, str(s))
return return
if widgets['pass2_entry'].get_text() != password: already_in_jids = []
dialogs.ErrorDialog(_('Passwords do not match'), for account in gajim.connections:
_('The passwords typed in both fields must be identical.')) j = gajim.config.get_per('accounts', account, 'name')
j += '@' + gajim.config.get_per('accounts', account, 'hostname')
already_in_jids.append(j)
if jid in already_in_jids:
pritext = _('Duplicate Jabber ID')
sectext = _('This account is already configured in Gajim.')
dialogs.ErrorDialog(pritext, sectext)
return return
jid = username + '@' + server self.account = server
# check if jid is conform to RFC and stringprep it i = 1
try: while self.account in gajim.connections:
jid = helpers.parse_jid(jid) self.account = server + str(i)
except helpers.InvalidFormat, s: i += 1
pritext = _('Invalid Jabber ID')
dialogs.ErrorDialog(pritext, str(s))
return
already_in_jids = [] username, server = gajim.get_name_and_server_from_jid(jid)
for account in gajim.connections: self.save_account(username, server, savepass, password)
j = gajim.config.get_per('accounts', account, 'name') self.cancel_button.hide()
j += '@' + gajim.config.get_per('accounts', account, 'hostname') self.back_button.hide()
already_in_jids.append(j) self.forward_button.hide()
if self.modify:
if jid in already_in_jids: finish_text = '<big><b>%s</b></big>\n\n%s' % (
pritext = _('Duplicate Jabber ID')
sectext = _('This account is already configured in Gajim.')
dialogs.ErrorDialog(pritext, sectext)
return
self.account = server
i = 1
while self.account in gajim.connections:
self.account = server + str(i)
i += 1
username, server = gajim.get_name_and_server_from_jid(jid)
self.save_account(username, server, savepass, password)
self.cancel_button.hide()
self.back_button.hide()
self.forward_button.hide()
if self.modify:
finish_text = '<big><b>%s</b></big>\n\n%s' % (
_('Account has been added successfully'), _('Account has been added successfully'),
_('You can set advanced account options by pressing the ' _('You can set advanced account options by pressing the '
'Advanced button, or later by choosing the Accounts menuitem ' 'Advanced button, or later by choosing the Accounts menuitem '
@ -2947,20 +2937,130 @@ class AccountCreationWizardWindow:
self.go_online_checkbutton.show() self.go_online_checkbutton.show()
img = self.xml.get_widget('finish_image') img = self.xml.get_widget('finish_image')
img.set_from_stock(gtk.STOCK_APPLY, gtk.ICON_SIZE_DIALOG) img.set_from_stock(gtk.STOCK_APPLY, gtk.ICON_SIZE_DIALOG)
self.notebook.set_current_page(3) # show finish page self.notebook.set_current_page(5) # show finish page
self.show_vcard_checkbutton.set_active(False) self.show_vcard_checkbutton.set_active(False)
else: elif cur_page == 2:
self.notebook.set_current_page(2) # show creating page server = self.xml.get_widget('server_comboboxentry1').child.get_text()\
.decode('utf-8')
if not server:
dialogs.ErrorDialog(_('Invalid server'),
_('Please provide a server on which you want to register.'))
return
self.account = server
i = 1
while self.account in gajim.connections:
self.account = server + str(i)
i += 1
config = self.get_config('', server, '', '')
# Get advanced options
proxies_combobox = self.xml.get_widget('proxies_combobox')
active = proxies_combobox.get_active()
proxy = proxies_combobox.get_model()[active][0].decode('utf-8')
if proxy == _('None'):
proxy = ''
config['proxy'] = proxy
config['use_custom_host'] = self.xml.get_widget(
'custom_host_port_checkbutton').get_active()
custom_port = self.xml.get_widget('custom_port_entry').get_text()
try:
custom_port = int(custom_port)
except:
dialogs.ErrorDialog(_('Invalid entry'),
_('Custom port must be a port number.'))
return
config['custom_port'] = custom_port
config['custom_host'] = self.xml.get_widget(
'custom_host_entry').get_text().decode('utf-8')
self.notebook.set_current_page(4) # show creating page
self.back_button.hide()
self.forward_button.hide()
self.update_progressbar_timeout_id = gobject.timeout_add(100, self.update_progressbar_timeout_id = gobject.timeout_add(100,
self.update_progressbar) self.update_progressbar)
# Get form from serveur
con = connection.Connection(self.account)
con.new_account(self.account, config)
gajim.connections[self.account] = con
elif cur_page == 3:
if self.is_form:
form = self.data_form_widget.data_form
else:
form = self.data_form_widget.get_infos()
gajim.connections[self.account].send_new_account_infos(form,
self.is_form)
self.xml.get_widget('form_vbox').remove(self.data_form_widget)
self.xml.get_widget('progressbar_label').set_markup('<b>Account is being created</b>\n\nPlease wait...')
self.notebook.set_current_page(4) # show creating page
self.back_button.hide()
self.forward_button.hide()
self.update_progressbar_timeout_id = gobject.timeout_add(100,
self.update_progressbar)
def update_proxy_list(self):
proxies_combobox = self.xml.get_widget('proxies_combobox')
model = gtk.ListStore(str)
proxies_combobox.set_model(model)
l = gajim.config.get_per('proxies')
l.insert(0, _('None'))
for i in xrange(len(l)):
model.append([l[i]])
proxies_combobox.set_active(0)
def on_manage_proxies_button_clicked(self, widget):
if gajim.interface.instances.has_key('manage_proxies'):
gajim.interface.instances['manage_proxies'].window.present()
else:
gajim.interface.instances['manage_proxies'] = \
ManageProxiesWindow()
def on_custom_host_port_checkbutton_toggled(self, widget):
self.xml.get_widget('custom_host_hbox').set_sensitive(widget.get_active())
def update_progressbar(self): def update_progressbar(self):
self.progressbar.pulse() self.progressbar.pulse()
return True # loop forever return True # loop forever
def new_acc_connected(self, form, is_form):
'''connection to server succeded, present the form to the user'''
if self.update_progressbar_timeout_id is not None:
gobject.source_remove(self.update_progressbar_timeout_id)
self.back_button.show()
self.forward_button.show()
self.notebook.set_current_page(3) # show form page
self.is_form = is_form
if is_form:
dataform = dataforms.ExtendForm(node = form)
self.data_form_widget = dataforms_widget.DataFormWidget(dataform)
else:
self.data_form_widget = FakeDataForm(form)
self.data_form_widget.show_all()
self.xml.get_widget('form_vbox').pack_start(self.data_form_widget)
def new_acc_not_connected(self, reason):
'''Account creation failed: connection to server failed'''
if self.update_progressbar_timeout_id is not None:
gobject.source_remove(self.update_progressbar_timeout_id)
del gajim.connections[self.account]
self.back_button.show()
self.cancel_button.show()
self.go_online_checkbutton.hide()
self.show_vcard_checkbutton.hide()
img = self.xml.get_widget('finish_image')
img.set_from_stock(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_DIALOG)
finish_text = '<big><b>%s</b></big>\n\n%s' % (
_('An error occurred during account creation') , reason)
self.finish_label.set_markup(finish_text)
self.notebook.set_current_page(5) # show finish page
def acc_is_ok(self, config): def acc_is_ok(self, config):
'''Account creation succeeded''' '''Account creation succeeded'''
self.create_vars(config) self.create_vars(config)
self.cancel_button.hide()
self.back_button.hide()
self.forward_button.hide()
self.finish_button.show() self.finish_button.show()
self.finish_button.set_property('has-default', True) self.finish_button.set_property('has-default', True)
self.advanced_button.show() self.advanced_button.show()
@ -2976,7 +3076,7 @@ class AccountCreationWizardWindow:
'button, or later by choosing the Accounts menuitem under the Edit ' 'button, or later by choosing the Accounts menuitem under the Edit '
'menu from the main window.')) 'menu from the main window.'))
self.finish_label.set_markup(finish_text) self.finish_label.set_markup(finish_text)
self.notebook.set_current_page(3) # show finish page self.notebook.set_current_page(5) # show finish page
if self.update_progressbar_timeout_id is not None: if self.update_progressbar_timeout_id is not None:
gobject.source_remove(self.update_progressbar_timeout_id) gobject.source_remove(self.update_progressbar_timeout_id)
@ -2987,12 +3087,16 @@ class AccountCreationWizardWindow:
self.cancel_button.show() self.cancel_button.show()
self.go_online_checkbutton.hide() self.go_online_checkbutton.hide()
self.show_vcard_checkbutton.hide() self.show_vcard_checkbutton.hide()
del gajim.connections[self.account]
img = self.xml.get_widget('finish_image') img = self.xml.get_widget('finish_image')
img.set_from_stock(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_DIALOG) img.set_from_stock(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_DIALOG)
finish_text = '<big><b>%s</b></big>\n\n%s' % (_('An error occurred during ' finish_text = '<big><b>%s</b></big>\n\n%s' % (_('An error occurred during '
'account creation') , reason) 'account creation') , reason)
self.finish_label.set_markup(finish_text) self.finish_label.set_markup(finish_text)
self.notebook.set_current_page(3) # show finish page self.notebook.set_current_page(5) # show finish page
if self.update_progressbar_timeout_id is not None:
gobject.source_remove(self.update_progressbar_timeout_id)
def on_advanced_button_clicked(self, widget): def on_advanced_button_clicked(self, widget):
gajim.interface.instances[self.account]['account_modification'] = \ gajim.interface.instances[self.account]['account_modification'] = \
@ -3022,12 +3126,11 @@ class AccountCreationWizardWindow:
combobox.child.set_position(-1) combobox.child.set_position(-1)
return True return True
def on_server_comboboxentry_key_press_event(self, widget, event): def on_server_comboboxentry_key_press_event(self, widget, event, combobox):
# If backspace is pressed in empty field, return to the nick entry field # If backspace is pressed in empty field, return to the nick entry field
backspace = event.keyval == gtk.keysyms.BackSpace backspace = event.keyval == gtk.keysyms.BackSpace
combobox = self.xml.get_widget('server_comboboxentry')
empty = len(combobox.get_active_text()) == 0 empty = len(combobox.get_active_text()) == 0
if backspace and empty: if backspace and empty and self.modify:
username_entry = self.xml.get_widget('username_entry') username_entry = self.xml.get_widget('username_entry')
username_entry.grab_focus() username_entry.grab_focus()
username_entry.set_position(-1) username_entry.set_position(-1)
@ -3045,14 +3148,7 @@ class AccountCreationWizardWindow:
string = '<b>%s@%s</b>' % (name, server) string = '<b>%s@%s</b>' % (name, server)
jid_label.set_label(string) jid_label.set_label(string)
def save_account(self, login, server, savepass, password): def get_config(self, login, server, savepass, password):
if self.account in gajim.connections:
dialogs.ErrorDialog(_('Account name is in use'),
_('You already have an account using this name.'))
return
con = connection.Connection(self.account)
con.password = password
config = {} config = {}
config['name'] = login config['name'] = login
config['hostname'] = server config['hostname'] = server
@ -3072,6 +3168,17 @@ class AccountCreationWizardWindow:
config['keyid'] = '' config['keyid'] = ''
config['savegpgpass'] = False config['savegpgpass'] = False
config['gpgpassword'] = '' config['gpgpassword'] = ''
return config
def save_account(self, login, server, savepass, password):
if self.account in gajim.connections:
dialogs.ErrorDialog(_('Account name is in use'),
_('You already have an account using this name.'))
return
con = connection.Connection(self.account)
con.password = password
config = self.get_config(login, server, savepass, password)
if not self.modify: if not self.modify:
con.new_account(self.account, config) con.new_account(self.account, config)

View file

@ -948,6 +948,17 @@ class Interface:
except AttributeError: except AttributeError:
return return
def handle_event_new_acc_connected(self, account, array):
#('NEW_ACC_CONNECTED', account, (infos, is_form))
if self.instances.has_key('account_creation_wizard'):
self.instances['account_creation_wizard'].new_acc_connected(array[0],
array[1])
def handle_event_new_acc_not_connected(self, account, array):
#('NEW_ACC_NOT_CONNECTED', account, (reason))
if self.instances.has_key('account_creation_wizard'):
self.instances['account_creation_wizard'].new_acc_not_connected(array)
def handle_event_acc_ok(self, account, array): def handle_event_acc_ok(self, account, array):
#('ACC_OK', account, (config)) #('ACC_OK', account, (config))
if self.instances.has_key('account_creation_wizard'): if self.instances.has_key('account_creation_wizard'):
@ -2047,6 +2058,8 @@ class Interface:
'AGENT_INFO_ITEMS': self.handle_event_agent_info_items, 'AGENT_INFO_ITEMS': self.handle_event_agent_info_items,
'AGENT_INFO_INFO': self.handle_event_agent_info_info, 'AGENT_INFO_INFO': self.handle_event_agent_info_info,
'QUIT': self.handle_event_quit, 'QUIT': self.handle_event_quit,
'NEW_ACC_CONNECTED': self.handle_event_new_acc_connected,
'NEW_ACC_NOT_CONNECTED': self.handle_event_new_acc_not_connected,
'ACC_OK': self.handle_event_acc_ok, 'ACC_OK': self.handle_event_acc_ok,
'ACC_NOT_OK': self.handle_event_acc_not_ok, 'ACC_NOT_OK': self.handle_event_acc_not_ok,
'MYVCARD': self.handle_event_myvcard, 'MYVCARD': self.handle_event_myvcard,