diff --git a/src/Signup.js b/src/Signup.js index 5b368b4811..4518955d95 100644 --- a/src/Signup.js +++ b/src/Signup.js @@ -293,8 +293,9 @@ class Register extends Signup { class Login extends Signup { - constructor(hsUrl, isUrl) { + constructor(hsUrl, isUrl, fallbackHsUrl) { super(hsUrl, isUrl); + this._fallbackHsUrl = fallbackHsUrl; this._currentFlowIndex = 0; this._flows = []; } @@ -359,6 +360,30 @@ class Login extends Signup { error.friendlyText = ( 'Incorrect username and/or password.' ); + if (self._fallbackHsUrl) { + // as per elsewhere, it would be much nicer to not replace the global + // client just to try an alternate HS + MatrixClientPeg.replaceUsingUrls( + self._fallbackHsUrl, + self._isUrl + ); + return MatrixClientPeg.get().login('m.login.password', loginParams).then(function(data) { + return q({ + homeserverUrl: self._fallbackHsUrl, + identityServerUrl: self._isUrl, + userId: data.user_id, + accessToken: data.access_token + }); + }, function(fallback_error) { + // We also have to put the default back again if it fails... + MatrixClientPeg.replaceUsingUrls( + this._hsUrl, + this._isUrl + ); + // throw the original error + throw error; + }); + } } else { error.friendlyText = ( diff --git a/src/Velociraptor.js b/src/Velociraptor.js index ad12d1323b..0abf34b230 100644 --- a/src/Velociraptor.js +++ b/src/Velociraptor.js @@ -106,6 +106,18 @@ module.exports = React.createClass({ }); //console.log("enter: "+JSON.stringify(node.props._restingStyle)); + } else if (node === null) { + // Velocity stores data on elements using the jQuery .data() + // method, and assumes you'll be using jQuery's .remove() to + // remove the element, but we don't use jQuery, so we need to + // blow away the element's data explicitly otherwise it will leak. + // This uses Velocity's internal jQuery compatible wrapper. + // See the bug at + // https://github.com/julianshapiro/velocity/issues/300 + // and the FAQ entry, "Preventing memory leaks when + // creating/destroying large numbers of elements" + // (https://github.com/julianshapiro/velocity/issues/47) + Velocity.Utilities.removeData(this.nodes[k]); } this.nodes[k] = node; }, diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 255f7c9b92..2f7a6ed8ec 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -103,6 +103,10 @@ module.exports = React.createClass({ return "https://matrix.org"; }, + getFallbackHsUrl: function() { + return this.props.config.fallback_hs_url; + }, + getCurrentIsUrl: function() { if (this.state.register_is_url) { return this.state.register_is_url; @@ -1183,6 +1187,7 @@ module.exports = React.createClass({ defaultIsUrl={this.props.config.default_is_url} customHsUrl={this.getCurrentHsUrl()} customIsUrl={this.getCurrentIsUrl()} + fallbackHsUrl={this.getFallbackHsUrl()} onForgotPasswordClick={this.onForgotPasswordClick} onLoginAsGuestClick={this.props.enableGuest && this.props.config && this.props.config.default_hs_url ? this._registerAsGuest.bind(this, true) : undefined} onCancelClick={ this.state.guestCreds ? this.onReturnToGuestClick : null } diff --git a/src/components/structures/login/Login.js b/src/components/structures/login/Login.js index d127c7ed78..aa0c42dc98 100644 --- a/src/components/structures/login/Login.js +++ b/src/components/structures/login/Login.js @@ -35,6 +35,10 @@ module.exports = React.createClass({displayName: 'Login', customIsUrl: React.PropTypes.string, defaultHsUrl: React.PropTypes.string, defaultIsUrl: React.PropTypes.string, + // Secondary HS which we try to log into if the user is using + // the default HS but login fails. Useful for migrating to a + // different home server without confusing users. + fallbackHsUrl: React.PropTypes.string, // login shouldn't know or care how registration is done. onRegisterClick: React.PropTypes.func.isRequired, @@ -105,7 +109,9 @@ module.exports = React.createClass({displayName: 'Login', hsUrl = hsUrl || this.state.enteredHomeserverUrl; isUrl = isUrl || this.state.enteredIdentityServerUrl; - var loginLogic = new Signup.Login(hsUrl, isUrl); + var fallbackHsUrl = hsUrl == this.props.defaultHsUrl ? this.props.fallbackHsUrl : null; + + var loginLogic = new Signup.Login(hsUrl, isUrl, fallbackHsUrl); this._loginLogic = loginLogic; loginLogic.getFlows().then(function(flows) { diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index 223eabdc36..a72608d329 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -117,7 +117,7 @@ module.exports = React.createClass({ else { var url = node.getAttribute("href"); var host = url.match(/^https?:\/\/(.*?)(\/|$)/)[1]; - if (node.textContent.trim().startsWith(host)) { + if (node.textContent.toLowerCase().trim().startsWith(host.toLowerCase())) { // it's a "foo.pl" style link return; }