mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-01-10 08:51:12 +00:00
8e89486fbc
All errors that lead to MTP request resending by default error handler now can be handled differently. For example inline bot requests are not being resent on 5XX error codes. + extensive use of auto keyword in MTP types handling.
637 lines
22 KiB
C++
637 lines
22 KiB
C++
/*
|
|
This file is part of Telegram Desktop,
|
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
|
|
|
Telegram Desktop is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
It is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
In addition, as a special exception, the copyright holders give permission
|
|
to link the code of portions of this program with the OpenSSL library.
|
|
|
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
|
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|
*/
|
|
#include "stdafx.h"
|
|
#include "lang.h"
|
|
|
|
#include "passcodebox.h"
|
|
#include "confirmbox.h"
|
|
#include "window.h"
|
|
|
|
#include "localstorage.h"
|
|
|
|
PasscodeBox::PasscodeBox(bool turningOff) : AbstractBox(st::boxWidth)
|
|
, _replacedBy(0)
|
|
, _turningOff(turningOff)
|
|
, _cloudPwd(false)
|
|
, _setRequest(0)
|
|
, _hasRecovery(false)
|
|
, _skipEmailWarning(false)
|
|
, _aboutHeight(0)
|
|
, _about(st::boxWidth - st::boxPadding.left() * 1.5)
|
|
, _saveButton(this, lang(_turningOff ? lng_passcode_remove_button : lng_settings_save), st::defaultBoxButton)
|
|
, _cancelButton(this, lang(lng_cancel), st::cancelBoxButton)
|
|
, _oldPasscode(this, st::defaultInputField, lang(lng_passcode_enter_old))
|
|
, _newPasscode(this, st::defaultInputField, lang(cHasPasscode() ? lng_passcode_enter_new : lng_passcode_enter_first))
|
|
, _reenterPasscode(this, st::defaultInputField, lang(lng_passcode_confirm_new))
|
|
, _passwordHint(this, st::defaultInputField, lang(lng_cloud_password_hint))
|
|
, _recoverEmail(this, st::defaultInputField, lang(lng_cloud_password_email))
|
|
, _recover(this, lang(lng_signin_recover)) {
|
|
init();
|
|
prepare();
|
|
}
|
|
|
|
PasscodeBox::PasscodeBox(const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff) : AbstractBox(st::boxWidth)
|
|
, _replacedBy(0)
|
|
, _turningOff(turningOff)
|
|
, _cloudPwd(true)
|
|
, _setRequest(0)
|
|
, _newSalt(newSalt)
|
|
, _curSalt(curSalt)
|
|
, _hasRecovery(hasRecovery)
|
|
, _skipEmailWarning(false)
|
|
, _aboutHeight(0)
|
|
, _about(st::boxWidth - st::boxPadding.left() * 1.5)
|
|
, _saveButton(this, lang(_turningOff ? lng_passcode_remove_button : lng_settings_save), st::defaultBoxButton)
|
|
, _cancelButton(this, lang(lng_cancel), st::cancelBoxButton)
|
|
, _oldPasscode(this, st::defaultInputField, lang(lng_cloud_password_enter_old))
|
|
, _newPasscode(this, st::defaultInputField, lang(curSalt.isEmpty() ? lng_cloud_password_enter_first : lng_cloud_password_enter_new))
|
|
, _reenterPasscode(this, st::defaultInputField, lang(lng_cloud_password_confirm_new))
|
|
, _passwordHint(this, st::defaultInputField, lang(curSalt.isEmpty() ? lng_cloud_password_hint : lng_cloud_password_change_hint))
|
|
, _recoverEmail(this, st::defaultInputField, lang(lng_cloud_password_email))
|
|
, _recover(this, lang(lng_signin_recover)) {
|
|
textstyleSet(&st::usernameTextStyle);
|
|
if (!hint.isEmpty()) _hintText.setText(st::normalFont, lng_signin_hint(lt_password_hint, hint));
|
|
textstyleRestore();
|
|
init();
|
|
prepare();
|
|
}
|
|
|
|
void PasscodeBox::init() {
|
|
setBlueTitle(true);
|
|
|
|
textstyleSet(&st::usernameTextStyle);
|
|
_about.setRichText(st::normalFont, lang(_cloudPwd ? lng_cloud_password_about : lng_passcode_about));
|
|
_aboutHeight = _about.countHeight(st::boxWidth - st::boxPadding.left() * 1.5);
|
|
textstyleRestore();
|
|
if (_turningOff) {
|
|
_oldPasscode.show();
|
|
_boxTitle = lang(_cloudPwd ? lng_cloud_password_remove : lng_passcode_remove);
|
|
setMaxHeight(st::boxTitleHeight + st::passcodePadding.top() + _oldPasscode.height() + st::passcodeSkip + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeSkip : 0) + _aboutHeight + st::passcodePadding.bottom() + st::boxButtonPadding.top() + _saveButton.height() + st::boxButtonPadding.bottom());
|
|
} else {
|
|
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode();
|
|
if (has) {
|
|
_oldPasscode.show();
|
|
_boxTitle = lang(_cloudPwd ? lng_cloud_password_change : lng_passcode_change);
|
|
setMaxHeight(st::boxTitleHeight + st::passcodePadding.top() + _oldPasscode.height() + st::passcodeSkip + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeSkip : 0) + _newPasscode.height() + st::contactSkip + _reenterPasscode.height() + st::passcodeSkip + (_cloudPwd ? _passwordHint.height() + st::contactSkip : 0) + _aboutHeight + st::passcodePadding.bottom() + st::boxButtonPadding.top() + _saveButton.height() + st::boxButtonPadding.bottom());
|
|
} else {
|
|
_oldPasscode.hide();
|
|
_boxTitle = lang(_cloudPwd ? lng_cloud_password_create : lng_passcode_create);
|
|
setMaxHeight(st::boxTitleHeight + st::passcodePadding.top() + _newPasscode.height() + st::contactSkip + _reenterPasscode.height() + st::passcodeSkip + (_cloudPwd ? _passwordHint.height() + st::contactSkip : 0) + _aboutHeight + (_cloudPwd ? st::contactSkip + _recoverEmail.height() + st::passcodeSkip : st::passcodePadding.bottom()) + st::boxButtonPadding.top() + _saveButton.height() + st::boxButtonPadding.bottom());
|
|
}
|
|
}
|
|
|
|
connect(&_saveButton, SIGNAL(clicked()), this, SLOT(onSave()));
|
|
connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onClose()));
|
|
|
|
connect(&_oldPasscode, SIGNAL(changed()), this, SLOT(onOldChanged()));
|
|
connect(&_newPasscode, SIGNAL(changed()), this, SLOT(onNewChanged()));
|
|
connect(&_reenterPasscode, SIGNAL(changed()), this, SLOT(onNewChanged()));
|
|
connect(&_passwordHint, SIGNAL(changed()), this, SLOT(onNewChanged()));
|
|
connect(&_recoverEmail, SIGNAL(changed()), this, SLOT(onEmailChanged()));
|
|
|
|
connect(&_oldPasscode, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
|
|
connect(&_newPasscode, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
|
|
connect(&_reenterPasscode, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
|
|
connect(&_passwordHint, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
|
|
connect(&_recoverEmail, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
|
|
|
|
connect(&_recover, SIGNAL(clicked()), this, SLOT(onRecoverByEmail()));
|
|
}
|
|
|
|
void PasscodeBox::hideAll() {
|
|
_oldPasscode.hide();
|
|
_newPasscode.hide();
|
|
_reenterPasscode.hide();
|
|
_passwordHint.hide();
|
|
_recoverEmail.hide();
|
|
_recover.hide();
|
|
_saveButton.hide();
|
|
_cancelButton.hide();
|
|
AbstractBox::hideAll();
|
|
}
|
|
|
|
void PasscodeBox::showAll() {
|
|
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode();
|
|
if (_turningOff) {
|
|
_oldPasscode.show();
|
|
if (_cloudPwd && _hasRecovery) {
|
|
_recover.show();
|
|
} else {
|
|
_recover.hide();
|
|
}
|
|
_passwordHint.hide();
|
|
_newPasscode.hide();
|
|
_reenterPasscode.hide();
|
|
} else {
|
|
if (has) {
|
|
_oldPasscode.show();
|
|
if (_cloudPwd && _hasRecovery) {
|
|
_recover.show();
|
|
} else {
|
|
_recover.hide();
|
|
}
|
|
} else {
|
|
_oldPasscode.hide();
|
|
_recover.hide();
|
|
}
|
|
_newPasscode.show();
|
|
_reenterPasscode.show();
|
|
if (_cloudPwd) {
|
|
_passwordHint.show();
|
|
} else {
|
|
_passwordHint.hide();
|
|
}
|
|
if (_cloudPwd && _curSalt.isEmpty()) {
|
|
_recoverEmail.show();
|
|
} else {
|
|
_recoverEmail.hide();
|
|
}
|
|
}
|
|
_saveButton.show();
|
|
_cancelButton.show();
|
|
AbstractBox::showAll();
|
|
}
|
|
|
|
void PasscodeBox::onSubmit() {
|
|
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode();
|
|
if (_oldPasscode.hasFocus()) {
|
|
if (_turningOff) {
|
|
onSave();
|
|
} else {
|
|
_newPasscode.setFocus();
|
|
}
|
|
} else if (_newPasscode.hasFocus()) {
|
|
_reenterPasscode.setFocus();
|
|
} else if (_reenterPasscode.hasFocus()) {
|
|
if (has && _oldPasscode.text().isEmpty()) {
|
|
_oldPasscode.setFocus();
|
|
_oldPasscode.showError();
|
|
} else if (_newPasscode.text().isEmpty()) {
|
|
_newPasscode.setFocus();
|
|
_newPasscode.showError();
|
|
} else if (_reenterPasscode.text().isEmpty()) {
|
|
_reenterPasscode.showError();
|
|
} else if (!_passwordHint.isHidden()) {
|
|
_passwordHint.setFocus();
|
|
} else {
|
|
onSave();
|
|
}
|
|
} else if (_passwordHint.hasFocus()) {
|
|
if (_recoverEmail.isHidden()) {
|
|
onSave();
|
|
} else {
|
|
_recoverEmail.setFocus();
|
|
}
|
|
} else if (_recoverEmail.hasFocus()) {
|
|
onSave();
|
|
}
|
|
}
|
|
|
|
void PasscodeBox::paintEvent(QPaintEvent *e) {
|
|
Painter p(this);
|
|
if (paint(p)) return;
|
|
|
|
paintTitle(p, _boxTitle);
|
|
|
|
textstyleSet(&st::usernameTextStyle);
|
|
|
|
int32 w = st::boxWidth - st::boxPadding.left() * 1.5;
|
|
int32 abouty = (_passwordHint.isHidden() ? (_reenterPasscode.isHidden() ? (_oldPasscode.y() + (_hasRecovery && !_hintText.isEmpty() ? st::passcodeSkip : 0)) : _reenterPasscode.y()) + st::passcodeSkip : _passwordHint.y() + st::contactSkip) + _oldPasscode.height();
|
|
p.setPen(st::black);
|
|
_about.drawLeft(p, st::boxPadding.left(), abouty, w, width());
|
|
|
|
if (!_hintText.isEmpty() && _oldError.isEmpty()) {
|
|
p.setPen(st::black->p);
|
|
_hintText.drawLeftElided(p, st::boxPadding.left(), _oldPasscode.y() + _oldPasscode.height() + ((st::passcodeSkip - st::normalFont->height) / 2), w, width(), 1, style::al_topleft);
|
|
}
|
|
|
|
if (!_oldError.isEmpty()) {
|
|
p.setPen(st::setErrColor->p);
|
|
p.drawText(QRect(st::boxPadding.left(), _oldPasscode.y() + _oldPasscode.height(), w, st::passcodeSkip), _oldError, style::al_left);
|
|
}
|
|
|
|
if (!_newError.isEmpty()) {
|
|
p.setPen(st::setErrColor->p);
|
|
p.drawText(QRect(st::boxPadding.left(), _reenterPasscode.y() + _reenterPasscode.height(), w, st::passcodeSkip), _newError, style::al_left);
|
|
}
|
|
|
|
if (!_emailError.isEmpty()) {
|
|
p.setPen(st::setErrColor->p);
|
|
p.drawText(QRect(st::boxPadding.left(), _recoverEmail.y() + _recoverEmail.height(), w, st::passcodeSkip), _emailError, style::al_left);
|
|
}
|
|
|
|
textstyleRestore();
|
|
}
|
|
|
|
void PasscodeBox::resizeEvent(QResizeEvent *e) {
|
|
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode();
|
|
int32 w = st::boxWidth - st::boxPadding.left() - st::boxPadding.right();
|
|
_oldPasscode.resize(w, _oldPasscode.height());
|
|
_oldPasscode.moveToLeft(st::boxPadding.left(), st::boxTitleHeight + st::passcodePadding.top());
|
|
_newPasscode.resize(w, _newPasscode.height());
|
|
_newPasscode.moveToLeft(st::boxPadding.left(), _oldPasscode.y() + ((_turningOff || has) ? (_oldPasscode.height() + st::passcodeSkip + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeSkip : 0)) : 0));
|
|
_reenterPasscode.resize(w, _reenterPasscode.height());
|
|
_reenterPasscode.moveToLeft(st::boxPadding.left(), _newPasscode.y() + _newPasscode.height() + st::contactSkip);
|
|
_passwordHint.resize(w, _passwordHint.height());
|
|
_passwordHint.moveToLeft(st::boxPadding.left(), _reenterPasscode.y() + _reenterPasscode.height() + st::passcodeSkip);
|
|
_recoverEmail.resize(w, _passwordHint.height());
|
|
_recoverEmail.moveToLeft(st::boxPadding.left(), _passwordHint.y() + _passwordHint.height() + st::contactSkip + _aboutHeight + st::contactSkip);
|
|
|
|
if (!_recover.isHidden()) {
|
|
_recover.moveToLeft(st::boxPadding.left(), _oldPasscode.y() + _oldPasscode.height() + (_hintText.isEmpty() ? ((st::passcodeSkip - _recover.height()) / 2) : st::passcodeSkip));
|
|
}
|
|
|
|
_saveButton.moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _saveButton.height());
|
|
_cancelButton.moveToRight(st::boxButtonPadding.right() + _saveButton.width() + st::boxButtonPadding.left(), _saveButton.y());
|
|
|
|
AbstractBox::resizeEvent(e);
|
|
}
|
|
|
|
void PasscodeBox::showDone() {
|
|
if (_skipEmailWarning && !_recoverEmail.isHidden()) {
|
|
_recoverEmail.setFocus();
|
|
} else if (_oldPasscode.isHidden()) {
|
|
_newPasscode.setFocus();
|
|
} else {
|
|
_oldPasscode.setFocus();
|
|
}
|
|
_skipEmailWarning = false;
|
|
}
|
|
|
|
void PasscodeBox::setPasswordDone(const MTPBool &result) {
|
|
_setRequest = 0;
|
|
emit reloadPassword();
|
|
ConfirmBox *box = new InformBox(lang(_reenterPasscode.isHidden() ? lng_cloud_password_removed : (_oldPasscode.isHidden() ? lng_cloud_password_was_set : lng_cloud_password_updated)));
|
|
Ui::showLayer(box);
|
|
}
|
|
|
|
bool PasscodeBox::setPasswordFail(const RPCError &error) {
|
|
if (MTP::isFloodError(error)) {
|
|
if (_oldPasscode.isHidden()) return false;
|
|
|
|
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose();
|
|
_setRequest = 0;
|
|
|
|
_oldPasscode.selectAll();
|
|
_oldPasscode.setFocus();
|
|
_oldPasscode.showError();
|
|
_oldError = lang(lng_flood_error);
|
|
if (_hasRecovery && _hintText.isEmpty()) {
|
|
_recover.hide();
|
|
}
|
|
update();
|
|
return true;
|
|
}
|
|
if (MTP::isDefaultHandledError(error)) return false;
|
|
|
|
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose();
|
|
_setRequest = 0;
|
|
QString err = error.type();
|
|
if (err == qstr("PASSWORD_HASH_INVALID")) {
|
|
if (_oldPasscode.isHidden()) {
|
|
emit reloadPassword();
|
|
onClose();
|
|
} else {
|
|
onBadOldPasscode();
|
|
}
|
|
} else if (err == qstr("NEW_PASSWORD_BAD")) {
|
|
_newPasscode.setFocus();
|
|
_newPasscode.showError();
|
|
_newError = lang(lng_cloud_password_bad);
|
|
update();
|
|
} else if (err == qstr("NEW_SALT_INVALID")) {
|
|
emit reloadPassword();
|
|
onClose();
|
|
} else if (err == qstr("EMAIL_INVALID")) {
|
|
_emailError = lang(lng_cloud_password_bad_email);
|
|
_recoverEmail.setFocus();
|
|
_recoverEmail.showError();
|
|
update();
|
|
} else if (err == qstr("EMAIL_UNCONFIRMED")) {
|
|
Ui::showLayer(new InformBox(lang(lng_cloud_password_almost)));
|
|
emit reloadPassword();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void PasscodeBox::onSave(bool force) {
|
|
if (_setRequest) return;
|
|
|
|
QString old = _oldPasscode.text(), pwd = _newPasscode.text(), conf = _reenterPasscode.text();
|
|
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode();
|
|
if (!_cloudPwd && (_turningOff || has)) {
|
|
if (!passcodeCanTry()) {
|
|
_oldError = lang(lng_flood_error);
|
|
_oldPasscode.setFocus();
|
|
_oldPasscode.showError();
|
|
update();
|
|
return;
|
|
}
|
|
|
|
if (Local::checkPasscode(old.toUtf8())) {
|
|
cSetPasscodeBadTries(0);
|
|
if (_turningOff) pwd = conf = QString();
|
|
} else {
|
|
cSetPasscodeBadTries(cPasscodeBadTries() + 1);
|
|
cSetPasscodeLastTry(getms(true));
|
|
onBadOldPasscode();
|
|
return;
|
|
}
|
|
}
|
|
if (!_turningOff && pwd.isEmpty()) {
|
|
_newPasscode.setFocus();
|
|
_newPasscode.showError();
|
|
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose();
|
|
return;
|
|
}
|
|
if (pwd != conf) {
|
|
_reenterPasscode.selectAll();
|
|
_reenterPasscode.setFocus();
|
|
_reenterPasscode.showError();
|
|
if (!conf.isEmpty()) {
|
|
_newError = lang(_cloudPwd ? lng_cloud_password_differ : lng_passcode_differ);
|
|
update();
|
|
}
|
|
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose();
|
|
} else if (!_turningOff && has && old == pwd) {
|
|
_newPasscode.setFocus();
|
|
_newPasscode.showError();
|
|
_newError = lang(_cloudPwd ? lng_cloud_password_is_same : lng_passcode_is_same);
|
|
update();
|
|
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose();
|
|
} else if (_cloudPwd) {
|
|
QString hint = _passwordHint.getLastText(), email = _recoverEmail.getLastText().trimmed();
|
|
if (_cloudPwd && pwd == hint && !_passwordHint.isHidden() && !_newPasscode.isHidden()) {
|
|
_newPasscode.setFocus();
|
|
_newPasscode.showError();
|
|
_newError = lang(lng_cloud_password_bad);
|
|
update();
|
|
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose();
|
|
return;
|
|
}
|
|
if (!_recoverEmail.isHidden() && email.isEmpty() && !force) {
|
|
_skipEmailWarning = true;
|
|
_replacedBy = new ConfirmBox(lang(lng_cloud_password_about_recover), lang(lng_cloud_password_skip_email), st::attentionBoxButton);
|
|
connect(_replacedBy, SIGNAL(confirmed()), this, SLOT(onForceNoMail()));
|
|
connect(_replacedBy, SIGNAL(destroyed(QObject*)), this, SLOT(onBoxDestroyed(QObject*)));
|
|
Ui::showLayer(_replacedBy, KeepOtherLayers);
|
|
} else {
|
|
QByteArray newPasswordData = pwd.isEmpty() ? QByteArray() : (_newSalt + pwd.toUtf8() + _newSalt);
|
|
QByteArray newPasswordHash = pwd.isEmpty() ? QByteArray() : QByteArray(32, Qt::Uninitialized);
|
|
if (pwd.isEmpty()) {
|
|
hint = QString();
|
|
email = QString();
|
|
} else {
|
|
hashSha256(newPasswordData.constData(), newPasswordData.size(), newPasswordHash.data());
|
|
}
|
|
QByteArray oldPasswordData = _oldPasscode.isHidden() ? QByteArray() : (_curSalt + old.toUtf8() + _curSalt);
|
|
QByteArray oldPasswordHash = _oldPasscode.isHidden() ? QByteArray() : QByteArray(32, Qt::Uninitialized);
|
|
if (!_oldPasscode.isHidden()) {
|
|
hashSha256(oldPasswordData.constData(), oldPasswordData.size(), oldPasswordHash.data());
|
|
}
|
|
MTPDaccount_passwordInputSettings::Flags flags = MTPDaccount_passwordInputSettings::Flag::f_new_salt | MTPDaccount_passwordInputSettings::Flag::f_new_password_hash | MTPDaccount_passwordInputSettings::Flag::f_hint;
|
|
if (_oldPasscode.isHidden() || _newPasscode.isHidden()) {
|
|
flags |= MTPDaccount_passwordInputSettings::Flag::f_email;
|
|
}
|
|
MTPaccount_PasswordInputSettings settings(MTP_account_passwordInputSettings(MTP_flags(flags), MTP_bytes(_newSalt), MTP_bytes(newPasswordHash), MTP_string(hint), MTP_string(email)));
|
|
_setRequest = MTP::send(MTPaccount_UpdatePasswordSettings(MTP_bytes(oldPasswordHash), settings), rpcDone(&PasscodeBox::setPasswordDone), rpcFail(&PasscodeBox::setPasswordFail));
|
|
}
|
|
} else {
|
|
cSetPasscodeBadTries(0);
|
|
Local::setPasscode(pwd.toUtf8());
|
|
App::wnd()->checkAutoLock();
|
|
App::wnd()->getTitle()->showUpdateBtn();
|
|
emit closed();
|
|
}
|
|
}
|
|
|
|
void PasscodeBox::onBadOldPasscode() {
|
|
_oldPasscode.selectAll();
|
|
_oldPasscode.setFocus();
|
|
_oldPasscode.showError();
|
|
_oldError = lang(_cloudPwd ? lng_cloud_password_wrong : lng_passcode_wrong);
|
|
if (_hasRecovery && _hintText.isEmpty()) {
|
|
_recover.hide();
|
|
}
|
|
update();
|
|
}
|
|
|
|
void PasscodeBox::onOldChanged() {
|
|
if (!_oldError.isEmpty()) {
|
|
_oldError = QString();
|
|
if (_hasRecovery && _hintText.isEmpty()) {
|
|
_recover.show();
|
|
}
|
|
update();
|
|
}
|
|
}
|
|
|
|
void PasscodeBox::onNewChanged() {
|
|
if (!_newError.isEmpty()) {
|
|
_newError = QString();
|
|
update();
|
|
}
|
|
}
|
|
|
|
void PasscodeBox::onEmailChanged() {
|
|
if (!_emailError.isEmpty()) {
|
|
_emailError = QString();
|
|
update();
|
|
}
|
|
}
|
|
|
|
void PasscodeBox::onForceNoMail() {
|
|
onSave(true);
|
|
}
|
|
|
|
void PasscodeBox::onBoxDestroyed(QObject *obj) {
|
|
if (obj == _replacedBy) {
|
|
_replacedBy = 0;
|
|
}
|
|
}
|
|
|
|
void PasscodeBox::onRecoverByEmail() {
|
|
if (_pattern.isEmpty()) {
|
|
_pattern = "-";
|
|
MTP::send(MTPauth_RequestPasswordRecovery(), rpcDone(&PasscodeBox::recoverStarted), rpcFail(&PasscodeBox::recoverStartFail));
|
|
} else {
|
|
recover();
|
|
}
|
|
}
|
|
|
|
void PasscodeBox::onRecoverExpired() {
|
|
_pattern = QString();
|
|
}
|
|
|
|
void PasscodeBox::recover() {
|
|
if (_pattern == "-") return;
|
|
|
|
_replacedBy = new RecoverBox(_pattern);
|
|
connect(_replacedBy, SIGNAL(reloadPassword()), this, SIGNAL(reloadPassword()));
|
|
connect(_replacedBy, SIGNAL(recoveryExpired()), this, SLOT(onRecoverExpired()));
|
|
connect(_replacedBy, SIGNAL(destroyed(QObject*)), this, SLOT(onBoxDestroyed(QObject*)));
|
|
Ui::showLayer(_replacedBy, KeepOtherLayers);
|
|
}
|
|
|
|
void PasscodeBox::recoverStarted(const MTPauth_PasswordRecovery &result) {
|
|
_pattern = qs(result.c_auth_passwordRecovery().vemail_pattern);
|
|
recover();
|
|
}
|
|
|
|
bool PasscodeBox::recoverStartFail(const RPCError &error) {
|
|
if (MTP::isDefaultHandledError(error)) return false;
|
|
|
|
_pattern = QString();
|
|
onClose();
|
|
return true;
|
|
}
|
|
|
|
RecoverBox::RecoverBox(const QString &pattern) : AbstractBox(st::boxWidth)
|
|
, _submitRequest(0)
|
|
, _pattern(st::normalFont->elided(lng_signin_recover_hint(lt_recover_email, pattern), st::boxWidth - st::boxPadding.left() * 1.5))
|
|
, _saveButton(this, lang(lng_passcode_submit), st::defaultBoxButton)
|
|
, _cancelButton(this, lang(lng_cancel), st::cancelBoxButton)
|
|
, _recoverCode(this, st::defaultInputField, lang(lng_signin_code)) {
|
|
setBlueTitle(true);
|
|
|
|
setMaxHeight(st::boxTitleHeight + st::passcodePadding.top() + st::passcodeSkip + _recoverCode.height() + st::passcodeSkip + st::passcodePadding.bottom() + st::boxButtonPadding.top() + _saveButton.height() + st::boxButtonPadding.bottom());
|
|
|
|
connect(&_saveButton, SIGNAL(clicked()), this, SLOT(onSubmit()));
|
|
connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onClose()));
|
|
|
|
connect(&_recoverCode, SIGNAL(changed()), this, SLOT(onCodeChanged()));
|
|
connect(&_recoverCode, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
|
|
|
|
prepare();
|
|
}
|
|
|
|
void RecoverBox::hideAll() {
|
|
_recoverCode.hide();
|
|
_saveButton.hide();
|
|
_cancelButton.hide();
|
|
AbstractBox::hideAll();
|
|
}
|
|
|
|
void RecoverBox::showAll() {
|
|
_recoverCode.show();
|
|
_saveButton.show();
|
|
_cancelButton.show();
|
|
AbstractBox::showAll();
|
|
}
|
|
|
|
void RecoverBox::paintEvent(QPaintEvent *e) {
|
|
Painter p(this);
|
|
if (paint(p)) return;
|
|
|
|
paintTitle(p, lang(lng_signin_recover_title));
|
|
|
|
p.setFont(st::normalFont);
|
|
p.setPen(st::black);
|
|
int32 w = st::boxWidth - st::boxPadding.left() * 1.5;
|
|
p.drawText(QRect(st::boxPadding.left(), _recoverCode.y() - st::passcodeSkip - st::passcodePadding.top(), w, st::passcodePadding.top() + st::passcodeSkip), _pattern, style::al_left);
|
|
|
|
if (!_error.isEmpty()) {
|
|
p.setPen(st::setErrColor->p);
|
|
p.drawText(QRect(st::boxPadding.left(), _recoverCode.y() + _recoverCode.height(), w, st::passcodeSkip), _error, style::al_left);
|
|
}
|
|
}
|
|
|
|
void RecoverBox::resizeEvent(QResizeEvent *e) {
|
|
_recoverCode.resize(st::boxWidth - st::boxPadding.left() - st::boxPadding.right(), _recoverCode.height());
|
|
_recoverCode.moveToLeft(st::boxPadding.left(), st::boxTitleHeight + st::passcodePadding.top() + st::passcodeSkip);
|
|
|
|
_saveButton.moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _saveButton.height());
|
|
_cancelButton.moveToRight(st::boxButtonPadding.right() + _saveButton.width() + st::boxButtonPadding.left(), _saveButton.y());
|
|
|
|
AbstractBox::resizeEvent(e);
|
|
}
|
|
|
|
void RecoverBox::showDone() {
|
|
_recoverCode.setFocus();
|
|
}
|
|
|
|
void RecoverBox::onSubmit() {
|
|
if (_submitRequest) return;
|
|
|
|
QString code = _recoverCode.getLastText().trimmed();
|
|
if (code.isEmpty()) {
|
|
_recoverCode.setFocus();
|
|
_recoverCode.showError();
|
|
return;
|
|
}
|
|
|
|
_submitRequest = MTP::send(MTPauth_RecoverPassword(MTP_string(code)), rpcDone(&RecoverBox::codeSubmitDone, true), rpcFail(&RecoverBox::codeSubmitFail));
|
|
}
|
|
|
|
void RecoverBox::onCodeChanged() {
|
|
_error = QString();
|
|
update();
|
|
}
|
|
|
|
void RecoverBox::codeSubmitDone(bool recover, const MTPauth_Authorization &result) {
|
|
_submitRequest = 0;
|
|
|
|
emit reloadPassword();
|
|
Ui::showLayer(new InformBox(lang(lng_cloud_password_removed)));
|
|
}
|
|
|
|
bool RecoverBox::codeSubmitFail(const RPCError &error) {
|
|
if (MTP::isFloodError(error)) {
|
|
_submitRequest = 0;
|
|
_error = lang(lng_flood_error);
|
|
update();
|
|
_recoverCode.showError();
|
|
return true;
|
|
}
|
|
if (MTP::isDefaultHandledError(error)) return false;
|
|
|
|
_submitRequest = 0;
|
|
|
|
const QString &err = error.type();
|
|
if (err == qstr("PASSWORD_EMPTY")) {
|
|
emit reloadPassword();
|
|
Ui::showLayer(new InformBox(lang(lng_cloud_password_removed)));
|
|
return true;
|
|
} else if (err == qstr("PASSWORD_RECOVERY_NA")) {
|
|
onClose();
|
|
return true;
|
|
} else if (err == qstr("PASSWORD_RECOVERY_EXPIRED")) {
|
|
emit recoveryExpired();
|
|
onClose();
|
|
return true;
|
|
} else if (err == qstr("CODE_INVALID")) {
|
|
_error = lang(lng_signin_wrong_code);
|
|
update();
|
|
_recoverCode.selectAll();
|
|
_recoverCode.setFocus();
|
|
_recoverCode.showError();
|
|
return true;
|
|
}
|
|
if (cDebug()) { // internal server error
|
|
_error = err + ": " + error.description();
|
|
} else {
|
|
_error = lang(lng_server_error);
|
|
}
|
|
update();
|
|
_recoverCode.setFocus();
|
|
return false;
|
|
}
|