2018-03-18 12:51:14 +04:00
|
|
|
/*
|
|
|
|
This file is part of Telegram Desktop,
|
|
|
|
the official desktop application for the Telegram messaging service.
|
|
|
|
|
|
|
|
For license and copyright information please follow this link:
|
|
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "mtproto/sender.h"
|
2018-03-25 15:37:57 +04:00
|
|
|
#include "base/weak_ptr.h"
|
2018-03-18 12:51:14 +04:00
|
|
|
|
2018-03-21 08:35:32 +04:00
|
|
|
class BoxContent;
|
|
|
|
|
2018-03-25 15:37:57 +04:00
|
|
|
namespace Storage {
|
2018-03-29 00:40:42 +04:00
|
|
|
struct UploadSecureDone;
|
|
|
|
struct UploadSecureProgress;
|
2018-03-25 15:37:57 +04:00
|
|
|
} // namespace Storage
|
|
|
|
|
2018-03-18 12:51:14 +04:00
|
|
|
namespace Window {
|
|
|
|
class Controller;
|
|
|
|
} // namespace Window
|
|
|
|
|
|
|
|
namespace Passport {
|
|
|
|
|
2018-03-29 23:49:31 +04:00
|
|
|
class ViewController;
|
|
|
|
|
2018-03-18 12:51:14 +04:00
|
|
|
struct FormRequest {
|
|
|
|
FormRequest(
|
|
|
|
UserId botId,
|
2018-03-27 17:00:13 +04:00
|
|
|
const QString &scope,
|
2018-03-18 12:51:14 +04:00
|
|
|
const QString &callbackUrl,
|
|
|
|
const QString &publicKey);
|
|
|
|
|
|
|
|
UserId botId;
|
2018-03-27 17:00:13 +04:00
|
|
|
QString scope;
|
2018-03-18 12:51:14 +04:00
|
|
|
QString callbackUrl;
|
|
|
|
QString publicKey;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2018-03-29 23:49:31 +04:00
|
|
|
struct UploadScanData {
|
|
|
|
FullMsgId fullId;
|
|
|
|
uint64 fileId = 0;
|
|
|
|
int partsCount = 0;
|
|
|
|
QByteArray md5checksum;
|
|
|
|
bytes::vector hash;
|
|
|
|
bytes::vector bytes;
|
|
|
|
|
|
|
|
int offset = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
class UploadScanDataPointer {
|
|
|
|
public:
|
|
|
|
UploadScanDataPointer(std::unique_ptr<UploadScanData> &&value);
|
|
|
|
UploadScanDataPointer(UploadScanDataPointer &&other);
|
|
|
|
UploadScanDataPointer &operator=(UploadScanDataPointer &&other);
|
|
|
|
~UploadScanDataPointer();
|
|
|
|
|
|
|
|
UploadScanData *get() const;
|
|
|
|
operator UploadScanData*() const;
|
|
|
|
explicit operator bool() const;
|
|
|
|
UploadScanData *operator->() const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::unique_ptr<UploadScanData> _value;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
struct File {
|
|
|
|
uint64 id = 0;
|
|
|
|
uint64 accessHash = 0;
|
|
|
|
int32 size = 0;
|
|
|
|
int32 dcId = 0;
|
|
|
|
TimeId date = 0;
|
|
|
|
bytes::vector hash;
|
|
|
|
bytes::vector secret;
|
|
|
|
bytes::vector encryptedSecret;
|
|
|
|
|
|
|
|
int downloadOffset = 0;
|
|
|
|
QImage image;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct EditFile {
|
|
|
|
EditFile(
|
|
|
|
const File &fields,
|
|
|
|
std::unique_ptr<UploadScanData> &&uploadData);
|
|
|
|
|
|
|
|
File fields;
|
|
|
|
UploadScanDataPointer uploadData;
|
|
|
|
std::shared_ptr<bool> guard;
|
|
|
|
bool deleted = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Verification {
|
|
|
|
TimeId date;
|
|
|
|
};
|
|
|
|
|
2018-03-31 05:45:40 +04:00
|
|
|
struct ValueMap {
|
|
|
|
std::map<QString, QString> fields;
|
|
|
|
};
|
|
|
|
|
2018-03-29 23:49:31 +04:00
|
|
|
struct ValueData {
|
|
|
|
QByteArray original;
|
2018-03-31 05:45:40 +04:00
|
|
|
ValueMap parsed;
|
2018-03-29 23:49:31 +04:00
|
|
|
bytes::vector hash;
|
|
|
|
bytes::vector secret;
|
|
|
|
bytes::vector encryptedSecret;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Value {
|
|
|
|
enum class Type {
|
|
|
|
Identity,
|
|
|
|
Address,
|
|
|
|
Phone,
|
|
|
|
Email,
|
|
|
|
};
|
|
|
|
|
|
|
|
explicit Value(Type type);
|
|
|
|
Value(Value &&other) = default;
|
|
|
|
Value &operator=(Value &&other) = default;
|
|
|
|
|
|
|
|
Type type;
|
|
|
|
ValueData data;
|
|
|
|
std::vector<File> files;
|
|
|
|
std::vector<EditFile> filesInEdit;
|
|
|
|
base::optional<Verification> verification;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Form {
|
|
|
|
std::vector<Value> rows;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct PasswordSettings {
|
|
|
|
bytes::vector salt;
|
|
|
|
bytes::vector newSalt;
|
|
|
|
bytes::vector newSecureSalt;
|
|
|
|
QString hint;
|
|
|
|
QString unconfirmedPattern;
|
|
|
|
QString confirmedEmail;
|
|
|
|
bool hasRecovery = false;
|
|
|
|
};
|
2018-03-21 08:35:32 +04:00
|
|
|
|
2018-03-25 15:37:57 +04:00
|
|
|
struct FileKey {
|
|
|
|
uint64 id = 0;
|
|
|
|
int32 dcId = 0;
|
|
|
|
|
|
|
|
inline bool operator==(const FileKey &other) const {
|
|
|
|
return (id == other.id) && (dcId == other.dcId);
|
|
|
|
}
|
|
|
|
inline bool operator!=(const FileKey &other) const {
|
|
|
|
return !(*this == other);
|
|
|
|
}
|
|
|
|
inline bool operator<(const FileKey &other) const {
|
|
|
|
return (id < other.id) || ((id == other.id) && (dcId < other.dcId));
|
|
|
|
}
|
|
|
|
inline bool operator>(const FileKey &other) const {
|
|
|
|
return (other < *this);
|
|
|
|
}
|
|
|
|
inline bool operator<=(const FileKey &other) const {
|
|
|
|
return !(other < *this);
|
|
|
|
}
|
|
|
|
inline bool operator>=(const FileKey &other) const {
|
|
|
|
return !(*this < other);
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
class FormController : private MTP::Sender, public base::has_weak_ptr {
|
2018-03-18 12:51:14 +04:00
|
|
|
public:
|
|
|
|
FormController(
|
|
|
|
not_null<Window::Controller*> controller,
|
|
|
|
const FormRequest &request);
|
|
|
|
|
|
|
|
void show();
|
2018-03-29 23:49:31 +04:00
|
|
|
UserData *bot() const;
|
2018-03-18 12:51:14 +04:00
|
|
|
|
2018-03-19 20:22:27 +04:00
|
|
|
void submitPassword(const QString &password);
|
|
|
|
rpl::producer<QString> passwordError() const;
|
|
|
|
QString passwordHint() const;
|
|
|
|
|
2018-03-29 18:44:34 +04:00
|
|
|
void uploadScan(int valueIndex, QByteArray &&content);
|
|
|
|
void deleteScan(int valueIndex, int fileIndex);
|
2018-03-31 05:45:40 +04:00
|
|
|
void restoreScan(int valueIndex, int fileIndex);
|
2018-03-25 15:37:57 +04:00
|
|
|
|
2018-03-19 20:22:27 +04:00
|
|
|
rpl::producer<> secretReadyEvents() const;
|
|
|
|
|
|
|
|
QString defaultEmail() const;
|
|
|
|
QString defaultPhoneNumber() const;
|
|
|
|
|
2018-03-29 23:49:31 +04:00
|
|
|
rpl::producer<not_null<const EditFile*>> scanUpdated() const;
|
|
|
|
|
|
|
|
void enumerateRows(base::lambda<void(const Value &value)> callback);
|
|
|
|
not_null<Value*> startValueEdit(int index);
|
|
|
|
void cancelValueEdit(int index);
|
|
|
|
void saveValueEdit(int index);
|
2018-03-21 08:35:32 +04:00
|
|
|
|
2018-03-31 05:45:40 +04:00
|
|
|
void cancel();
|
|
|
|
|
|
|
|
rpl::lifetime &lifetime();
|
2018-03-19 20:22:27 +04:00
|
|
|
|
2018-03-25 15:37:57 +04:00
|
|
|
~FormController();
|
|
|
|
|
2018-03-18 12:51:14 +04:00
|
|
|
private:
|
2018-03-25 15:37:57 +04:00
|
|
|
EditFile *findEditFile(const FullMsgId &fullId);
|
2018-03-29 00:40:42 +04:00
|
|
|
EditFile *findEditFile(const FileKey &key);
|
2018-03-29 18:44:34 +04:00
|
|
|
std::pair<Value*, File*> findFile(const FileKey &key);
|
2018-03-18 12:51:14 +04:00
|
|
|
|
|
|
|
void requestForm();
|
|
|
|
void requestPassword();
|
|
|
|
|
|
|
|
void formDone(const MTPaccount_AuthorizationForm &result);
|
|
|
|
void formFail(const RPCError &error);
|
|
|
|
void parseForm(const MTPaccount_AuthorizationForm &result);
|
|
|
|
void showForm();
|
2018-03-29 18:44:34 +04:00
|
|
|
Value parseValue(const MTPSecureValue &value) const;
|
2018-03-27 17:00:13 +04:00
|
|
|
template <typename DataType>
|
2018-03-29 18:44:34 +04:00
|
|
|
Value parseEncryptedValue(
|
|
|
|
Value::Type type,
|
2018-03-27 17:00:13 +04:00
|
|
|
const DataType &data) const;
|
|
|
|
template <typename DataType>
|
2018-03-29 18:44:34 +04:00
|
|
|
Value parsePlainTextValue(
|
|
|
|
Value::Type type,
|
|
|
|
const QByteArray &text,
|
2018-03-27 17:00:13 +04:00
|
|
|
const DataType &data) const;
|
|
|
|
Verification parseVerified(const MTPSecureValueVerified &data) const;
|
2018-03-29 00:40:42 +04:00
|
|
|
std::vector<File> parseFiles(
|
|
|
|
const QVector<MTPSecureFile> &data,
|
|
|
|
const std::vector<EditFile> &editData = {}) const;
|
2018-03-29 18:44:34 +04:00
|
|
|
void fillDownloadedFile(
|
|
|
|
File &destination,
|
|
|
|
const std::vector<EditFile> &source) const;
|
2018-03-18 12:51:14 +04:00
|
|
|
|
|
|
|
void passwordDone(const MTPaccount_Password &result);
|
|
|
|
void passwordFail(const RPCError &error);
|
2018-03-19 20:22:27 +04:00
|
|
|
void parsePassword(const MTPDaccount_noPassword &settings);
|
|
|
|
void parsePassword(const MTPDaccount_password &settings);
|
2018-03-27 17:00:13 +04:00
|
|
|
bytes::vector passwordHashForAuth(bytes::const_span password) const;
|
|
|
|
void validateSecureSecret(
|
|
|
|
bytes::const_span salt,
|
|
|
|
bytes::const_span encryptedSecret,
|
|
|
|
bytes::const_span password);
|
2018-03-29 18:44:34 +04:00
|
|
|
void decryptValues();
|
|
|
|
void decryptValue(Value &value);
|
|
|
|
bool validateValueSecrets(Value &value);
|
|
|
|
void resetValue(Value &value);
|
2018-03-18 12:51:14 +04:00
|
|
|
|
2018-03-29 00:40:42 +04:00
|
|
|
void loadFiles(std::vector<File> &files);
|
|
|
|
void fileLoadDone(FileKey key, const QByteArray &bytes);
|
|
|
|
void fileLoadProgress(FileKey key, int offset);
|
|
|
|
void fileLoadFail(FileKey key);
|
2018-03-27 17:00:13 +04:00
|
|
|
void generateSecret(bytes::const_span password);
|
2018-03-21 08:35:32 +04:00
|
|
|
|
2018-03-25 15:37:57 +04:00
|
|
|
void subscribeToUploader();
|
2018-03-29 00:40:42 +04:00
|
|
|
void encryptScan(
|
2018-03-29 18:44:34 +04:00
|
|
|
int valueIndex,
|
2018-03-29 00:40:42 +04:00
|
|
|
int fileIndex,
|
|
|
|
QByteArray &&content);
|
2018-03-29 18:44:34 +04:00
|
|
|
void uploadEncryptedScan(
|
|
|
|
int valueIndex,
|
|
|
|
int fileIndex,
|
|
|
|
UploadScanData &&data);
|
2018-03-29 00:40:42 +04:00
|
|
|
void scanUploadDone(const Storage::UploadSecureDone &data);
|
|
|
|
void scanUploadProgress(const Storage::UploadSecureProgress &data);
|
|
|
|
void scanUploadFail(const FullMsgId &fullId);
|
2018-03-31 05:45:40 +04:00
|
|
|
void scanDeleteRestore(int valueIndex, int fileIndex, bool deleted);
|
2018-03-29 23:49:31 +04:00
|
|
|
|
|
|
|
bool isEncryptedValue(Value::Type type) const;
|
|
|
|
void saveEncryptedValue(int index);
|
|
|
|
void savePlainTextValue(int index);
|
|
|
|
void sendSaveRequest(int index, const MTPInputSecureValue &value);
|
2018-03-25 15:37:57 +04:00
|
|
|
|
2018-03-18 12:51:14 +04:00
|
|
|
not_null<Window::Controller*> _controller;
|
|
|
|
FormRequest _request;
|
|
|
|
UserData *_bot = nullptr;
|
|
|
|
|
2018-03-19 20:22:27 +04:00
|
|
|
mtpRequestId _formRequestId = 0;
|
|
|
|
mtpRequestId _passwordRequestId = 0;
|
|
|
|
mtpRequestId _passwordCheckRequestId = 0;
|
|
|
|
|
|
|
|
PasswordSettings _password;
|
2018-03-18 12:51:14 +04:00
|
|
|
Form _form;
|
2018-03-31 05:45:40 +04:00
|
|
|
bool _cancelled = false;
|
2018-03-25 15:37:57 +04:00
|
|
|
std::map<FileKey, std::unique_ptr<mtpFileLoader>> _fileLoaders;
|
2018-03-29 23:49:31 +04:00
|
|
|
|
|
|
|
rpl::event_stream<not_null<const EditFile*>> _scanUpdated;
|
2018-03-18 12:51:14 +04:00
|
|
|
|
2018-03-27 16:16:00 +04:00
|
|
|
bytes::vector _secret;
|
2018-03-29 18:44:34 +04:00
|
|
|
uint64 _secretId = 0;
|
2018-03-25 15:37:57 +04:00
|
|
|
std::vector<base::lambda<void()>> _secretCallbacks;
|
2018-03-21 08:35:32 +04:00
|
|
|
mtpRequestId _saveSecretRequestId = 0;
|
2018-03-19 20:22:27 +04:00
|
|
|
rpl::event_stream<> _secretReady;
|
|
|
|
rpl::event_stream<QString> _passwordError;
|
|
|
|
|
2018-03-25 15:37:57 +04:00
|
|
|
rpl::lifetime _uploaderSubscriptions;
|
2018-03-29 23:49:31 +04:00
|
|
|
rpl::lifetime _lifetime;
|
2018-03-25 15:37:57 +04:00
|
|
|
|
2018-03-31 05:45:40 +04:00
|
|
|
std::unique_ptr<ViewController> _view;
|
|
|
|
|
2018-03-18 12:51:14 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace Passport
|