Update layer to 85.

GitOrigin-RevId: 0a32bd0287e3d09dd484c8dbe230f29b92d19771
This commit is contained in:
levlam 2018-08-10 19:39:48 +03:00
parent 00fabb8f97
commit 3d05d44be8
11 changed files with 267 additions and 64 deletions

View File

@ -873,17 +873,17 @@ passportElementTypeEmailAddress = PassportElementType;
//@description Represents a date according to the Gregorian calendar @day Day of the month, 1-31 @month Month, 1-12 @year Year, 1-9999
date day:int32 month:int32 year:int32 = Date;
//@description Contains the user's personal details @first_name First name of the user; 1-255 characters @last_name Last name of the user; 1-255 characters @birthdate Birthdate of the user
//@description Contains the user's personal details @first_name First name of the user; 1-255 characters @middle_name Middle name of the user; 0-255 characters @last_name Last name of the user; 1-255 characters @birthdate Birthdate of the user
//@gender Gender of the user, "male" or "female" @country_code A two-letter ISO 3166-1 alpha-2 country code for the user's country @residence_country_code A two-letter ISO 3166-1 alpha-2 country code for the user's residence country
personalDetails first_name:string last_name:string birthdate:date gender:string country_code:string residence_country_code:string = PersonalDetails;
personalDetails first_name:string middle_name:string last_name:string birthdate:date gender:string country_code:string residence_country_code:string = PersonalDetails;
//@description An identity document @number Document number; 1-24 characters @expiry_date Document expiry date; may be null @front_side Front side of the document
//@reverse_side Reverse side of the document; only for driver license and identity card @selfie Selfie with the document; may be null
identityDocument number:string expiry_date:date front_side:datedFile reverse_side:datedFile selfie:datedFile = IdentityDocument;
//@reverse_side Reverse side of the document; only for driver license and identity card @selfie Selfie with the document; may be null @translations List of files with the document translation
identityDocument number:string expiry_date:date front_side:datedFile reverse_side:datedFile selfie:datedFile translations:vector<datedFile> = IdentityDocument;
//@description An identity document to be saved @number Document number; 1-24 characters @expiry_date Document expiry date, if available @front_side Front side of the document
//@reverse_side Reverse side of the document; only for driver license and identity card @selfie Selfie with the document, if available
inputIdentityDocument number:string expiry_date:date front_side:InputFile reverse_side:InputFile selfie:InputFile = InputIdentityDocument;
//@reverse_side Reverse side of the document; only for driver license and identity card @selfie Selfie with the document, if available @translations List of files with the document translation
inputIdentityDocument number:string expiry_date:date front_side:InputFile reverse_side:InputFile selfie:InputFile translations:vector<InputFile> = InputIdentityDocument;
//@class PassportElement @description Contains information about a Telegram Passport element
@ -976,6 +976,9 @@ passportElements elements:vector<PassportElement> = PassportElements;
//@class PassportElementErrorSource @description Contains the description of an error in a Telegram Passport element
//@description The element contains an error in an unspecified place. The error will be considered resolved when anything changes
passportElementErrorSourceUnspecified = PassportElementErrorSource;
//@description One of the data fields contains an error. The error will be considered resolved when the value of the field changes @field_name Field name
passportElementErrorSourceDataField field_name:string = PassportElementErrorSource;
@ -988,6 +991,12 @@ passportElementErrorSourceReverseSide = PassportElementErrorSource;
//@description The selfie with the document contains an error. The error will be considered resolved when the file with the selfie changes
passportElementErrorSourceSelfie = PassportElementErrorSource;
//@description The translation of the document contains an error. The error will be considered resolved when the file with the translation changes
passportElementErrorSourceTranslation = PassportElementErrorSource;
//@description The list of translations of the document contains an error. The error will be considered resolved when the list of translations changes
passportElementErrorSourceTranslations = PassportElementErrorSource;
//@description The file contains an error. The error will be considered resolved when the file changes
passportElementErrorSourceFile = PassportElementErrorSource;
@ -1001,20 +1010,24 @@ passportElementError type:PassportElementType message:string source:PassportElem
//@description Contains information about a Telegram Passport authorization form that was requested @id Unique identifier of the authorization form
//@required_types Telegram Passport element types that need to be provided to complete the form. If the user has more than one identity document or proof of address document, any one of each can be chosen
//@elements Already available Telegram Passport elements @errors Errors in the elements that is already available @is_selfie_required True, if a selfie is required with the identity document @privacy_policy_url URL for the privacy policy of the service; can be empty
passportAuthorizationForm id:int32 required_types:vector<PassportElementType> elements:vector<PassportElement> errors:vector<passportElementError> is_selfie_required:Bool privacy_policy_url:string = PassportAuthorizationForm;
//@elements Already available Telegram Passport elements @errors Errors in the elements that is already available @is_selfie_required True, if a selfie is required with the identity document
//@is_translation_required True, if a translation is required with the identity document @privacy_policy_url URL for the privacy policy of the service; can be empty
passportAuthorizationForm id:int32 required_types:vector<PassportElementType> elements:vector<PassportElement> errors:vector<passportElementError> is_selfie_required:Bool is_translation_required:Bool privacy_policy_url:string = PassportAuthorizationForm;
//@description Contains encrypted Telegram Passport data credentials @data The encrypted credentials @hash The decrypted data hash @secret Secret for data decryption, encrypted with service's public key
encryptedCredentials data:bytes hash:bytes secret:bytes = EncryptedCredentials;
//@description Contains information about encrypted Telegram Passport element; for bots only @type Type of Telegram Passport element @data Encrypted JSON-encoded data about the user @front_side The front side of an identity document @reverse_side The reverse side of an identity document; may be null @selfie Selfie with the document; may be null @files List of attached files @value Unencrypted data, phone number or email address
encryptedPassportElement type:PassportElementType data:bytes front_side:datedFile reverse_side:datedFile selfie:datedFile files:vector<datedFile> value:string = EncryptedPassportElement;
//@description Contains information about encrypted Telegram Passport element; for bots only @type Type of Telegram Passport element @data Encrypted JSON-encoded data about the user @front_side The front side of an identity document @reverse_side The reverse side of an identity document; may be null @selfie Selfie with the document; may be null @translations List of files with the document translation @files List of attached files @value Unencrypted data, phone number or email address @hash Hash of the whole element
encryptedPassportElement type:PassportElementType data:bytes front_side:datedFile reverse_side:datedFile selfie:datedFile translations:vector<datedFile> files:vector<datedFile> value:string hash:string = EncryptedPassportElement;
//@class InputPassportElementErrorSource @description Contains the description of an error in Telegram Passport element; for bots only
//@description The element contains an error in an unspecified place. The error will be considered resolved when anything changes @element_hash Current hash of the whole element
inputPassportElementErrorSourceUnspecified element_hash:bytes = InputPassportElementErrorSource;
//@description A data field contains an error. The error is considered resolved when the field's value changes @field_name Field name @data_hash Current data hash
inputPassportElementErrorSourceDataField field_name:string data_hash:bytes = InputPassportElementErrorSource;
@ -1027,10 +1040,16 @@ inputPassportElementErrorSourceReverseSide file_hash:bytes = InputPassportElemen
//@description The selfie contains an error. The error is considered resolved when the file with the selfie changes @file_hash Current hash of the file containing the selfie
inputPassportElementErrorSourceSelfie file_hash:bytes = InputPassportElementErrorSource;
//@description The file contains an error. The error is considered resolved when the file changes @file_hash Hash of the file with an error
//@description The translation contains an error. The error is considered resolved when the file with the translation changes @file_hash Current hash of the file containing the translation
inputPassportElementErrorSourceTranslation file_hash:bytes = InputPassportElementErrorSource;
//@description The list of translation files contains an error. The error is considered resolved when the file list changes @file_hashes Current hashes of all files with the translation
inputPassportElementErrorSourceTranslations file_hashes:vector<bytes> = InputPassportElementErrorSource;
//@description The file contains an error. The error is considered resolved when the file changes @file_hash Current hash of the file with an error
inputPassportElementErrorSourceFile file_hash:bytes = InputPassportElementErrorSource;
//@description The list of attached files contains an error. The error is considered resolved when the file list changes @file_hashes Hashes of all files
//@description The list of attached files contains an error. The error is considered resolved when the file list changes @file_hashes Current hashes of all attached files
inputPassportElementErrorSourceFiles file_hashes:vector<bytes> = InputPassportElementErrorSource;

