mirror of
https://github.com/ars3niy/tdlib-purple
synced 2025-08-31 22:15:10 +00:00
Implemented configuring two-step authentication
This commit is contained in:
@@ -25,7 +25,7 @@ add_library(telegram-tdlib SHARED
|
||||
td-client.cpp
|
||||
transceiver.cpp
|
||||
account-data.cpp
|
||||
chat-info.cpp
|
||||
purple-info.cpp
|
||||
config.cpp
|
||||
client-utils.cpp
|
||||
format.cpp
|
||||
|
@@ -1,7 +1,8 @@
|
||||
#include "client-utils.h"
|
||||
#include "chat-info.h"
|
||||
#include "purple-info.h"
|
||||
#include "config.h"
|
||||
#include "format.h"
|
||||
#include "td-client.h"
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
@@ -58,4 +58,6 @@ void setChatMembers(PurpleConvChat *purpleChat, const td::td_api::basicGroupFull
|
||||
void transmitMessage(int64_t chatId, const char *message, TdTransceiver &transceiver,
|
||||
TdAccountData &account, TdTransceiver::ResponseCb response);
|
||||
|
||||
void requestRecoveryEmailConfirmation(PurpleConnection *gc, const char *emailInfo);
|
||||
|
||||
#endif
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#include "chat-info.h"
|
||||
#include "purple-info.h"
|
||||
#include "config.h"
|
||||
#include <algorithm>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#ifndef _CHAT_INFO_H
|
||||
#define _CHAT_INFO_H
|
||||
#ifndef _PURPLE_INFO_H
|
||||
#define _PURPLE_INFO_H
|
||||
|
||||
#include <purple.h>
|
||||
#include <td/telegram/td_api.h>
|
100
td-client.cpp
100
td-client.cpp
@@ -1,5 +1,5 @@
|
||||
#include "td-client.h"
|
||||
#include "chat-info.h"
|
||||
#include "purple-info.h"
|
||||
#include "config.h"
|
||||
#include "format.h"
|
||||
#include <unistd.h>
|
||||
@@ -532,7 +532,7 @@ void PurpleTdClient::requestMissingPrivateChats()
|
||||
|
||||
void PurpleTdClient::loginCreatePrivateChatResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object)
|
||||
{
|
||||
if (object->get_id() == td::td_api::chat::ID) {
|
||||
if (object && (object->get_id() == td::td_api::chat::ID)) {
|
||||
td::td_api::object_ptr<td::td_api::chat> chat = td::move_tl_object_as<td::td_api::chat>(object);
|
||||
purple_debug_misc(config::pluginId, "Requested private chat received: id %" G_GINT64_FORMAT "\n",
|
||||
chat->id_);
|
||||
@@ -1254,7 +1254,7 @@ void PurpleTdClient::importContactResponse(uint64_t requestId, td::td_api::objec
|
||||
return;
|
||||
|
||||
int32_t userId = 0;
|
||||
if (object->get_id() == td::td_api::importedContacts::ID) {
|
||||
if (object && (object->get_id() == td::td_api::importedContacts::ID)) {
|
||||
td::td_api::object_ptr<td::td_api::importedContacts> reply =
|
||||
td::move_tl_object_as<td::td_api::importedContacts>(object);
|
||||
if (!reply->user_ids_.empty())
|
||||
@@ -1276,7 +1276,7 @@ void PurpleTdClient::addContactResponse(uint64_t requestId, td::td_api::object_p
|
||||
if (!request)
|
||||
return;
|
||||
|
||||
if (object->get_id() == td::td_api::ok::ID) {
|
||||
if (object && (object->get_id() == td::td_api::ok::ID)) {
|
||||
td::td_api::object_ptr<td::td_api::createPrivateChat> createChat =
|
||||
td::td_api::make_object<td::td_api::createPrivateChat>(request->userId, false);
|
||||
uint64_t newRequestId = m_transceiver.sendQuery(std::move(createChat),
|
||||
@@ -1528,3 +1528,95 @@ void PurpleTdClient::removeTempFile(int64_t messageId)
|
||||
remove(path.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void PurpleTdClient::setTwoStepAuth(const char *oldPassword, const char *newPassword,
|
||||
const char *hint, const char *email)
|
||||
{
|
||||
auto setPassword = td::td_api::make_object<td::td_api::setPassword>();
|
||||
if (oldPassword)
|
||||
setPassword->old_password_ = oldPassword;
|
||||
if (newPassword)
|
||||
setPassword->new_password_ = newPassword;
|
||||
if (hint)
|
||||
setPassword->new_hint_ = hint;
|
||||
setPassword->set_recovery_email_address_ = (email && *email);
|
||||
if (email)
|
||||
setPassword->new_recovery_email_address_ = email;
|
||||
|
||||
m_transceiver.sendQuery(std::move(setPassword), &PurpleTdClient::setTwoStepAuthResponse);
|
||||
}
|
||||
|
||||
static void inputCancelled(void *data)
|
||||
{
|
||||
}
|
||||
|
||||
void PurpleTdClient::requestRecoveryEmailConfirmation(const std::string &emailInfo)
|
||||
{
|
||||
std::string secondary = "Password will be changed after new e-mail is confirmed\n" + emailInfo;
|
||||
PurpleConnection *gc = purple_account_get_connection(m_account);
|
||||
purple_request_input(gc, _("Two-factor authentication"),
|
||||
_("Enter verification code received in the e-mail"), secondary.c_str(),
|
||||
NULL, // default value
|
||||
FALSE, // multiline input
|
||||
FALSE, // masked input
|
||||
NULL,
|
||||
_("OK"), G_CALLBACK(PurpleTdClient::verifyRecoveryEmail),
|
||||
_("Cancel"), G_CALLBACK(inputCancelled),
|
||||
purple_connection_get_account(gc),
|
||||
NULL, // buddy
|
||||
NULL, // conversation
|
||||
this);
|
||||
}
|
||||
|
||||
static void notifyPasswordChangeSuccess(PurpleAccount *account, const td::td_api::passwordState &passwordState)
|
||||
{
|
||||
purple_notify_info(account, _("Two-step authentication"),
|
||||
passwordState.has_password_ ? _("Password set") : _("Password cleared"),
|
||||
passwordState.has_recovery_email_address_ ? _("Recovery e-mail is configured") :
|
||||
_("No recovery e-mail configured"));
|
||||
}
|
||||
|
||||
void PurpleTdClient::setTwoStepAuthResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object)
|
||||
{
|
||||
if (object && (object->get_id() == td::td_api::passwordState::ID)) {
|
||||
const td::td_api::passwordState &passwordState = static_cast<const td::td_api::passwordState &>(*object);
|
||||
if (passwordState.recovery_email_address_code_info_) {
|
||||
std::string emailInfo = formatMessage(_("Code sent to {} (length: {})"),
|
||||
{passwordState.recovery_email_address_code_info_->email_address_pattern_,
|
||||
std::to_string(passwordState.recovery_email_address_code_info_->length_)});
|
||||
requestRecoveryEmailConfirmation(emailInfo);
|
||||
} else
|
||||
notifyPasswordChangeSuccess(m_account, passwordState);
|
||||
} else {
|
||||
std::string errorMessage = getDisplayedError(object);
|
||||
purple_notify_error(m_account, _("Two-step authentication"), _("Failed to set password"), errorMessage.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void PurpleTdClient::verifyRecoveryEmail(PurpleTdClient *self, const char *code)
|
||||
{
|
||||
auto checkCode = td::td_api::make_object<td::td_api::checkRecoveryEmailAddressCode>();
|
||||
if (code)
|
||||
checkCode->code_ = code;
|
||||
self->m_transceiver.sendQuery(std::move(checkCode), &PurpleTdClient::verifyRecoveryEmailResponse);
|
||||
}
|
||||
|
||||
void PurpleTdClient::verifyRecoveryEmailResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object)
|
||||
{
|
||||
if (object && (object->get_id() == td::td_api::passwordState::ID)) {
|
||||
const td::td_api::passwordState &passwordState = static_cast<const td::td_api::passwordState &>(*object);
|
||||
if (passwordState.recovery_email_address_code_info_) {
|
||||
if (passwordState.recovery_email_address_code_info_->length_ > 0) {
|
||||
std::string emailInfo = formatMessage(_("E-mail address: {}"),
|
||||
passwordState.recovery_email_address_code_info_->email_address_pattern_);
|
||||
purple_notify_info(m_account, _("Two-step authentication"),
|
||||
_("For some reason, new confirmation code was sent"), emailInfo.c_str());
|
||||
} else
|
||||
purple_notify_error(m_account, _("Two-step authentication"), _("Looks like the code was wrong"), NULL);
|
||||
} else
|
||||
notifyPasswordChangeSuccess(m_account, passwordState);
|
||||
} else {
|
||||
std::string errorMessage = getDisplayedError(object);
|
||||
purple_notify_error(m_account, _("Two-step authentication"), _("Failed to verify recovery e-mail"), errorMessage.c_str());
|
||||
}
|
||||
}
|
||||
|
@@ -32,6 +32,9 @@ public:
|
||||
BasicGroupMembership getBasicGroupMembership(const char *purpleChatName);
|
||||
void leaveGroup(const std::string &purpleChatName, bool deleteSupergroup);
|
||||
int sendGroupMessage(int purpleChatId, const char *message);
|
||||
|
||||
void setTwoStepAuth(const char *oldPassword, const char *newPassword, const char *hint,
|
||||
const char *email);
|
||||
private:
|
||||
using TdObjectPtr = td::td_api::object_ptr<td::td_api::Object>;
|
||||
using ResponseCb = void (PurpleTdClient::*)(uint64_t requestId, TdObjectPtr object);
|
||||
@@ -118,6 +121,11 @@ private:
|
||||
void sendMessageResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object);
|
||||
void removeTempFile(int64_t messageId);
|
||||
|
||||
void setTwoStepAuthResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object);
|
||||
void requestRecoveryEmailConfirmation(const std::string &emailInfo);
|
||||
static void verifyRecoveryEmail(PurpleTdClient *self, const char *code);
|
||||
void verifyRecoveryEmailResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object);
|
||||
|
||||
PurpleAccount *m_account;
|
||||
TdTransceiver m_transceiver;
|
||||
TdAccountData m_data;
|
||||
|
103
tdlib-purple.cpp
103
tdlib-purple.cpp
@@ -1,6 +1,6 @@
|
||||
#include "config.h"
|
||||
#include "td-client.h"
|
||||
#include "chat-info.h"
|
||||
#include "purple-info.h"
|
||||
#include "format.h"
|
||||
#include <purple.h>
|
||||
|
||||
@@ -84,6 +84,8 @@ static GList *tgprpl_status_types (PurpleAccount *acct)
|
||||
struct RequestData {
|
||||
PurpleAccount *account;
|
||||
std::string stringData;
|
||||
|
||||
RequestData(PurpleAccount *account) : account(account) {}
|
||||
};
|
||||
|
||||
static void cancelRequest(RequestData *data, int action)
|
||||
@@ -119,8 +121,7 @@ static void leaveGroup(PurpleBlistNode *node, gpointer data)
|
||||
PurpleTdClient *tdClient = getTdClient(account);
|
||||
if (tdClient) {
|
||||
const char *chatName = getChatName(purple_chat_get_components(chat));
|
||||
RequestData *request = new RequestData;
|
||||
request->account = account;
|
||||
RequestData *request = new RequestData(account);
|
||||
request->stringData = chatName ? chatName : "";
|
||||
|
||||
if (tdClient->getBasicGroupMembership(chatName) == BasicGroupMembership::Creator)
|
||||
@@ -152,8 +153,7 @@ static void deleteGroup(PurpleBlistNode *node, gpointer data)
|
||||
purple_notify_error(account, _("Error"), _("Cannot delete group"),
|
||||
_("Cannot delete basic group created by someone else"));
|
||||
else {
|
||||
RequestData *request = new RequestData;
|
||||
request->account = account;
|
||||
RequestData *request = new RequestData(account);
|
||||
request->stringData = chatName ? chatName : "";
|
||||
purple_request_action(purple_account_get_connection(account), _("Deleting group"),
|
||||
_("Delete the group?"), NULL,
|
||||
@@ -295,8 +295,7 @@ static void tgprpl_request_delete_contact (PurpleConnection *gc, PurpleBuddy *bu
|
||||
{
|
||||
g_return_if_fail(buddy);
|
||||
|
||||
RequestData *data = new RequestData;
|
||||
data->account = purple_connection_get_account(gc);
|
||||
RequestData *data = new RequestData(purple_connection_get_account(gc));
|
||||
data->stringData = purple_buddy_get_name(buddy);
|
||||
|
||||
purple_request_yes_no(gc, _("Remove contact"), _("Remove contact"),
|
||||
@@ -335,11 +334,6 @@ static void create_group_chat_cb (RequestData *data, PurpleRequestFields* fields
|
||||
tdClient->createGroup(request->stringData.c_str(), GROUP_TYPE_BASIC, members);
|
||||
}
|
||||
|
||||
static void cancel_group_chat_cb (RequestData *data)
|
||||
{
|
||||
delete data;
|
||||
}
|
||||
|
||||
static void requestCreateBasicGroup(PurpleConnection *gc, const char *name)
|
||||
{
|
||||
// Telegram doesn't allow to create chats with only one user, so we need to force
|
||||
@@ -362,11 +356,10 @@ static void requestCreateBasicGroup(PurpleConnection *gc, const char *name)
|
||||
|
||||
purple_request_fields_add_group (fields, group);
|
||||
|
||||
RequestData *data = new RequestData;
|
||||
data->account = purple_connection_get_account(gc);
|
||||
RequestData *data = new RequestData(purple_connection_get_account(gc));
|
||||
data->stringData = name;
|
||||
purple_request_fields (gc, _("Create group chat"), _("Invite users"), NULL, fields, _("OK"),
|
||||
G_CALLBACK(create_group_chat_cb), _("Cancel"), G_CALLBACK(cancel_group_chat_cb),
|
||||
G_CALLBACK(create_group_chat_cb), _("Cancel"), G_CALLBACK(cancelRequest),
|
||||
purple_connection_get_account(gc), NULL, NULL, data);
|
||||
}
|
||||
|
||||
@@ -603,9 +596,87 @@ static void tgprpl_init (PurplePlugin *plugin)
|
||||
PurpleTdClient::setLogLevel(1);
|
||||
}
|
||||
|
||||
static void setTwoStepAuth(RequestData *data, PurpleRequestFields* fields);
|
||||
|
||||
static void requestTwoStepAuth(PurpleConnection *gc, const char *primaryText, const char *email)
|
||||
{
|
||||
PurpleRequestFields *fields = purple_request_fields_new();
|
||||
PurpleRequestFieldGroup *group = purple_request_field_group_new(NULL);
|
||||
|
||||
PurpleRequestField *field = purple_request_field_string_new ("oldpw", _("Current password"), NULL, FALSE);
|
||||
purple_request_field_string_set_masked(field, TRUE);
|
||||
purple_request_field_group_add_field (group, field);
|
||||
|
||||
field = purple_request_field_string_new ("pw1", _("New password"), NULL, FALSE);
|
||||
purple_request_field_string_set_masked(field, TRUE);
|
||||
purple_request_field_group_add_field (group, field);
|
||||
|
||||
field = purple_request_field_string_new ("pw2", _("Repeat password"), NULL, FALSE);
|
||||
purple_request_field_string_set_masked(field, TRUE);
|
||||
purple_request_field_group_add_field (group, field);
|
||||
|
||||
field = purple_request_field_string_new ("hint", _("Password hint"), NULL, FALSE);
|
||||
purple_request_field_group_add_field (group, field);
|
||||
|
||||
field = purple_request_field_string_new ("email", _("Recovery e-mail"), email, FALSE);
|
||||
purple_request_field_group_add_field (group, field);
|
||||
|
||||
purple_request_fields_add_group (fields, group);
|
||||
|
||||
RequestData *data = new RequestData(purple_connection_get_account(gc));
|
||||
data->account = purple_connection_get_account(gc);
|
||||
purple_request_fields (gc, _("Two-step authentication"), primaryText, NULL, fields, _("OK"),
|
||||
G_CALLBACK(setTwoStepAuth), _("Cancel"), G_CALLBACK(cancelRequest),
|
||||
purple_connection_get_account(gc), NULL, NULL, data);
|
||||
}
|
||||
|
||||
static int reRequestTwoStepAuth(gpointer user_data)
|
||||
{
|
||||
std::unique_ptr<RequestData> request(static_cast<RequestData *>(user_data));
|
||||
requestTwoStepAuth(purple_account_get_connection(request->account),
|
||||
_("Please enter same password twice"), request->stringData.c_str());
|
||||
return FALSE; // this idle handler will not be called again
|
||||
}
|
||||
|
||||
static void setTwoStepAuth(RequestData *data, PurpleRequestFields* fields)
|
||||
{
|
||||
std::unique_ptr<RequestData> request(data);
|
||||
PurpleTdClient *tdClient = getTdClient(request->account);
|
||||
|
||||
if (tdClient) {
|
||||
const char *oldPass = purple_request_fields_get_string(fields, "oldpw");
|
||||
const char *password1 = purple_request_fields_get_string(fields, "pw1");
|
||||
const char *password2 = purple_request_fields_get_string(fields, "pw2");
|
||||
const char *hint = purple_request_fields_get_string(fields, "hint");
|
||||
const char *email = purple_request_fields_get_string(fields, "email");
|
||||
|
||||
if ((password1 != password2) && (!password1 || !password2 || strcmp(password1, password2))) {
|
||||
// Calling purple_request_fields synchronously causes glitch in pidgin
|
||||
RequestData *newRequest = new RequestData(request->account);
|
||||
if (email)
|
||||
newRequest->stringData = email;
|
||||
g_idle_add(reRequestTwoStepAuth, newRequest);
|
||||
} else if (tdClient)
|
||||
tdClient->setTwoStepAuth(oldPass, password1, hint, email);
|
||||
}
|
||||
}
|
||||
|
||||
static void configureTwoStepAuth(PurplePluginAction *action)
|
||||
{
|
||||
PurpleConnection *gc = static_cast<PurpleConnection *>(action->context);
|
||||
requestTwoStepAuth(gc, _("Enter new password and recovery e-mail address"), NULL);
|
||||
}
|
||||
|
||||
static GList *tgprpl_actions (PurplePlugin *plugin, gpointer context)
|
||||
{
|
||||
return (GList *)NULL;
|
||||
GList *actionsList = NULL;
|
||||
PurplePluginAction *action;
|
||||
|
||||
action = purple_plugin_action_new(_("Configure two-step authentication..."),
|
||||
configureTwoStepAuth);
|
||||
actionsList = g_list_append(actionsList, action);
|
||||
|
||||
return actionsList;
|
||||
}
|
||||
|
||||
static PurplePluginInfo plugin_info = {
|
||||
|
@@ -19,7 +19,7 @@ add_executable(tests EXCLUDE_FROM_ALL
|
||||
../td-client.cpp
|
||||
../transceiver.cpp
|
||||
../account-data.cpp
|
||||
../chat-info.cpp
|
||||
../purple-info.cpp
|
||||
../config.cpp
|
||||
../client-utils.cpp
|
||||
../format.cpp
|
||||
|
@@ -924,6 +924,11 @@ void purple_request_field_set_type_hint(PurpleRequestField *field,
|
||||
{
|
||||
}
|
||||
|
||||
void purple_request_field_string_set_masked(PurpleRequestField *field,
|
||||
gboolean masked)
|
||||
{
|
||||
}
|
||||
|
||||
void purple_request_field_group_add_field(PurpleRequestFieldGroup *group,
|
||||
PurpleRequestField *field)
|
||||
{
|
||||
@@ -967,4 +972,9 @@ void purple_menu_action_free(PurpleMenuAction *act)
|
||||
delete act;
|
||||
}
|
||||
|
||||
PurplePluginAction *purple_plugin_action_new(const char* label, void (*callback)(PurplePluginAction *))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
};
|
||||
|
Reference in New Issue
Block a user