2016-02-19 11:43:46 +01:00
|
|
|
// Converse.js (A browser based XMPP chat client)
|
|
|
|
// http://conversejs.org
|
|
|
|
//
|
2017-02-13 15:37:17 +01:00
|
|
|
// Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
|
2016-02-19 11:43:46 +01:00
|
|
|
// Licensed under the Mozilla Public License (MPLv2)
|
|
|
|
//
|
2017-04-21 15:52:16 +02:00
|
|
|
/*global define */
|
2016-02-19 11:43:46 +01:00
|
|
|
|
|
|
|
/* This is a Converse.js plugin which add support for in-band registration
|
|
|
|
* as specified in XEP-0077.
|
|
|
|
*/
|
|
|
|
(function (root, factory) {
|
2017-02-14 15:08:39 +01:00
|
|
|
define(["converse-core",
|
2016-09-23 10:54:55 +02:00
|
|
|
"tpl!form_username",
|
|
|
|
"tpl!register_panel",
|
|
|
|
"tpl!register_tab",
|
|
|
|
"tpl!registration_form",
|
|
|
|
"tpl!registration_request",
|
2017-06-14 18:09:22 +02:00
|
|
|
"tpl!spinner",
|
2016-02-28 20:24:06 +01:00
|
|
|
"converse-controlbox"
|
|
|
|
], factory);
|
2016-09-23 10:54:55 +02:00
|
|
|
}(this, function (
|
2016-12-20 11:42:20 +01:00
|
|
|
converse,
|
2016-09-23 10:54:55 +02:00
|
|
|
tpl_form_username,
|
|
|
|
tpl_register_panel,
|
|
|
|
tpl_register_tab,
|
|
|
|
tpl_registration_form,
|
2017-06-14 18:09:22 +02:00
|
|
|
tpl_registration_request,
|
|
|
|
tpl_spinner
|
|
|
|
) {
|
2016-09-23 10:54:55 +02:00
|
|
|
|
2016-02-19 11:43:46 +01:00
|
|
|
"use strict";
|
2016-09-23 10:54:55 +02:00
|
|
|
|
2016-02-19 11:43:46 +01:00
|
|
|
// Strophe methods for building stanzas
|
2016-12-20 11:42:20 +01:00
|
|
|
var Strophe = converse.env.Strophe,
|
2017-04-21 15:52:16 +02:00
|
|
|
Backbone = converse.env.Backbone,
|
2016-12-20 11:42:20 +01:00
|
|
|
utils = converse.env.utils,
|
|
|
|
$iq = converse.env.$iq;
|
2016-02-19 11:43:46 +01:00
|
|
|
// Other necessary globals
|
2016-12-20 11:42:20 +01:00
|
|
|
var $ = converse.env.jQuery,
|
|
|
|
_ = converse.env._;
|
2017-03-31 03:54:42 +02:00
|
|
|
|
2016-02-19 11:43:46 +01:00
|
|
|
// Add Strophe Namespaces
|
|
|
|
Strophe.addNamespace('REGISTER', 'jabber:iq:register');
|
|
|
|
|
|
|
|
// Add Strophe Statuses
|
|
|
|
var i = 0;
|
2017-01-26 15:49:02 +01:00
|
|
|
_.each(_.keys(Strophe.Status), function (key) {
|
2016-02-19 11:43:46 +01:00
|
|
|
i = Math.max(i, Strophe.Status[key]);
|
|
|
|
});
|
|
|
|
Strophe.Status.REGIFAIL = i + 1;
|
|
|
|
Strophe.Status.REGISTERED = i + 2;
|
|
|
|
Strophe.Status.CONFLICT = i + 3;
|
|
|
|
Strophe.Status.NOTACCEPTABLE = i + 5;
|
|
|
|
|
2016-12-20 11:42:20 +01:00
|
|
|
converse.plugins.add('converse-register', {
|
2016-02-19 11:43:46 +01:00
|
|
|
|
|
|
|
overrides: {
|
|
|
|
// Overrides mentioned here will be picked up by converse.js's
|
|
|
|
// plugin architecture they will replace existing methods on the
|
|
|
|
// relevant objects or classes.
|
|
|
|
//
|
|
|
|
// New functions which don't exist yet can also be added.
|
|
|
|
|
|
|
|
ControlBoxView: {
|
|
|
|
|
2017-03-31 03:54:42 +02:00
|
|
|
switchTab: function (ev) {
|
|
|
|
var _converse = this.__super__._converse;
|
|
|
|
var result = this.__super__.switchTab.apply(this, arguments);
|
|
|
|
if (_converse.registration_domain &&
|
|
|
|
ev.target.getAttribute('data-id') === "register" &&
|
|
|
|
!this.model.get('registration_form_rendered')) {
|
|
|
|
this.registerpanel.fetchRegistrationForm(_converse.registration_domain);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
},
|
|
|
|
|
2017-06-13 19:11:09 +02:00
|
|
|
renderRegistrationPanel: function () {
|
2016-12-20 11:28:30 +01:00
|
|
|
var _converse = this.__super__._converse;
|
2016-12-20 10:30:20 +01:00
|
|
|
if (_converse.allow_registration) {
|
|
|
|
this.registerpanel = new _converse.RegisterPanel({
|
2016-02-19 11:43:46 +01:00
|
|
|
'$parent': this.$el.find('.controlbox-panes'),
|
2017-03-31 03:54:42 +02:00
|
|
|
'model': this.model
|
2016-04-08 10:29:30 +02:00
|
|
|
});
|
2016-11-02 23:08:20 +01:00
|
|
|
this.registerpanel.render().$el.addClass('hidden');
|
2016-02-19 11:43:46 +01:00
|
|
|
}
|
|
|
|
return this;
|
2017-06-13 19:11:09 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
renderLoginPanel: function () {
|
|
|
|
/* Also render a registration panel, when rendering the
|
|
|
|
* login panel.
|
|
|
|
*/
|
|
|
|
this.__super__.renderLoginPanel.apply(this, arguments);
|
|
|
|
this.renderRegistrationPanel();
|
|
|
|
return this;
|
2016-02-19 11:43:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
initialize: function () {
|
|
|
|
/* The initialize function gets called as soon as the plugin is
|
|
|
|
* loaded by converse.js's plugin machinery.
|
|
|
|
*/
|
2016-12-20 11:42:20 +01:00
|
|
|
var _converse = this._converse,
|
|
|
|
__ = _converse.__;
|
|
|
|
|
|
|
|
// Add new templates
|
|
|
|
_converse.templates.form_username = tpl_form_username;
|
|
|
|
_converse.templates.register_panel = tpl_register_panel;
|
|
|
|
_converse.templates.register_tab = tpl_register_tab;
|
|
|
|
_converse.templates.registration_form = tpl_registration_form;
|
|
|
|
_converse.templates.registration_request = tpl_registration_request;
|
2016-03-13 17:22:42 +01:00
|
|
|
|
2017-07-05 11:03:13 +02:00
|
|
|
_converse.api.settings.update({
|
2016-02-19 11:43:46 +01:00
|
|
|
allow_registration: true,
|
|
|
|
domain_placeholder: __(" e.g. conversejs.org"), // Placeholder text shown in the domain input on the registration form
|
|
|
|
providers_link: 'https://xmpp.net/directory.php', // Link to XMPP providers shown on registration page
|
2016-03-13 17:22:42 +01:00
|
|
|
});
|
2016-02-19 11:43:46 +01:00
|
|
|
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.RegisterPanel = Backbone.View.extend({
|
2016-02-19 11:43:46 +01:00
|
|
|
tagName: 'div',
|
|
|
|
id: "register",
|
|
|
|
className: 'controlbox-pane',
|
|
|
|
events: {
|
|
|
|
'submit form#converse-register': 'onProviderChosen'
|
|
|
|
},
|
|
|
|
|
|
|
|
initialize: function (cfg) {
|
|
|
|
this.reset();
|
|
|
|
this.$parent = cfg.$parent;
|
|
|
|
this.$tabs = cfg.$parent.parent().find('#controlbox-tabs');
|
|
|
|
this.registerHooks();
|
|
|
|
},
|
|
|
|
|
|
|
|
render: function () {
|
2017-03-31 03:54:42 +02:00
|
|
|
this.model.set('registration_form_rendered', false);
|
2016-02-19 11:43:46 +01:00
|
|
|
this.$parent.append(this.$el.html(
|
2017-02-19 10:58:30 +01:00
|
|
|
tpl_register_panel({
|
2017-03-20 13:21:03 +01:00
|
|
|
'default_domain': _converse.registration_domain,
|
2016-02-19 11:43:46 +01:00
|
|
|
'label_domain': __("Your XMPP provider's domain name:"),
|
|
|
|
'label_register': __('Fetch registration form'),
|
|
|
|
'help_providers': __('Tip: A list of public XMPP providers is available'),
|
|
|
|
'help_providers_link': __('here'),
|
2016-12-20 10:30:20 +01:00
|
|
|
'href_providers': _converse.providers_link,
|
|
|
|
'domain_placeholder': _converse.domain_placeholder
|
2016-02-19 11:43:46 +01:00
|
|
|
})
|
|
|
|
));
|
2017-02-19 10:58:30 +01:00
|
|
|
this.$tabs.append(tpl_register_tab({label_register: __('Register')}));
|
2016-02-19 11:43:46 +01:00
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
registerHooks: function () {
|
|
|
|
/* Hook into Strophe's _connect_cb, so that we can send an IQ
|
2016-03-19 23:16:00 +01:00
|
|
|
* requesting the registration fields.
|
|
|
|
*/
|
2016-12-20 10:30:20 +01:00
|
|
|
var conn = _converse.connection;
|
2016-02-19 11:43:46 +01:00
|
|
|
var connect_cb = conn._connect_cb.bind(conn);
|
|
|
|
conn._connect_cb = function (req, callback, raw) {
|
|
|
|
if (!this._registering) {
|
|
|
|
connect_cb(req, callback, raw);
|
|
|
|
} else {
|
|
|
|
if (this.getRegistrationFields(req, callback, raw)) {
|
|
|
|
this._registering = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}.bind(this);
|
|
|
|
},
|
|
|
|
|
|
|
|
getRegistrationFields: function (req, _callback, raw) {
|
|
|
|
/* Send an IQ stanza to the XMPP server asking for the
|
2016-03-19 23:16:00 +01:00
|
|
|
* registration fields.
|
|
|
|
* Parameters:
|
|
|
|
* (Strophe.Request) req - The current request
|
|
|
|
* (Function) callback
|
|
|
|
*/
|
2016-12-20 10:30:20 +01:00
|
|
|
var conn = _converse.connection;
|
2016-02-19 11:43:46 +01:00
|
|
|
conn.connected = true;
|
|
|
|
|
|
|
|
var body = conn._proto._reqToData(req);
|
|
|
|
if (!body) { return; }
|
|
|
|
if (conn._proto._connect_cb(body) === Strophe.Status.CONNFAIL) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
var register = body.getElementsByTagName("register");
|
|
|
|
var mechanisms = body.getElementsByTagName("mechanism");
|
|
|
|
if (register.length === 0 && mechanisms.length === 0) {
|
|
|
|
conn._proto._no_auth_received(_callback);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (register.length === 0) {
|
|
|
|
conn._changeConnectStatus(
|
|
|
|
Strophe.Status.REGIFAIL,
|
2017-03-31 03:54:42 +02:00
|
|
|
__("Sorry, the given provider does not support in "+
|
|
|
|
"band account registration. Please try with a "+
|
|
|
|
"different provider.")
|
2016-02-19 11:43:46 +01:00
|
|
|
);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// Send an IQ stanza to get all required data fields
|
|
|
|
conn._addSysHandler(this.onRegistrationFields.bind(this), null, "iq", null, null);
|
|
|
|
conn.send($iq({type: "get"}).c("query", {xmlns: Strophe.NS.REGISTER}).tree());
|
2017-03-31 03:54:42 +02:00
|
|
|
conn.connected = false;
|
2016-02-19 11:43:46 +01:00
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
|
|
|
onRegistrationFields: function (stanza) {
|
|
|
|
/* Handler for Registration Fields Request.
|
2016-03-19 23:16:00 +01:00
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* (XMLElement) elem - The query stanza.
|
|
|
|
*/
|
2016-02-19 11:43:46 +01:00
|
|
|
if (stanza.getElementsByTagName("query").length !== 1) {
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.connection._changeConnectStatus(Strophe.Status.REGIFAIL, "unknown");
|
2016-02-19 11:43:46 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
this.setFields(stanza);
|
|
|
|
this.renderRegistrationForm(stanza);
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
|
|
|
reset: function (settings) {
|
|
|
|
var defaults = {
|
|
|
|
fields: {},
|
|
|
|
urls: [],
|
|
|
|
title: "",
|
|
|
|
instructions: "",
|
|
|
|
registered: false,
|
|
|
|
_registering: false,
|
|
|
|
domain: null,
|
|
|
|
form_type: null
|
|
|
|
};
|
|
|
|
_.extend(this, defaults);
|
|
|
|
if (settings) {
|
2017-01-26 15:49:02 +01:00
|
|
|
_.extend(this, _.pick(settings, _.keys(defaults)));
|
2016-02-19 11:43:46 +01:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
onProviderChosen: function (ev) {
|
|
|
|
/* Callback method that gets called when the user has chosen an
|
2016-03-19 23:16:00 +01:00
|
|
|
* XMPP provider.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* (Submit Event) ev - Form submission event.
|
|
|
|
*/
|
2016-02-19 11:43:46 +01:00
|
|
|
if (ev && ev.preventDefault) { ev.preventDefault(); }
|
|
|
|
var $form = $(ev.target),
|
|
|
|
$domain_input = $form.find('input[name=domain]'),
|
|
|
|
domain = $domain_input.val();
|
|
|
|
if (!domain) {
|
|
|
|
$domain_input.addClass('error');
|
|
|
|
return;
|
|
|
|
}
|
2017-03-20 13:21:03 +01:00
|
|
|
$form.find('input[type=submit]').hide();
|
2017-03-31 03:54:42 +02:00
|
|
|
this.fetchRegistrationForm(domain, __('Cancel'));
|
2017-03-20 13:21:03 +01:00
|
|
|
},
|
|
|
|
|
2017-03-31 03:54:42 +02:00
|
|
|
fetchRegistrationForm: function (domain_name, cancel_label) {
|
2017-03-20 13:21:03 +01:00
|
|
|
/* This is called with a domain name based on which, it fetches a
|
|
|
|
* registration form from the requested domain.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* (Domain name) domain_name - XMPP server domain
|
2017-03-31 03:54:42 +02:00
|
|
|
*/
|
|
|
|
this.renderRegistrationRequest(cancel_label);
|
2016-02-19 11:43:46 +01:00
|
|
|
this.reset({
|
2017-03-20 13:21:03 +01:00
|
|
|
domain: Strophe.getDomainFromJid(domain_name),
|
2016-02-19 11:43:46 +01:00
|
|
|
_registering: true
|
|
|
|
});
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.connection.connect(this.domain, "", this.onRegistering.bind(this));
|
2017-03-31 03:54:42 +02:00
|
|
|
return false;
|
2017-03-20 13:21:03 +01:00
|
|
|
},
|
|
|
|
|
2017-03-31 03:54:42 +02:00
|
|
|
renderRegistrationRequest: function (cancel_label) {
|
|
|
|
var form = this.el.querySelector('#converse-register');
|
|
|
|
utils.createElementsFromString(
|
|
|
|
form,
|
|
|
|
tpl_registration_request({
|
|
|
|
cancel: cancel_label,
|
|
|
|
info_message: _converse.__('Requesting a registration form from the XMPP server')
|
|
|
|
})
|
|
|
|
);
|
2017-03-20 13:21:03 +01:00
|
|
|
if (!_converse.registration_domain) {
|
|
|
|
var cancel_button = document.querySelector('button.button-cancel');
|
|
|
|
cancel_button.addEventListener('click', this.cancelRegistration.bind(this));
|
|
|
|
}
|
2016-02-19 11:43:46 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
giveFeedback: function (message, klass) {
|
|
|
|
this.$('.reg-feedback').attr('class', 'reg-feedback').text(message);
|
|
|
|
if (klass) {
|
|
|
|
$('.reg-feedback').addClass(klass);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
onRegistering: function (status, error) {
|
|
|
|
var that;
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.log('onRegistering');
|
2017-01-26 15:49:02 +01:00
|
|
|
if (_.includes([
|
2016-02-19 11:43:46 +01:00
|
|
|
Strophe.Status.DISCONNECTED,
|
|
|
|
Strophe.Status.CONNFAIL,
|
|
|
|
Strophe.Status.REGIFAIL,
|
|
|
|
Strophe.Status.NOTACCEPTABLE,
|
|
|
|
Strophe.Status.CONFLICT
|
|
|
|
], status)) {
|
|
|
|
|
2017-07-05 11:33:55 +02:00
|
|
|
_converse.log(
|
|
|
|
'Problem during registration: Strophe.Status is: '+status,
|
|
|
|
Strophe.LogLevel.ERROR
|
|
|
|
);
|
2016-02-19 11:43:46 +01:00
|
|
|
this.cancelRegistration();
|
|
|
|
if (error) {
|
|
|
|
this.giveFeedback(error, 'error');
|
|
|
|
} else {
|
|
|
|
this.giveFeedback(__(
|
2016-12-19 08:46:48 +01:00
|
|
|
'Something went wrong while establishing a connection with "%1$s". Are you sure it exists?',
|
|
|
|
this.domain
|
|
|
|
), 'error');
|
2016-02-19 11:43:46 +01:00
|
|
|
}
|
|
|
|
} else if (status === Strophe.Status.REGISTERED) {
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.log("Registered successfully.");
|
|
|
|
_converse.connection.reset();
|
2016-02-19 11:43:46 +01:00
|
|
|
that = this;
|
|
|
|
this.$('form').hide(function () {
|
2017-06-14 18:09:22 +02:00
|
|
|
$(this).replaceWith(tpl_spinner);
|
2016-02-19 11:43:46 +01:00
|
|
|
if (that.fields.password && that.fields.username) {
|
|
|
|
// automatically log the user in
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.connection.connect(
|
2016-02-19 11:43:46 +01:00
|
|
|
that.fields.username.toLowerCase()+'@'+that.domain.toLowerCase(),
|
|
|
|
that.fields.password,
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.onConnectStatusChanged
|
2016-02-19 11:43:46 +01:00
|
|
|
);
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.chatboxviews.get('controlbox')
|
2016-12-19 08:46:48 +01:00
|
|
|
.switchTab({'target': that.$tabs.find('.current')});
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.giveFeedback(__('Now logging you in'));
|
2016-02-19 11:43:46 +01:00
|
|
|
} else {
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.chatboxviews.get('controlbox').renderLoginPanel();
|
|
|
|
_converse.giveFeedback(__('Registered successfully'));
|
2016-02-19 11:43:46 +01:00
|
|
|
}
|
|
|
|
that.reset();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
renderRegistrationForm: function (stanza) {
|
|
|
|
/* Renders the registration form based on the XForm fields
|
2016-03-19 23:16:00 +01:00
|
|
|
* received from the XMPP server.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* (XMLElement) stanza - The IQ stanza received from the XMPP server.
|
|
|
|
*/
|
2017-03-31 03:54:42 +02:00
|
|
|
this.model.set('registration_form_rendered', true);
|
|
|
|
|
|
|
|
var $form = this.$('form'),
|
2016-02-19 11:43:46 +01:00
|
|
|
$stanza = $(stanza),
|
|
|
|
$fields, $input;
|
2017-02-19 10:58:30 +01:00
|
|
|
$form.empty().append(tpl_registration_form({
|
2016-02-19 11:43:46 +01:00
|
|
|
'domain': this.domain,
|
|
|
|
'title': this.title,
|
|
|
|
'instructions': this.instructions
|
|
|
|
}));
|
|
|
|
if (this.form_type === 'xform') {
|
|
|
|
$fields = $stanza.find('field');
|
|
|
|
_.each($fields, function (field) {
|
|
|
|
$form.append(utils.xForm2webForm.bind(this, $(field), $stanza));
|
|
|
|
}.bind(this));
|
|
|
|
} else {
|
|
|
|
// Show fields
|
2017-01-26 15:49:02 +01:00
|
|
|
_.each(_.keys(this.fields), function (key) {
|
2016-02-19 11:43:46 +01:00
|
|
|
if (key === "username") {
|
2017-02-19 10:58:30 +01:00
|
|
|
$input = tpl_form_username({
|
2016-02-19 11:43:46 +01:00
|
|
|
domain: ' @'+this.domain,
|
|
|
|
name: key,
|
|
|
|
type: "text",
|
|
|
|
label: key,
|
|
|
|
value: '',
|
|
|
|
required: 1
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
$form.append('<label>'+key+'</label>');
|
|
|
|
$input = $('<input placeholder="'+key+'" name="'+key+'"></input>');
|
|
|
|
if (key === 'password' || key === 'email') {
|
|
|
|
$input.attr('type', key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$form.append($input);
|
|
|
|
}.bind(this));
|
|
|
|
// Show urls
|
|
|
|
_.each(this.urls, function (url) {
|
|
|
|
$form.append($('<a target="blank"></a>').attr('href', url).text(url));
|
|
|
|
}.bind(this));
|
|
|
|
}
|
|
|
|
if (this.fields) {
|
|
|
|
$form.append('<input type="submit" class="pure-button button-primary" value="'+__('Register')+'"/>');
|
|
|
|
$form.on('submit', this.submitRegistrationForm.bind(this));
|
|
|
|
$form.append('<input type="button" class="pure-button button-cancel" value="'+__('Cancel')+'"/>');
|
|
|
|
$form.find('input[type=button]').on('click', this.cancelRegistration.bind(this));
|
|
|
|
} else {
|
|
|
|
$form.append('<input type="button" class="submit" value="'+__('Return')+'"/>');
|
|
|
|
$form.find('input[type=button]').on('click', this.cancelRegistration.bind(this));
|
|
|
|
}
|
2017-03-20 13:21:03 +01:00
|
|
|
if (_converse.registration_domain) {
|
|
|
|
$form.find('input[type=button]').hide();
|
|
|
|
}
|
2016-02-19 11:43:46 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
reportErrors: function (stanza) {
|
|
|
|
/* Report back to the user any error messages received from the
|
2016-03-19 23:16:00 +01:00
|
|
|
* XMPP server after attempted registration.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* (XMLElement) stanza - The IQ stanza received from the
|
|
|
|
* XMPP server.
|
|
|
|
*/
|
2016-02-19 11:43:46 +01:00
|
|
|
var $form= this.$('form'), flash;
|
|
|
|
var $errmsgs = $(stanza).find('error text');
|
|
|
|
var $flash = $form.find('.form-errors');
|
|
|
|
if (!$flash.length) {
|
|
|
|
flash = '<legend class="form-errors"></legend>';
|
|
|
|
if ($form.find('p.instructions').length) {
|
|
|
|
$form.find('p.instructions').append(flash);
|
|
|
|
} else {
|
|
|
|
$form.prepend(flash);
|
|
|
|
}
|
|
|
|
$flash = $form.find('.form-errors');
|
|
|
|
} else {
|
|
|
|
$flash.empty();
|
|
|
|
}
|
|
|
|
$errmsgs.each(function (idx, txt) {
|
|
|
|
$flash.append($('<p>').text($(txt).text()));
|
|
|
|
});
|
|
|
|
if (!$errmsgs.length) {
|
|
|
|
$flash.append($('<p>').text(
|
|
|
|
__('The provider rejected your registration attempt. '+
|
|
|
|
'Please check the values you entered for correctness.')));
|
|
|
|
}
|
|
|
|
$flash.show();
|
|
|
|
},
|
|
|
|
|
|
|
|
cancelRegistration: function (ev) {
|
|
|
|
/* Handler, when the user cancels the registration form.
|
2016-03-19 23:16:00 +01:00
|
|
|
*/
|
2016-02-19 11:43:46 +01:00
|
|
|
if (ev && ev.preventDefault) { ev.preventDefault(); }
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.connection.reset();
|
2017-03-31 03:54:42 +02:00
|
|
|
this.model.set('registration_form_rendered', false);
|
2016-02-19 11:43:46 +01:00
|
|
|
this.render();
|
2017-03-20 13:21:03 +01:00
|
|
|
if (_converse.registration_domain) {
|
|
|
|
document.querySelector('button.button-cancel').onclick =
|
2017-03-31 03:54:42 +02:00
|
|
|
_.bind(
|
|
|
|
this.fetchRegistrationForm, this,
|
|
|
|
_converse.registration_domain, __('Retry')
|
|
|
|
);
|
2017-03-20 13:21:03 +01:00
|
|
|
}
|
2016-02-19 11:43:46 +01:00
|
|
|
},
|
|
|
|
|
2017-03-31 03:54:42 +02:00
|
|
|
submitRegistrationForm: function (ev) {
|
2016-02-19 11:43:46 +01:00
|
|
|
/* Handler, when the user submits the registration form.
|
2016-03-19 23:16:00 +01:00
|
|
|
* Provides form error feedback or starts the registration
|
|
|
|
* process.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* (Event) ev - the submit event.
|
|
|
|
*/
|
2016-02-19 11:43:46 +01:00
|
|
|
if (ev && ev.preventDefault) { ev.preventDefault(); }
|
2017-03-30 14:39:44 +02:00
|
|
|
var has_empty_inputs = _.reduce(this.el.querySelectorAll('input.required'),
|
2017-03-30 13:48:19 +02:00
|
|
|
function (result, input) {
|
|
|
|
if (input.value === '') {
|
|
|
|
input.classList.add('error');
|
|
|
|
return result + 1;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}, 0);
|
|
|
|
if (has_empty_inputs) { return; }
|
2016-02-19 11:43:46 +01:00
|
|
|
var $inputs = $(ev.target).find(':input:not([type=button]):not([type=submit])'),
|
|
|
|
iq = $iq({type: "set"}).c("query", {xmlns:Strophe.NS.REGISTER});
|
|
|
|
|
|
|
|
if (this.form_type === 'xform') {
|
|
|
|
iq.c("x", {xmlns: Strophe.NS.XFORM, type: 'submit'});
|
|
|
|
$inputs.each(function () {
|
|
|
|
iq.cnode(utils.webForm2xForm(this)).up();
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
$inputs.each(function () {
|
|
|
|
var $input = $(this);
|
|
|
|
iq.c($input.attr('name'), {}, $input.val());
|
|
|
|
});
|
|
|
|
}
|
2017-03-31 03:54:42 +02:00
|
|
|
this.model.set('registration_form_rendered', false);
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.connection._addSysHandler(this._onRegisterIQ.bind(this), null, "iq", null, null);
|
|
|
|
_converse.connection.send(iq);
|
2016-02-19 11:43:46 +01:00
|
|
|
this.setFields(iq.tree());
|
|
|
|
},
|
|
|
|
|
|
|
|
setFields: function (stanza) {
|
|
|
|
/* Stores the values that will be sent to the XMPP server
|
2016-03-19 23:16:00 +01:00
|
|
|
* during attempted registration.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* (XMLElement) stanza - the IQ stanza that will be sent to the XMPP server.
|
|
|
|
*/
|
2016-02-19 11:43:46 +01:00
|
|
|
var $query = $(stanza).find('query'), $xform;
|
|
|
|
if ($query.length > 0) {
|
|
|
|
$xform = $query.find('x[xmlns="'+Strophe.NS.XFORM+'"]');
|
|
|
|
if ($xform.length > 0) {
|
|
|
|
this._setFieldsFromXForm($xform);
|
|
|
|
} else {
|
|
|
|
this._setFieldsFromLegacy($query);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_setFieldsFromLegacy: function ($query) {
|
|
|
|
$query.children().each(function (idx, field) {
|
|
|
|
var $field = $(field);
|
|
|
|
if (field.tagName.toLowerCase() === 'instructions') {
|
|
|
|
this.instructions = Strophe.getText(field);
|
|
|
|
return;
|
|
|
|
} else if (field.tagName.toLowerCase() === 'x') {
|
|
|
|
if ($field.attr('xmlns') === 'jabber:x:oob') {
|
|
|
|
$field.find('url').each(function (idx, url) {
|
|
|
|
this.urls.push($(url).text());
|
|
|
|
}.bind(this));
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.fields[field.tagName.toLowerCase()] = Strophe.getText(field);
|
|
|
|
}.bind(this));
|
|
|
|
this.form_type = 'legacy';
|
|
|
|
},
|
|
|
|
|
|
|
|
_setFieldsFromXForm: function ($xform) {
|
|
|
|
this.title = $xform.find('title').text();
|
|
|
|
this.instructions = $xform.find('instructions').text();
|
|
|
|
$xform.find('field').each(function (idx, field) {
|
|
|
|
var _var = field.getAttribute('var');
|
|
|
|
if (_var) {
|
|
|
|
this.fields[_var.toLowerCase()] = $(field).children('value').text();
|
|
|
|
} else {
|
|
|
|
// TODO: other option seems to be type="fixed"
|
2017-07-05 11:33:55 +02:00
|
|
|
_converse.log("Found field we couldn't parse", Strophe.LogLevel.WARN);
|
2016-02-19 11:43:46 +01:00
|
|
|
}
|
|
|
|
}.bind(this));
|
|
|
|
this.form_type = 'xform';
|
|
|
|
},
|
|
|
|
|
|
|
|
_onRegisterIQ: function (stanza) {
|
|
|
|
/* Callback method that gets called when a return IQ stanza
|
2016-03-19 23:16:00 +01:00
|
|
|
* is received from the XMPP server, after attempting to
|
|
|
|
* register a new user.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* (XMLElement) stanza - The IQ stanza.
|
|
|
|
*/
|
2016-02-19 11:43:46 +01:00
|
|
|
var error = null,
|
|
|
|
query = stanza.getElementsByTagName("query");
|
|
|
|
if (query.length > 0) {
|
|
|
|
query = query[0];
|
|
|
|
}
|
|
|
|
if (stanza.getAttribute("type") === "error") {
|
2017-07-05 11:33:55 +02:00
|
|
|
_converse.log("Registration failed.", Strophe.LogLevel.ERROR);
|
2016-02-19 11:43:46 +01:00
|
|
|
error = stanza.getElementsByTagName("error");
|
|
|
|
if (error.length !== 1) {
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.connection._changeConnectStatus(Strophe.Status.REGIFAIL, "unknown");
|
2016-02-19 11:43:46 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
error = error[0].firstChild.tagName.toLowerCase();
|
|
|
|
if (error === 'conflict') {
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.connection._changeConnectStatus(Strophe.Status.CONFLICT, error);
|
2016-02-19 11:43:46 +01:00
|
|
|
} else if (error === 'not-acceptable') {
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.connection._changeConnectStatus(Strophe.Status.NOTACCEPTABLE, error);
|
2016-02-19 11:43:46 +01:00
|
|
|
} else {
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.connection._changeConnectStatus(Strophe.Status.REGIFAIL, error);
|
2016-02-19 11:43:46 +01:00
|
|
|
}
|
|
|
|
this.reportErrors(stanza);
|
|
|
|
} else {
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.connection._changeConnectStatus(Strophe.Status.REGISTERED, null);
|
2016-02-19 11:43:46 +01:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
|
|
|
remove: function () {
|
|
|
|
this.$tabs.empty();
|
|
|
|
this.$el.parent().empty();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}));
|