Binary file not shown.

View File

@ -873,9 +873,9 @@ secureValueTypeTemporaryRegistration#ea02ec33 = SecureValueType;
secureValueTypePhone#b320aadb = SecureValueType;
secureValueTypeEmail#8e3ca7ee = SecureValueType;
secureValue#b4b4b699 flags:# type:SecureValueType data:flags.0?SecureData front_side:flags.1?SecureFile reverse_side:flags.2?SecureFile selfie:flags.3?SecureFile files:flags.4?Vector<SecureFile> plain_data:flags.5?SecurePlainData hash:bytes = SecureValue;
secureValue flags:# type:SecureValueType data:flags.0?SecureData front_side:flags.1?SecureFile reverse_side:flags.2?SecureFile selfie:flags.3?SecureFile translations:flags.6?Vector<SecureFile> files:flags.4?Vector<SecureFile> plain_data:flags.5?SecurePlainData hash:bytes = SecureValue;
inputSecureValue#67872e8 flags:# type:SecureValueType data:flags.0?SecureData front_side:flags.1?InputSecureFile reverse_side:flags.2?InputSecureFile selfie:flags.3?InputSecureFile files:flags.4?Vector<InputSecureFile> plain_data:flags.5?SecurePlainData = InputSecureValue;
inputSecureValue#8ec23218 flags:# type:SecureValueType data:flags.0?SecureData front_side:flags.1?InputSecureFile reverse_side:flags.2?InputSecureFile selfie:flags.3?InputSecureFile translations:flags.6?Vector<InputSecureFile> files:flags.4?Vector<InputSecureFile> plain_data:flags.5?SecurePlainData = InputSecureValue;
secureValueHash#ed1ecdb0 type:SecureValueType hash:bytes = SecureValueHash;
@ -885,10 +885,13 @@ secureValueErrorReverseSide#868a2aa5 type:SecureValueType file_hash:bytes text:s
secureValueErrorSelfie#e537ced6 type:SecureValueType file_hash:bytes text:string = SecureValueError;
secureValueErrorFile#7a700873 type:SecureValueType file_hash:bytes text:string = SecureValueError;
secureValueErrorFiles#666220e9 type:SecureValueType file_hash:Vector<bytes> text:string = SecureValueError;
secureValueError#869d758f type:SecureValueType hash:bytes text:string = SecureValueError;
secureValueErrorTranslation#5fbc1134 type:SecureValueType file_hash:bytes text:string = SecureValueError;
secureValueErrorTranslations type:SecureValueType file_hash:Vector<bytes> text:string = SecureValueError;
secureCredentialsEncrypted#33f0ea47 data:bytes hash:bytes secret:bytes = SecureCredentialsEncrypted;
account.authorizationForm#cb976d53 flags:# selfie_required:flags.1?true required_types:Vector<SecureValueType> values:Vector<SecureValue> errors:Vector<SecureValueError> users:Vector<User> privacy_policy_url:flags.0?string = account.AuthorizationForm;
account.authorizationForm#ad2e1cd8 flags:# selfie_required:flags.1?true translation_required:flags.2?true required_types:Vector<SecureRequiredType> values:Vector<SecureValue> errors:Vector<SecureValueError> users:Vector<User> privacy_policy_url:flags.0?string = account.AuthorizationForm;
account.sentEmailCode#811f854f email_pattern:string length:int = account.SentEmailCode;
@ -911,6 +914,9 @@ secureSecretSettings#1527bcac secure_algo:SecurePasswordKdfAlgo secure_secret:by
inputCheckPasswordEmpty#9880f658 = InputCheckPasswordSRP;
inputCheckPasswordSRP#d27ff082 srp_id:long A:bytes M1:bytes = InputCheckPasswordSRP;
secureRequiredType#c84462de type:SecureValueType = SecureRequiredType;
secureRequiredTypeOneOf#193c4874 types:Vector<SecureValueType> = SecureRequiredType;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;

Binary file not shown.

View File

@ -79,7 +79,8 @@ class SetSecureValue : public NetQueryCallback {
optional<secure_storage::Secret> secret_;
size_t files_left_to_upload_ = 0;
vector<SecureInputFile> to_upload_;
vector<SecureInputFile> files_to_upload_;
vector<SecureInputFile> translations_to_upload_;
optional<SecureInputFile> front_side_;
optional<SecureInputFile> reverse_side_;
optional<SecureInputFile> selfie_;
@ -318,7 +319,13 @@ void SetSecureValue::UploadCallback::on_upload_error(FileId file_id, Status erro
void SetSecureValue::on_upload_ok(FileId file_id, tl_object_ptr<telegram_api::InputSecureFile> input_file) {
SecureInputFile *info_ptr = nullptr;
for (auto &info : to_upload_) {
for (auto &info : files_to_upload_) {
if (info.file_id == file_id) {
info_ptr = &info;
break;
}
}
for (auto &info : translations_to_upload_) {
if (info.file_id == file_id) {
info_ptr = &info;
break;
@ -398,6 +405,8 @@ void SetSecureValue::start_up() {
return on_error(Status::Error(400, "Reverse side and selfie must be different"));
}
}
CHECK(secure_value_.files.empty() || secure_value_.translations.empty());
if (!secure_value_.files.empty()) {
CHECK(!front_side_file_id.is_valid());
CHECK(!reverse_side_file_id.is_valid());
@ -418,11 +427,33 @@ void SetSecureValue::start_up() {
}
}
}
if (!secure_value_.translations.empty()) {
for (auto it = secure_value_.translations.begin(); it != secure_value_.translations.end();) {
auto file_id = file_manager->get_file_view(it->file_id).file_id();
bool is_duplicate = file_id == front_side_file_id || file_id == reverse_side_file_id || file_id == selfie_file_id;
for (auto pit = secure_value_.translations.begin(); pit != it; pit++) {
if (file_id == file_manager->get_file_view(pit->file_id).file_id()) {
is_duplicate = true;
break;
}
}
if (is_duplicate) {
it = secure_value_.translations.erase(it);
} else {
++it;
}
}
}
to_upload_.resize(secure_value_.files.size());
upload_callback_ = std::make_shared<UploadCallback>(actor_id(this));
for (size_t i = 0; i < to_upload_.size(); i++) {
start_upload(file_manager, secure_value_.files[i].file_id, to_upload_[i]);
files_to_upload_.resize(secure_value_.files.size());
for (size_t i = 0; i < files_to_upload_.size(); i++) {
start_upload(file_manager, secure_value_.files[i].file_id, files_to_upload_[i]);
}
translations_to_upload_.resize(secure_value_.translations.size());
for (size_t i = 0; i < translations_to_upload_.size(); i++) {
start_upload(file_manager, secure_value_.translations[i].file_id, translations_to_upload_[i]);
}
if (front_side_) {
start_upload(file_manager, secure_value_.front_side.file_id, front_side_.value());
@ -461,7 +492,7 @@ void SetSecureValue::loop() {
auto *file_manager = G()->td().get_actor_unsafe()->file_manager_.get();
auto input_secure_value =
get_input_secure_value_object(file_manager, encrypt_secure_value(file_manager, *secret_, secure_value_),
to_upload_, front_side_, reverse_side_, selfie_);
files_to_upload_, front_side_, reverse_side_, selfie_, translations_to_upload_);
auto save_secure_value =
telegram_api::account_saveSecureValue(std::move(input_secure_value), secret_.value().get_hash());
auto query = G()->net_query_creator().create(create_storer(save_secure_value));
@ -480,7 +511,10 @@ void SetSecureValue::tear_down() {
if (file_manager == nullptr) {
return;
}
for (auto &file_info : to_upload_) {
for (auto &file_info : files_to_upload_) {
file_manager->upload(file_info.file_id, nullptr, 0, 0);
}
for (auto &file_info : translations_to_upload_) {
file_manager->upload(file_info.file_id, nullptr, 0, 0);
}
if (front_side_) {
@ -520,6 +554,9 @@ void SetSecureValue::on_result(NetQueryPtr query) {
if (secure_value_.selfie.file_id.is_valid() && encrypted_secure_value.selfie.file.file_id.is_valid()) {
merge(file_manager, secure_value_.selfie.file_id, encrypted_secure_value.selfie);
}
for (size_t i = 0; i < secure_value_.translations.size(); i++) {
merge(file_manager, secure_value_.translations[i].file_id, encrypted_secure_value.translations[i]);
}
auto r_secure_value = decrypt_secure_value(file_manager, *secret_, encrypted_secure_value);
if (r_secure_value.is_error()) {
return on_error(r_secure_value.move_as_error());
@ -647,7 +684,26 @@ class GetPassportAuthorizationForm : public NetQueryCallback {
std::vector<TdApiSecureValue> values;
bool is_selfie_required =
(authorization_form_->flags_ & telegram_api::account_authorizationForm::SELFIE_REQUIRED_MASK) != 0;
auto types = get_secure_value_types(authorization_form_->required_types_);
bool is_translation_required =
(authorization_form_->flags_ & telegram_api::account_authorizationForm::TRANSLATION_REQUIRED_MASK) != 0;
vector<SecureValueType> types;
for (auto &type_ptr : authorization_form_->required_types_) {
CHECK(type_ptr != nullptr);
switch (type_ptr->get_id()) {
case telegram_api::secureRequiredType::ID: {
auto type = move_tl_object_as<telegram_api::secureRequiredType>(type_ptr);
types.push_back(get_secure_value_type(type->type_));
break;
}
case telegram_api::secureRequiredTypeOneOf::ID: {
auto type = move_tl_object_as<telegram_api::secureRequiredTypeOneOf>(type_ptr);
append(types, get_secure_value_types(type->types_));
break;
}
default:
UNREACHABLE();
}
}
for (auto type : types) {
for (auto &value : authorization_form_->values_) {
if (value == nullptr) {
@ -685,6 +741,13 @@ class GetPassportAuthorizationForm : public NetQueryCallback {
td_api::object_ptr<td_api::PassportElementErrorSource> source;
string message;
switch (error_ptr->get_id()) {
case telegram_api::secureValueError::ID: {
auto error = move_tl_object_as<telegram_api::secureValueError>(error_ptr);
type = get_secure_value_type(error->type_);
message = std::move(error->text_);
source = td_api::make_object<td_api::passportElementErrorSourceUnspecified>();
break;
}
case telegram_api::secureValueErrorData::ID: {
auto error = move_tl_object_as<telegram_api::secureValueErrorData>(error_ptr);
type = get_secure_value_type(error->type_);
@ -731,6 +794,20 @@ class GetPassportAuthorizationForm : public NetQueryCallback {
source = td_api::make_object<td_api::passportElementErrorSourceSelfie>();
break;
}
case telegram_api::secureValueErrorTranslation::ID: {
auto error = move_tl_object_as<telegram_api::secureValueErrorTranslation>(error_ptr);
type = get_secure_value_type(error->type_);
message = std::move(error->text_);
source = td_api::make_object<td_api::passportElementErrorSourceTranslation>();
break;
}
case telegram_api::secureValueErrorTranslations::ID: {
auto error = move_tl_object_as<telegram_api::secureValueErrorTranslations>(error_ptr);
type = get_secure_value_type(error->type_);
message = std::move(error->text_);
source = td_api::make_object<td_api::passportElementErrorSourceTranslations>();
break;
}
default:
UNREACHABLE();
}
@ -744,7 +821,7 @@ class GetPassportAuthorizationForm : public NetQueryCallback {
promise_.set_value(make_tl_object<td_api::passportAuthorizationForm>(
authorization_form_id_, get_passport_element_types_object(types), std::move(values), std::move(errors),
is_selfie_required, authorization_form_->privacy_policy_url_));
is_selfie_required, is_translation_required, authorization_form_->privacy_policy_url_));
stop();
}
};
@ -841,6 +918,12 @@ void SecureManager::set_secure_value_errors(Td *td, tl_object_ptr<telegram_api::
auto type = get_input_secure_value_type(get_secure_value_type_td_api(error->type_));
switch (error->source_->get_id()) {
case td_api::inputPassportElementErrorSourceUnspecified::ID: {
auto source = td_api::move_object_as<td_api::inputPassportElementErrorSourceUnspecified>(error->source_);
input_errors.push_back(make_tl_object<telegram_api::secureValueError>(
std::move(type), BufferSlice(source->element_hash_), error->message_));
break;
}
case td_api::inputPassportElementErrorSourceDataField::ID: {
auto source = td_api::move_object_as<td_api::inputPassportElementErrorSourceDataField>(error->source_);
if (!clean_input_string(source->field_name_)) {
@ -869,6 +952,22 @@ void SecureManager::set_secure_value_errors(Td *td, tl_object_ptr<telegram_api::
std::move(type), BufferSlice(source->file_hash_), error->message_));
break;
}
case td_api::inputPassportElementErrorSourceTranslation::ID: {
auto source = td_api::move_object_as<td_api::inputPassportElementErrorSourceTranslation>(error->source_);
input_errors.push_back(make_tl_object<telegram_api::secureValueErrorTranslation>(
std::move(type), BufferSlice(source->file_hash_), error->message_));
break;
}
case td_api::inputPassportElementErrorSourceTranslations::ID: {
auto source = td_api::move_object_as<td_api::inputPassportElementErrorSourceTranslations>(error->source_);
if (source->file_hashes_.empty()) {
return promise.set_error(Status::Error(400, "File hashes must be non-empty"));
}
auto file_hashes = transform(source->file_hashes_, [](Slice hash) { return BufferSlice(hash); });
input_errors.push_back(make_tl_object<telegram_api::secureValueErrorTranslations>(
std::move(type), std::move(file_hashes), error->message_));
break;
}
case td_api::inputPassportElementErrorSourceFile::ID: {
auto source = td_api::move_object_as<td_api::inputPassportElementErrorSourceFile>(error->source_);
input_errors.push_back(make_tl_object<telegram_api::secureValueErrorFile>(
@ -878,7 +977,7 @@ void SecureManager::set_secure_value_errors(Td *td, tl_object_ptr<telegram_api::
case td_api::inputPassportElementErrorSourceFiles::ID: {
auto source = td_api::move_object_as<td_api::inputPassportElementErrorSourceFiles>(error->source_);
if (source->file_hashes_.empty()) {
return promise.set_error(Status::Error(400, "Error hashes must be non-empty"));
return promise.set_error(Status::Error(400, "File hashes must be non-empty"));
}
auto file_hashes = transform(source->file_hashes_, [](Slice hash) { return BufferSlice(hash); });
input_errors.push_back(make_tl_object<telegram_api::secureValueErrorFiles>(
@ -927,6 +1026,7 @@ void SecureManager::on_get_passport_authorization_form(int32 authorization_form_
auto authorization_form = r_authorization_form.move_as_ok();
CHECK(authorization_form != nullptr);
it->second.is_selfie_required = authorization_form->is_selfie_required_;
it->second.is_translation_required = authorization_form->is_translation_required_;
promise.set_value(std::move(authorization_form));
}
@ -997,7 +1097,8 @@ void SecureManager::do_send_passport_authorization_form(int32 authorization_form
}
auto r_encrypted_credentials =
get_encrypted_credentials(credentials, it->second.payload, it->second.is_selfie_required, it->second.public_key);
get_encrypted_credentials(credentials, it->second.payload, it->second.is_selfie_required,
it->second.is_translation_required, it->second.public_key);
if (r_encrypted_credentials.is_error()) {
return promise.set_error(r_encrypted_credentials.move_as_error());
}

View File

@ -57,6 +57,7 @@ class SecureManager : public NetQueryCallback {
string public_key;
string payload;
bool is_selfie_required;
bool is_translation_required;
bool is_received;
};

View File

@ -239,8 +239,8 @@ vector<td_api::object_ptr<td_api::PassportElementType>> get_passport_element_typ
string get_secure_value_data_field_name(SecureValueType type, string field_name) {
switch (type) {
case SecureValueType::PersonalDetails:
if (field_name == "first_name" || field_name == "last_name" || field_name == "gender" ||
field_name == "country_code" || field_name == "residence_country_code") {
if (field_name == "first_name" || field_name == "middle_name" || field_name == "last_name" ||
field_name == "gender" || field_name == "country_code" || field_name == "residence_country_code") {
return field_name;
}
if (field_name == "birth_date") {
@ -433,7 +433,7 @@ telegram_api::object_ptr<telegram_api::secureData> get_secure_data_object(const
bool operator==(const EncryptedSecureValue &lhs, const EncryptedSecureValue &rhs) {
return lhs.type == rhs.type && lhs.data == rhs.data && lhs.files == rhs.files && lhs.front_side == rhs.front_side &&
lhs.reverse_side == rhs.reverse_side && lhs.selfie == rhs.selfie;
lhs.reverse_side == rhs.reverse_side && lhs.selfie == rhs.selfie && lhs.translations == rhs.translations;
}
bool operator!=(const EncryptedSecureValue &lhs, const EncryptedSecureValue &rhs) {
@ -447,10 +447,12 @@ static bool check_encrypted_secure_value(const EncryptedSecureValue &value) {
bool has_front_side = value.front_side.file.file_id.is_valid();
bool has_reverse_side = value.reverse_side.file.file_id.is_valid();
bool has_selfie = value.selfie.file.file_id.is_valid();
bool has_translations = !value.translations.empty();
switch (value.type) {
case SecureValueType::PersonalDetails:
case SecureValueType::Address:
return has_encrypted_data && !has_files && !has_front_side && !has_reverse_side && !has_selfie;
return has_encrypted_data && !has_files && !has_front_side && !has_reverse_side && !has_selfie &&
!has_translations;
case SecureValueType::Passport:
case SecureValueType::InternalPassport:
return has_encrypted_data && !has_files && has_front_side && !has_reverse_side;
@ -462,11 +464,12 @@ static bool check_encrypted_secure_value(const EncryptedSecureValue &value) {
case SecureValueType::RentalAgreement:
case SecureValueType::PassportRegistration:
case SecureValueType::TemporaryRegistration:
return !has_encrypted_data && !has_plain_data && has_files && !has_front_side && !has_reverse_side && !has_selfie;
return !has_encrypted_data && !has_plain_data && has_files && !has_front_side && !has_reverse_side &&
!has_selfie && !has_translations;
case SecureValueType::PhoneNumber:
return has_plain_data && !has_files && !has_front_side && !has_reverse_side && !has_selfie;
return has_plain_data && !has_files && !has_front_side && !has_reverse_side && !has_selfie && !has_translations;
case SecureValueType::EmailAddress:
return has_plain_data && !has_files && !has_front_side && !has_reverse_side && !has_selfie;
return has_plain_data && !has_files && !has_front_side && !has_reverse_side && !has_selfie && !has_translations;
case SecureValueType::None:
return false;
default:
@ -507,6 +510,7 @@ EncryptedSecureValue get_encrypted_secure_value(FileManager *file_manager,
if (secure_value->selfie_ != nullptr) {
result.selfie = get_encrypted_secure_file(file_manager, std::move(secure_value->selfie_));
}
result.translations = get_encrypted_secure_files(file_manager, std::move(secure_value->translations_));
result.hash = secure_value->hash_.as_slice().str();
if (!check_encrypted_secure_value(result)) {
LOG(ERROR) << "Receive invalid encrypted secure value of type " << result.type;
@ -536,12 +540,14 @@ td_api::object_ptr<td_api::encryptedPassportElement> get_encrypted_passport_elem
value.front_side.file.file_id.is_valid() ? get_dated_file_object(file_manager, value.front_side) : nullptr,
value.reverse_side.file.file_id.is_valid() ? get_dated_file_object(file_manager, value.reverse_side) : nullptr,
value.selfie.file.file_id.is_valid() ? get_dated_file_object(file_manager, value.selfie) : nullptr,
get_dated_files_object(file_manager, value.files), is_plain ? value.data.data : string());
get_dated_files_object(file_manager, value.translations), get_dated_files_object(file_manager, value.files),
is_plain ? value.data.data : string(), value.hash);
}
telegram_api::object_ptr<telegram_api::inputSecureValue> get_input_secure_value_object(
FileManager *file_manager, const EncryptedSecureValue &value, std::vector<SecureInputFile> &input_files,
optional<SecureInputFile> &front_side, optional<SecureInputFile> &reverse_side, optional<SecureInputFile> &selfie) {
FileManager *file_manager, const EncryptedSecureValue &value, std::vector<SecureInputFile> &files,
optional<SecureInputFile> &front_side, optional<SecureInputFile> &reverse_side, optional<SecureInputFile> &selfie,
std::vector<SecureInputFile> &translations) {
bool is_plain = value.type == SecureValueType::PhoneNumber || value.type == SecureValueType::EmailAddress;
bool has_front_side = value.front_side.file.file_id.is_valid();
bool has_reverse_side = value.reverse_side.file.file_id.is_valid();
@ -573,12 +579,16 @@ telegram_api::object_ptr<telegram_api::inputSecureValue> get_input_secure_value_
flags |= telegram_api::inputSecureValue::SELFIE_MASK;
CHECK(selfie);
}
if (!value.translations.empty()) {
flags |= telegram_api::inputSecureValue::TRANSLATIONS_MASK;
}
return telegram_api::make_object<telegram_api::inputSecureValue>(
flags, get_input_secure_value_type(value.type), is_plain ? nullptr : get_secure_data_object(value.data),
has_front_side ? get_input_secure_file_object(file_manager, value.front_side, *front_side) : nullptr,
has_reverse_side ? get_input_secure_file_object(file_manager, value.reverse_side, *reverse_side) : nullptr,
has_selfie ? get_input_secure_file_object(file_manager, value.selfie, *selfie) : nullptr,
get_input_secure_files_object(file_manager, value.files, input_files), std::move(plain_data));
get_input_secure_files_object(file_manager, value.translations, translations),
get_input_secure_files_object(file_manager, value.files, files), std::move(plain_data));
}
vector<td_api::object_ptr<td_api::encryptedPassportElement>> get_encrypted_passport_element_object(
@ -700,6 +710,16 @@ static Status check_first_name(string &first_name) {
return Status::OK();
}
static Status check_middle_name(string &middle_name) {
if (!clean_input_string(middle_name)) {
return Status::Error(400, "Middle name must be encoded in UTF-8");
}
if (utf8_length(middle_name) > 255) {
return Status::Error(400, "Middle name is too long");
}
return Status::OK();
}
static Status check_last_name(string &last_name) {
if (!clean_input_string(last_name)) {
return Status::Error(400, "Last name must be encoded in UTF-8");
@ -725,6 +745,7 @@ static Result<string> get_personal_details(td_api::object_ptr<td_api::personalDe
return Status::Error(400, "Personal details must not be empty");
}
TRY_STATUS(check_first_name(personal_details->first_name_));
TRY_STATUS(check_middle_name(personal_details->middle_name_));
TRY_STATUS(check_last_name(personal_details->last_name_));
TRY_RESULT(birthdate, get_date(std::move(personal_details->birthdate_)));
if (birthdate.empty()) {
@ -736,6 +757,7 @@ static Result<string> get_personal_details(td_api::object_ptr<td_api::personalDe
return json_encode<std::string>(json_object([&](auto &o) {
o("first_name", personal_details->first_name_);
o("middle_name", personal_details->middle_name_);
o("last_name", personal_details->last_name_);
o("birth_date", birthdate);
o("gender", personal_details->gender_);
@ -758,6 +780,7 @@ static Result<td_api::object_ptr<td_api::personalDetails>> get_personal_details_
auto &object = value.get_object();
TRY_RESULT(first_name, get_json_object_string_field(object, "first_name", true));
TRY_RESULT(middle_name, get_json_object_string_field(object, "middle_name", true));
TRY_RESULT(last_name, get_json_object_string_field(object, "last_name", true));
TRY_RESULT(birthdate, get_json_object_string_field(object, "birth_date", true));
if (birthdate.empty()) {
@ -768,15 +791,16 @@ static Result<td_api::object_ptr<td_api::personalDetails>> get_personal_details_
TRY_RESULT(residence_country_code, get_json_object_string_field(object, "residence_country_code", true));
TRY_STATUS(check_first_name(first_name));
TRY_STATUS(check_middle_name(middle_name));
TRY_STATUS(check_last_name(last_name));
TRY_RESULT(date, get_date_object(birthdate));
TRY_STATUS(check_gender(gender));
TRY_STATUS(check_country_code(country_code));
TRY_STATUS(check_country_code(residence_country_code));
return td_api::make_object<td_api::personalDetails>(std::move(first_name), std::move(last_name), std::move(date),
std::move(gender), std::move(country_code),
std::move(residence_country_code));
return td_api::make_object<td_api::personalDetails>(std::move(first_name), std::move(middle_name),
std::move(last_name), std::move(date), std::move(gender),
std::move(country_code), std::move(residence_country_code));
}
static Status check_document_number(string &number) {
@ -841,14 +865,18 @@ static Result<SecureValue> get_identity_document(SecureValueType type, FileManag
}
TRY_RESULT(front_side, get_secure_file(file_manager, std::move(identity_document->front_side_)));
res.front_side = front_side;
res.front_side = std::move(front_side);
if (identity_document->reverse_side_ != nullptr) {
TRY_RESULT(reverse_side, get_secure_file(file_manager, std::move(identity_document->reverse_side_)));
res.reverse_side = reverse_side;
res.reverse_side = std::move(reverse_side);
}
if (identity_document->selfie_ != nullptr) {
TRY_RESULT(selfie, get_secure_file(file_manager, std::move(identity_document->selfie_)));
res.selfie = selfie;
res.selfie = std::move(selfie);
}
if (!identity_document->translations_.empty()) {
TRY_RESULT(translations, get_secure_files(file_manager, std::move(identity_document->translations_)));
res.translations = std::move(translations);
}
return res;
}
@ -888,8 +916,11 @@ static Result<td_api::object_ptr<td_api::identityDocument>> get_identity_documen
TRY_STATUS(check_document_number(number));
TRY_RESULT(date, get_date_object(expiry_date));
auto translations = transform(
value.translations, [file_manager](const DatedFile &file) { return get_dated_file_object(file_manager, file); });
return td_api::make_object<td_api::identityDocument>(std::move(number), std::move(date), std::move(front_side),
std::move(reverse_side), std::move(selfie));
std::move(reverse_side), std::move(selfie),
std::move(translations));
}
static Status check_phone_number(string &phone_number) {
@ -1167,6 +1198,9 @@ Result<SecureValueWithCredentials> decrypt_secure_value(FileManager *file_manage
if (res.selfie.file_id.is_valid()) {
res_credentials.selfie = std::move(selfie.second);
}
TRY_RESULT(translations, decrypt_secure_files(file_manager, secret, encrypted_secure_value.translations));
res.translations = std::move(translations.first);
res_credentials.translations = std::move(translations.second);
break;
}
}
@ -1281,6 +1315,7 @@ EncryptedSecureValue encrypt_secure_value(FileManager *file_manager, const secur
res.front_side = encrypt_secure_file(file_manager, master_secret, secure_value.front_side, to_hash);
res.reverse_side = encrypt_secure_file(file_manager, master_secret, secure_value.reverse_side, to_hash);
res.selfie = encrypt_secure_file(file_manager, master_secret, secure_value.selfie, to_hash);
res.translations = encrypt_secure_files(file_manager, master_secret, secure_value.translations, to_hash);
res.hash = secure_storage::calc_value_hash(to_hash).as_slice().str();
break;
}
@ -1346,15 +1381,15 @@ static Slice secure_value_type_as_slice(SecureValueType type) {
}
static auto credentials_as_jsonable(const std::vector<SecureValueCredentials> &credentials, Slice payload,
bool with_selfie) {
return json_object([&credentials, payload, with_selfie](auto &o) {
o("secure_data", json_object([&credentials, with_selfie](auto &o) {
bool with_selfie, bool with_translations) {
return json_object([&credentials, payload, with_selfie, with_translations](auto &o) {
o("secure_data", json_object([&credentials, with_selfie, with_translations](auto &o) {
for (auto &cred : credentials) {
if (cred.type == SecureValueType::PhoneNumber || cred.type == SecureValueType::EmailAddress) {
continue;
}
o(secure_value_type_as_slice(cred.type), json_object([&cred, with_selfie](auto &o) {
o(secure_value_type_as_slice(cred.type), json_object([&cred, with_selfie, with_translations](auto &o) {
if (cred.data) {
o("data", as_jsonable(cred.data.value()));
}
@ -1370,6 +1405,9 @@ static auto credentials_as_jsonable(const std::vector<SecureValueCredentials> &c
if (cred.selfie && with_selfie) {
o("selfie", as_jsonable(cred.selfie.value()));
}
if (!cred.translations.empty() && with_translations) {
o("translations", as_jsonable(cred.translations));
}
}));
}
}));
@ -1378,8 +1416,10 @@ static auto credentials_as_jsonable(const std::vector<SecureValueCredentials> &c
}
Result<EncryptedSecureCredentials> get_encrypted_credentials(const std::vector<SecureValueCredentials> &credentials,
Slice payload, bool with_selfie, Slice public_key) {
auto encoded_credentials = json_encode<std::string>(credentials_as_jsonable(credentials, payload, with_selfie));
Slice payload, bool with_selfie, bool with_translations,
Slice public_key) {
auto encoded_credentials =
json_encode<std::string>(credentials_as_jsonable(credentials, payload, with_selfie, with_translations));
LOG(INFO) << "Created credentials " << encoded_credentials;
auto secret = secure_storage::Secret::create_new();

View File

@ -113,7 +113,8 @@ struct EncryptedSecureValue {
EncryptedSecureFile front_side;
EncryptedSecureFile reverse_side;
EncryptedSecureFile selfie;
string hash; // memory only
vector<EncryptedSecureFile> translations;
string hash;
};
bool operator==(const EncryptedSecureValue &lhs, const EncryptedSecureValue &rhs);
@ -128,8 +129,9 @@ vector<EncryptedSecureValue> get_encrypted_secure_values(
td_api::object_ptr<td_api::encryptedPassportElement> get_encrypted_passport_element_object(
FileManager *file_manager, const EncryptedSecureValue &value);
telegram_api::object_ptr<telegram_api::inputSecureValue> get_input_secure_value_object(
FileManager *file_manager, const EncryptedSecureValue &value, vector<SecureInputFile> &input_files,
optional<SecureInputFile> &front_side, optional<SecureInputFile> &reverse_side, optional<SecureInputFile> &selfie);
FileManager *file_manager, const EncryptedSecureValue &value, vector<SecureInputFile> &files,
optional<SecureInputFile> &front_side, optional<SecureInputFile> &reverse_side, optional<SecureInputFile> &selfie,
vector<SecureInputFile> &translations);
vector<td_api::object_ptr<td_api::encryptedPassportElement>> get_encrypted_passport_element_object(
FileManager *file_manager, const vector<EncryptedSecureValue> &values);
@ -168,10 +170,12 @@ struct SecureValueCredentials {
optional<SecureFileCredentials> front_side;
optional<SecureFileCredentials> reverse_side;
optional<SecureFileCredentials> selfie;
std::vector<SecureFileCredentials> translations;
};
Result<EncryptedSecureCredentials> get_encrypted_credentials(const std::vector<SecureValueCredentials> &credentials,
Slice payload, bool with_selfie, Slice public_key);
Slice payload, bool with_selfie, bool with_translations,
Slice public_key);
class SecureValue {
public:
@ -181,6 +185,7 @@ class SecureValue {
DatedFile front_side;
DatedFile reverse_side;
DatedFile selfie;
vector<DatedFile> translations;
};
struct SecureValueWithCredentials {

View File

@ -75,12 +75,16 @@ void store(const EncryptedSecureValue &value, StorerT &storer) {
bool has_front_side = value.front_side.file.file_id.is_valid();
bool has_reverse_side = value.reverse_side.file.file_id.is_valid();
bool has_selfie = value.selfie.file.file_id.is_valid();
bool has_hash = !value.hash.empty();
bool has_translations = !value.translations.empty();
BEGIN_STORE_FLAGS();
STORE_FLAG(has_data_hash);
STORE_FLAG(has_files);
STORE_FLAG(has_front_side);
STORE_FLAG(has_reverse_side);
STORE_FLAG(has_selfie);
STORE_FLAG(has_hash);
STORE_FLAG(has_translations);
END_STORE_FLAGS();
store(value.type, storer);
if (has_data_hash) {
@ -100,6 +104,12 @@ void store(const EncryptedSecureValue &value, StorerT &storer) {
if (has_selfie) {
store(value.selfie, storer);
}
if (has_hash) {
store(value.hash, storer);
}
if (has_translations) {
store(value.translations, storer);
}
}
template <class ParserT>
@ -109,12 +119,16 @@ void parse(EncryptedSecureValue &value, ParserT &parser) {
bool has_front_side;
bool has_reverse_side;
bool has_selfie;
bool has_hash;
bool has_translations;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_data_hash);
PARSE_FLAG(has_files);
PARSE_FLAG(has_front_side);
PARSE_FLAG(has_reverse_side);
PARSE_FLAG(has_selfie);
PARSE_FLAG(has_hash);
PARSE_FLAG(has_translations);
END_PARSE_FLAGS();
parse(value.type, parser);
if (has_data_hash) {
@ -134,6 +148,12 @@ void parse(EncryptedSecureValue &value, ParserT &parser) {
if (has_selfie) {
parse(value.selfie, parser);
}
if (has_hash) {
parse(value.hash, parser);
}
if (has_translations) {
parse(value.translations, parser);
}
}
} // namespace td

View File

@ -1093,23 +1093,34 @@ class CliClient final : public Actor {
return make_tl_object<td_api::inputPassportElementPhoneNumber>(arg);
} else if (passport_element_type == "pd") {
return make_tl_object<td_api::inputPassportElementPersonalDetails>(make_tl_object<td_api::personalDetails>(
"Mike", "Towers", make_tl_object<td_api::date>(29, 2, 2000), "male", "US", "GB"));
"Mike", "Jr", "Towers", make_tl_object<td_api::date>(29, 2, 2000), "male", "US", "GB"));
} else if (passport_element_type == "driver_license" || passport_element_type == "dl") {
if (input_files.size() == 2) {
if (input_files.size() >= 2) {
auto front_side = std::move(input_files[0]);
input_files.erase(input_files.begin());
auto reverse_side = std::move(input_files[0]);
input_files.erase(input_files.begin());
return make_tl_object<td_api::inputPassportElementDriverLicense>(make_tl_object<td_api::inputIdentityDocument>(
"1234567890", make_tl_object<td_api::date>(1, 3, 2029), std::move(input_files[0]),
std::move(input_files[1]), std::move(selfie)));
"1234567890", make_tl_object<td_api::date>(1, 3, 2029), std::move(front_side), std::move(reverse_side),
std::move(selfie), std::move(input_files)));
}
} else if (passport_element_type == "identity_card" || passport_element_type == "ic") {
if (input_files.size() == 2) {
if (input_files.size() >= 2) {
auto front_side = std::move(input_files[0]);
input_files.erase(input_files.begin());
auto reverse_side = std::move(input_files[0]);
input_files.erase(input_files.begin());
return make_tl_object<td_api::inputPassportElementIdentityCard>(make_tl_object<td_api::inputIdentityDocument>(
"1234567890", nullptr, std::move(input_files[0]), std::move(input_files[1]), std::move(selfie)));
"1234567890", nullptr, std::move(front_side), std::move(reverse_side), std::move(selfie),
std::move(input_files)));
}
} else if (passport_element_type == "internal_passport" || passport_element_type == "ip") {
if (input_files.size() == 1) {
if (input_files.size() >= 1) {
auto front_side = std::move(input_files[0]);
input_files.erase(input_files.begin());
return make_tl_object<td_api::inputPassportElementInternalPassport>(
make_tl_object<td_api::inputIdentityDocument>("1234567890", nullptr, std::move(input_files[0]), nullptr,
std::move(selfie)));
make_tl_object<td_api::inputIdentityDocument>("1234567890", nullptr, std::move(front_side), nullptr,
std::move(selfie), std::move(input_files)));
}
} else if (passport_element_type == "rental_aggrement" || passport_element_type == "ra") {
return make_tl_object<td_api::inputPassportElementRentalAgreement>(std::move(input_files));

View File

@ -21,7 +21,7 @@ class HeaderStorer {
}
template <class StorerT>
void store(StorerT &storer) const {
constexpr int32 LAYER = 84;
constexpr int32 LAYER = 85;
using td::store;
// invokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X;