Merge branch 'master' into support-secret-chats

Conflicts:
	Makefile.in
	telegram-base.c
	telegram-base.h
	telegram-purple.c
	telegram-purple.h
This commit is contained in:
mjentsch 2015-01-02 14:29:42 +01:00
commit 817ab52aae
18 changed files with 353 additions and 133 deletions

View file

@ -15,8 +15,7 @@ OBJ=objs
LIB=libs
DIR_LIST=${DEP} ${AUTO} ${EXE} ${OBJ} ${LIB} ${DEP}/auto ${OBJ}/auto
PLUGIN_OBJECTS=${OBJ}/tgp-net.o ${OBJ}/tgp-timers.o ${OBJ}/msglog.o ${OBJ}/telegram-base.o ${OBJ}/telegram-purple.o ${OBJ}/tgp-2prpl.o ${OBJ}/lodepng.o
PLUGIN_OBJECTS=${OBJ}/tgp-net.o ${OBJ}/tgp-timers.o ${OBJ}/msglog.o ${OBJ}/telegram-base.o ${OBJ}/telegram-purple.o ${OBJ}/tgp-2prpl.o ${OBJ}/tgp-structs.o ${OBJ}/lodepng.o
ALL_OBJS=${PLUGIN_OBJECTS}
.SUFFIXES:

View file

@ -18,7 +18,7 @@ When encountering a crash or some other bugs, please report it to us, preferably
- Support changing own profile picture
- Support adding new contacts
- Display service messages
- Works with libpurple proxy settings
## Version 0.4
@ -45,7 +45,6 @@ The following features are currently planned and will probably be added in the f
- File transfers
- Geo-locations
- Multiple accounts on one client
- Respect libpurple proxy settings (implemented but untested)
## Platform Support

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 671 B

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 943 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -38,15 +38,9 @@
#define COLOR_NORMAL ""
#endif
void hexdump (int *in_ptr, int *in_end) {
// TODO: figure out how to log hexdumps to purple log
int *ptr = in_ptr;
while (ptr < in_end) {
++ ptr;
//printf (" %08x", *(ptr ++));
}
//printf ("\n");
}
/*
msglog.c: Convenience methods for logging to libpurple log
*/
void log_level_printf (const char* format, va_list ap, int level, char *color) {
char buffer[256];

View file

@ -19,8 +19,6 @@
*/
#include <stdarg.h>
void hexdump (int *in_ptr, int *in_end);
void debug(const char* format, ...);
void info(const char* format, ...);
void warning(const char* format, ...);

View file

@ -35,6 +35,7 @@
#include <telegram-purple.h>
#include <msglog.h>
#include <tgp-2prpl.h>
#include "tgp-structs.h"
#include "lodepng.h"
#define DC_SERIALIZED_MAGIC 0x868aa81d
@ -164,6 +165,15 @@ void read_dc (struct tgl_state *TLS, int auth_file_fd, int id, unsigned ver) {
bl_do_dc_signed (TLS, id);
}
int error_if_val_false (struct tgl_state *TLS, int val, const char *msg) {
if (!val) {
connection_data *conn = TLS->ev_base;
purple_connection_error_reason (conn->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, msg);
return 1;
}
return 0;
}
void empty_auth_file (struct tgl_state *TLS) {
if (TLS->test_mode) {
bl_do_dc_option (TLS, 1, 0, "", strlen (TG_SERVER_TEST_1), TG_SERVER_TEST_1, 443);
@ -226,8 +236,9 @@ void read_auth_file (struct tgl_state *TLS) {
void telegram_export_authorization (struct tgl_state *TLS);
void export_auth_callback (struct tgl_state *TLS, void *extra, int success) {
assert (success);
telegram_export_authorization (TLS);
if (!error_if_val_false(TLS, success, "Authentication Export failed.")) {
telegram_export_authorization (TLS);
}
}
void telegram_export_authorization (struct tgl_state *TLS) {
@ -262,21 +273,21 @@ static void code_auth_receive_result (struct tgl_state *TLS, void *extra, int su
void request_code_entered (gpointer data, const gchar *code) {
struct tgl_state *TLS = data;
telegram_conn *conn = TLS->ev_base;
connection_data *conn = TLS->ev_base;
char const *username = purple_account_get_username(conn->pa);
tgl_do_send_code_result (TLS, username, conn->hash, code, code_receive_result, 0) ;
}
static void request_code_canceled (gpointer data) {
struct tgl_state *TLS = data;
telegram_conn *conn = TLS->ev_base;
connection_data *conn = TLS->ev_base;
purple_connection_error_reason(conn->gc,
PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, "registration canceled");
}
static void request_name_code_entered (PurpleConnection* gc, PurpleRequestFields* fields) {
telegram_conn *conn = purple_connection_get_protocol_data(gc);
connection_data *conn = purple_connection_get_protocol_data(gc);
struct tgl_state *TLS = conn->TLS;
char const *username = purple_account_get_username(conn->pa);
@ -293,7 +304,7 @@ static void request_name_code_entered (PurpleConnection* gc, PurpleRequestFields
static void request_code (struct tgl_state *TLS) {
debug ("Client is not registered, registering...\n");
telegram_conn *conn = TLS->ev_base;
connection_data *conn = TLS->ev_base;
int compat = purple_account_get_bool (tg_get_acc(TLS), "compat-verification", 0);
if (compat || ! purple_request_input (conn->gc, "Telegram Code", "Enter Telegram Code",
@ -315,7 +326,7 @@ static void request_code (struct tgl_state *TLS) {
static void request_name_and_code (struct tgl_state *TLS) {
debug ("Phone is not registered, registering...\n");
telegram_conn *conn = TLS->ev_base;
connection_data *conn = TLS->ev_base;
PurpleRequestFields* fields = purple_request_fields_new();
PurpleRequestField* field = 0;
@ -342,14 +353,14 @@ static void request_name_and_code (struct tgl_state *TLS) {
}
static void sign_in_callback (struct tgl_state *TLS, void *extra, int success, int registered, const char *mhash) {
assert (success); // TODO proper error handle
telegram_conn *conn = TLS->ev_base;
conn->hash = strdup (mhash);
if (registered) {
request_code (TLS);
} else {
request_name_and_code (TLS);
connection_data *conn = TLS->ev_base;
if (!error_if_val_false (TLS, success, "Invalid or non-existing phone number.")) {
conn->hash = strdup (mhash);
if (registered) {
request_code (TLS);
} else {
request_name_and_code (TLS);
}
}
}
@ -358,7 +369,7 @@ static void telegram_send_sms (struct tgl_state *TLS) {
telegram_export_authorization (TLS);
return;
}
telegram_conn *conn = TLS->ev_base;
connection_data *conn = TLS->ev_base;
char const *username = purple_account_get_username(conn->pa);
tgl_do_send_code (TLS, username, sign_in_callback, 0);
}
@ -395,7 +406,7 @@ void telegram_login (struct tgl_state *TLS) {
PurpleConversation *chat_show (PurpleConnection *gc, int id) {
debug ("show chat");
telegram_conn *conn = purple_connection_get_protocol_data(gc);
connection_data *conn = purple_connection_get_protocol_data(gc);
PurpleConversation *convo = purple_find_chat(gc, id);
if (! convo) {
@ -411,17 +422,20 @@ PurpleConversation *chat_show (PurpleConnection *gc, int id) {
}
int chat_add_message (struct tgl_state *TLS, struct tgl_message *M, char *text) {
telegram_conn *conn = TLS->ev_base;
connection_data *conn = TLS->ev_base;
if (chat_show (conn->gc, tgl_get_peer_id (M->to_id))) {
p2tgl_got_chat_in(TLS, M->to_id, M->from_id, text ? text : M->message,
M->service ? PURPLE_MESSAGE_SYSTEM : PURPLE_MESSAGE_RECV, M->date);
pending_reads_add (conn->pending_reads, M->to_id);
if (p2tgl_status_is_present(purple_account_get_active_status(conn->pa))) {
pending_reads_send_all (conn->pending_reads, conn->TLS);
}
return 1;
} else {
// add message once the chat was initialised
struct message_text *mt = malloc (sizeof (*mt));
mt->M = M;
mt->text = text ? g_strdup (text) : text;
struct message_text *mt = message_text_init (M, text);
g_queue_push_tail (conn->new_messages, mt);
return 0;
}
@ -442,6 +456,9 @@ void chat_add_all_users (PurpleConversation *pc, struct tgl_chat *chat) {
}
}
/**
* This function generates a png image to visulize the sha1 key from an encrypted chat.
*/
int generate_ident_icon (unsigned char* sha1_key)
{
int colors[4] = {
@ -490,4 +507,4 @@ int generate_ident_icon (unsigned char* sha1_key)
g_free(image);
g_free(png);
return imgStoreId;
}
}

View file

@ -19,6 +19,9 @@
*/
#ifndef __TELEGRAM_BASE_H__
#define __TELEGRAM_BASE_H__
#include "telegram-purple.h"
void read_state_file (struct tgl_state *TLS);
void read_auth_file (struct tgl_state *TLS);
void write_auth_file (struct tgl_state *TLS);
@ -30,4 +33,5 @@ int chat_add_message (struct tgl_state *TLS, struct tgl_message *M, char *text);
void chat_add_all_users (PurpleConversation *pc, struct tgl_chat *chat);
void request_code_entered (gpointer data, const gchar *code);
int generate_ident_icon(unsigned char* sha1_key);
#endif

View file

@ -51,6 +51,7 @@
#include "request.h"
#include <tgl.h>
#include "tgp-structs.h"
#include "tgp-2prpl.h"
#include "tgp-net.h"
#include "tgp-timers.h"
@ -65,8 +66,8 @@ const char *pk_path = "/etc/telegram-purple/server.pub";
void tgprpl_login_on_connected();
void on_user_get_info (struct tgl_state *TLS, void *show_info, int success, struct tgl_user *U);
static telegram_conn *get_conn_from_buddy (PurpleBuddy *buddy) {
telegram_conn *c = purple_connection_get_protocol_data (
static connection_data *get_conn_from_buddy (PurpleBuddy *buddy) {
connection_data *c = purple_connection_get_protocol_data (
purple_account_get_connection (purple_buddy_get_account (buddy)));
return c;
}
@ -181,12 +182,17 @@ static char *format_service_msg (struct tgl_state *TLS, struct tgl_message *M)
static int our_msg (struct tgl_state *TLS, struct tgl_message *M) {
//return tgl_get_peer_id(M->from_id) == TLS->our_id;
//return M->out;
return (M->flags & FLAG_SESSION_OUTBOUND) != 0;
}
static int out_msg (struct tgl_state *TLS, struct tgl_message *M) {
return M->out;
}
static gboolean queries_timerfunc (gpointer data) {
debug ("queries_timerfunc()\n");
telegram_conn *conn = data;
connection_data *conn = data;
if (conn->updated) {
conn->updated = 0;
@ -230,25 +236,28 @@ struct tgl_update_callback tgp_callback = {
};
void on_message_load_photo (struct tgl_state *TLS, void *extra, int success, char *filename) {
connection_data *conn = TLS->ev_base;
gchar *data = NULL;
size_t len;
GError *err = NULL;
g_file_get_contents (filename, &data, &len, &err);
int imgStoreId = purple_imgstore_add_with_id (g_memdup(data, (guint)len), len, NULL);
char *image = format_img_full(imgStoreId);
used_images_add (conn, imgStoreId);
char *image = format_img_full (imgStoreId);
struct tgl_message *M = extra;
switch (tgl_get_peer_type (M->to_id)) {
case TGL_PEER_CHAT:
debug ("PEER_CHAT\n");
if (! our_msg(TLS, M)) {
if (!our_msg(TLS, M)) {
chat_add_message (TLS, M, image);
}
break;
case TGL_PEER_USER:
debug ("PEER_USER\n");
if (our_msg(TLS, M)) {
if (out_msg(TLS, M)) {
p2tgl_got_im (TLS, M->to_id, image, PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_IMAGES, M->date);
} else {
p2tgl_got_im (TLS, M->from_id, image, PURPLE_MESSAGE_RECV | PURPLE_MESSAGE_IMAGES, M->date);
@ -267,13 +276,13 @@ void on_message_load_photo (struct tgl_state *TLS, void *extra, int success, cha
}
g_free (image);
telegram_conn *conn = TLS->ev_base;
conn = TLS->ev_base;
conn->updated = 1;
}
static void update_message_received (struct tgl_state *TLS, struct tgl_message *M) {
debug ("received message\n");
telegram_conn *conn = TLS->ev_base;
connection_data *conn = TLS->ev_base;
conn->updated = 1;
if (M->service) {
@ -316,7 +325,7 @@ static void update_message_received (struct tgl_state *TLS, struct tgl_message *
switch (tgl_get_peer_type (M->to_id)) {
case TGL_PEER_CHAT:
debug ("PEER_CHAT\n");
if (! our_msg(TLS, M)) {
if (!our_msg(TLS, M)) {
chat_add_message (TLS, M, text);
}
break;
@ -326,8 +335,17 @@ static void update_message_received (struct tgl_state *TLS, struct tgl_message *
// p2tgl_got_im (TLS, M->to_id, text, PURPLE_MESSAGE_SEND, M->date);
// :TODO: figure out how to add messages from different devices to history
if (! our_msg(TLS, M)) {
p2tgl_got_im (TLS, M->from_id, text, PURPLE_MESSAGE_RECV, M->date);
if (!our_msg(TLS, M)) {
if (out_msg(TLS, M)) {
p2tgl_got_im (TLS, M->to_id, text, PURPLE_MESSAGE_SEND, M->date);
} else {
p2tgl_got_im (TLS, M->from_id, text, PURPLE_MESSAGE_RECV, M->date);
pending_reads_add (conn->pending_reads, M->from_id);
if (p2tgl_status_is_present(purple_account_get_active_status(conn->pa))) {
pending_reads_send_all (conn->pending_reads, conn->TLS);
}
}
}
break;
@ -362,9 +380,6 @@ static void update_user_handler (struct tgl_state *TLS, struct tgl_user *user, u
p2tgl_prpl_got_user_status (TLS, user->id, &user->status);
p2tgl_buddy_update (TLS, (tgl_peer_t *)user, flags);
}
if (flags & (TGL_UPDATE_NAME | TGL_UPDATE_REAL_NAME | TGL_UPDATE_USERNAME) && buddy) {
p2tgl_blist_alias_buddy (buddy, user);
}
if (flags & TGL_UPDATE_PHOTO) {
tgl_do_get_user_info (TLS, user->id, 0, on_user_get_info, 0);
}
@ -449,13 +464,15 @@ static void on_userpic_loaded (struct tgl_state *TLS, void *extra, int success,
struct tgl_user *U = dld->data;
warning ("Can not load userpic for user %s %s\n", U->first_name, U->last_name);
}
telegram_conn *conn = TLS->ev_base;
connection_data *conn = TLS->ev_base;
gchar *data = NULL;
size_t len;
GError *err = NULL;
g_file_get_contents (filename, &data, &len, &err);
int imgStoreId = purple_imgstore_add_with_id (g_memdup(data, (guint)len), len, NULL);
used_images_add (conn, imgStoreId);
struct download_desc *dld = extra;
struct tgl_user *U = dld->data;
@ -482,7 +499,7 @@ static void on_userpic_loaded (struct tgl_state *TLS, void *extra, int success,
purple_notify_userinfo (conn->gc, who, info, NULL, NULL);
g_free (profile_image);
}
purple_buddy_icons_set_for_user(conn->pa, who, g_memdup(data, (guint)len), len, NULL);
purple_buddy_icons_set_for_user(conn->pa, who, data, len, NULL);
g_free(who);
}
@ -507,7 +524,7 @@ void on_chat_get_info (struct tgl_state *TLS, void *extra, int success, struct t
assert (success);
debug ("on_chat_joined(%d)\n", tgl_get_peer_id (C->id));
telegram_conn *conn = TLS->ev_base;
connection_data *conn = TLS->ev_base;
PurpleConversation *conv;
if (!(conv = purple_find_chat(conn->gc, tgl_get_peer_id(C->id)))) {
@ -534,13 +551,9 @@ void on_chat_get_info (struct tgl_state *TLS, void *extra, int success, struct t
g_free (name);
}
// This function generates a png image to visulize the sha1 key from an encrypted chat.
void on_ready (struct tgl_state *TLS) {
debug ("on_ready().\n");
telegram_conn *conn = TLS->ev_base;
connection_data *conn = TLS->ev_base;
purple_connection_set_state(conn->gc, PURPLE_CONNECTED);
purple_connection_set_display_name(conn->gc, purple_account_get_username(conn->pa));
@ -585,16 +598,25 @@ static GList *tgprpl_status_types (PurpleAccount * acct) {
debug ("tgprpl_status_types()\n");
GList *types = NULL;
PurpleStatusType *type;
type = purple_status_type_new_with_attrs (PURPLE_STATUS_AVAILABLE, NULL, NULL,
1, 1, 0, "last online", "last online", purple_value_new (PURPLE_TYPE_STRING), NULL);
type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, NULL, NULL, FALSE, TRUE, FALSE);
types = g_list_prepend (types, type);
type = purple_status_type_new_with_attrs (PURPLE_STATUS_MOBILE, NULL, NULL, 1,
1, 0, "last online", "last online", purple_value_new (PURPLE_TYPE_STRING), NULL);
type = purple_status_type_new_full(PURPLE_STATUS_MOBILE, NULL, NULL, FALSE, TRUE, FALSE);
types = g_list_prepend (types, type);
type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, NULL, NULL, FALSE, TRUE, FALSE);
types = g_list_prepend (types, type);
type = purple_status_type_new (PURPLE_STATUS_OFFLINE, NULL, NULL, 1);
types = g_list_append (types, type);
/*
The states below are only registered internally so that we get notified about
state changes to away and unavailable. This is useful for deciding when to send
No other peer should ever have those states.
*/
type = purple_status_type_new_full(PURPLE_STATUS_AWAY, NULL, NULL, FALSE, TRUE, FALSE);
types = g_list_prepend (types, type);
type = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, NULL, NULL, FALSE, TRUE, FALSE);
types = g_list_prepend (types, type);
return g_list_reverse (types);
}
@ -637,12 +659,7 @@ static void tgprpl_login (PurpleAccount * acct) {
// create handle to store additional info for libpurple in
// the new telegram instance
telegram_conn *conn = g_new0(telegram_conn, 1);
conn->TLS = TLS;
conn->gc = gc;
conn->pa = acct;
conn->new_messages = g_queue_new ();
conn->joining_chats = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
connection_data *conn = connection_data_init (TLS, gc, acct);
purple_connection_set_protocol_data (gc, conn);
tgl_set_ev_base (TLS, conn);
@ -659,15 +676,16 @@ static void tgprpl_login (PurpleAccount * acct) {
static void tgprpl_close (PurpleConnection * gc) {
debug ("tgprpl_close()\n");
telegram_conn *conn = purple_connection_get_protocol_data(gc);
purple_timeout_remove(conn->timer);
tgl_free_all (conn->TLS);
connection_data *conn = purple_connection_get_protocol_data (gc);
purple_timeout_remove (conn->timer);
connection_data_free (conn);
}
static int tgprpl_send_im (PurpleConnection * gc, const char *who, const char *message, PurpleMessageFlags flags) {
debug ("tgprpl_send_im()\n");
telegram_conn *conn = purple_connection_get_protocol_data(gc);
connection_data *conn = purple_connection_get_protocol_data(gc);
PurpleAccount *pa = conn->pa;
// this is part of a workaround to support clients without
@ -698,7 +716,7 @@ static int tgprpl_send_im (PurpleConnection * gc, const char *who, const char *m
static unsigned int tgprpl_send_typing (PurpleConnection * gc, const char *who, PurpleTypingState typing) {
debug ("tgprpl_send_typing()\n");
int id = atoi (who);
telegram_conn *conn = purple_connection_get_protocol_data(gc);
connection_data *conn = purple_connection_get_protocol_data(gc);
tgl_peer_t *U = tgl_peer_get (conn->TLS, TGL_MK_USER (id));
if (U) {
if (typing == PURPLE_TYPING) {
@ -712,41 +730,42 @@ static unsigned int tgprpl_send_typing (PurpleConnection * gc, const char *who,
static void tgprpl_get_info (PurpleConnection * gc, const char *username) {
debug ("tgprpl_get_info()\n");
telegram_conn *conn = purple_connection_get_protocol_data(gc);
connection_data *conn = purple_connection_get_protocol_data(gc);
tgl_peer_id_t u = TGL_MK_USER(atoi(username));
tgl_do_get_user_info (conn->TLS, u, 0, on_user_get_info, (void *)1l);
}
static void tgprpl_set_status (PurpleAccount * acct, PurpleStatus * status) {
debug ("tgprpl_set_status()\n");
debug ("tgprpl_set_status(%s)\n", purple_status_get_name (status));
debug ("tgprpl_set_status(currstatus=%s)\n", purple_status_get_name(purple_account_get_active_status(acct)));
PurpleConnection *gc = purple_account_get_connection(acct);
if (!gc) { return; }
connection_data *conn = purple_connection_get_protocol_data (gc);
if (p2tgl_status_is_present(status)) {
pending_reads_send_all (conn->pending_reads, conn->TLS);
}
}
static void tgprpl_add_buddy (PurpleConnection * gc, PurpleBuddy * buddy, PurpleGroup * group) {
telegram_conn *conn = purple_connection_get_protocol_data(gc);
connection_data *conn = purple_connection_get_protocol_data(gc);
const char* first = buddy->alias ? buddy->alias : "";
tgl_do_add_contact (conn->TLS, buddy->name, (int)strlen (buddy->name), first, (int)strlen (first), "", 0, 0, on_contact_added, buddy);
}
static void tgprpl_add_buddies (PurpleConnection * gc, GList * buddies, GList * groups) {
debug ("tgprpl_add_buddies()\n");
}
static void tgprpl_remove_buddy (PurpleConnection * gc, PurpleBuddy * buddy, PurpleGroup * group) {
debug ("tgprpl_remove_buddy()\n");
if (!buddy) { return; }
telegram_conn *conn = purple_connection_get_protocol_data (gc);
connection_data *conn = purple_connection_get_protocol_data (gc);
struct tgl_user *user = purple_buddy_get_protocol_data (buddy);
if (!user) { warning ("cannot remove buddy '%s', no protocol data found\n", buddy->name); return; }
tgl_do_del_contact (conn->TLS, user->id, NULL, NULL);
}
static void tgprpl_remove_buddies (PurpleConnection * gc, GList * buddies, GList * groups){
debug ("tgprpl_remove_buddies()\n");
}
static void tgprpl_add_deny (PurpleConnection * gc, const char *name){
debug ("tgprpl_add_deny()\n");
}
@ -758,7 +777,7 @@ static void tgprpl_rem_deny (PurpleConnection * gc, const char *name){
static void tgprpl_chat_join (PurpleConnection * gc, GHashTable * data) {
debug ("tgprpl_chat_join()\n");
telegram_conn *conn = purple_connection_get_protocol_data (gc);
connection_data *conn = purple_connection_get_protocol_data (gc);
const char *groupname = g_hash_table_lookup (data, "subject");
char *id = g_hash_table_lookup(data, "id");
@ -795,7 +814,7 @@ static GHashTable *tgprpl_chat_info_deflt (PurpleConnection * gc, const char *ch
static void tgprpl_chat_invite (PurpleConnection * gc, int id, const char *message, const char *name) {
debug ("tgprpl_chat_invite()\n");
telegram_conn *conn = purple_connection_get_protocol_data (gc);
connection_data *conn = purple_connection_get_protocol_data (gc);
tgl_peer_t *chat = tgl_peer_get(conn->TLS, TGL_MK_CHAT (id));
tgl_peer_t *user = tgl_peer_get(conn->TLS, TGL_MK_USER (atoi(name)));
@ -809,14 +828,20 @@ static void tgprpl_chat_invite (PurpleConnection * gc, int id, const char *messa
static int tgprpl_send_chat (PurpleConnection * gc, int id, const char *message, PurpleMessageFlags flags) {
debug ("tgprpl_send_chat()\n");
telegram_conn *conn = purple_connection_get_protocol_data (gc);
connection_data *conn = purple_connection_get_protocol_data (gc);
gchar *raw = purple_unescape_html(message);
tgl_do_send_message (conn->TLS, TGL_MK_CHAT(id), raw, (int)strlen (raw), 0, 0);
g_free (raw);
/* Pidgin won't display the written message if we don't call this, Adium will display it twice
if we call it, so we don't do it for the adium Plugin.
TODO: there has to be a better way to do this, figure out how.
*/
#ifndef __ADIUM_
p2tgl_got_chat_in(conn->TLS, TGL_MK_CHAT(id), TGL_MK_USER(conn->TLS->our_id), message,
PURPLE_MESSAGE_RECV, time(NULL));
PURPLE_MESSAGE_RECV, time(NULL));
#endif
return 1;
}
@ -835,7 +860,7 @@ static void tgprpl_convo_closed (PurpleConnection * gc, const char *who){
static void tgprpl_set_buddy_icon (PurpleConnection * gc, PurpleStoredImage * img) {
debug ("tgprpl_set_buddy_icon()\n");
telegram_conn *conn = purple_connection_get_protocol_data (gc);
connection_data *conn = purple_connection_get_protocol_data (gc);
if (purple_imgstore_get_filename (img)) {
char* filename = g_strdup_printf ("%s/icons/%s", purple_user_dir(), purple_imgstore_get_filename (img));
debug (filename);
@ -906,9 +931,9 @@ static PurplePluginProtocolInfo prpl_info = {
NULL, // set_idle
NULL, // change_passwd
tgprpl_add_buddy,
tgprpl_add_buddies,
NULL, // add_buddies
tgprpl_remove_buddy,
tgprpl_remove_buddies,
NULL, // remove_buddies
NULL, // add_permit
tgprpl_add_deny,
NULL, // rem_permit
@ -964,8 +989,7 @@ static PurplePluginProtocolInfo prpl_info = {
static void tgprpl_init (PurplePlugin *plugin) {
PurpleAccountOption *opt;
opt = purple_account_option_bool_new("Compatibility Mode (read SMS code from settings)",
"compat-verification", 0);
opt = purple_account_option_bool_new("Fallback SMS verification", "compat-verification", 0);
prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, opt);
_telegram_protocol = plugin;

View file

@ -28,7 +28,6 @@
#define TG_VERSION "0.5"
#define TG_BUILD "10"
#include <glib.h>
#include <notify.h>
#include <plugin.h>
#include <version.h>
@ -38,28 +37,6 @@
#define TGP_APP_HASH "99428c722d0ed59b9cd844e4577cb4bb"
#define TGP_APP_ID 16154
typedef struct {
struct tgl_state *TLS;
char *hash;
PurpleAccount *pa;
PurpleConnection *gc;
int updated;
GQueue *new_messages;
GHashTable *joining_chats;
guint timer;
int in_fallback_chat;
} telegram_conn;
struct download_desc {
int type;
void *data;
};
struct message_text {
struct tgl_message *M;
char *text;
};
void on_chat_get_info (struct tgl_state *TLS, void *extra, int success, struct tgl_chat *C);
void on_ready (struct tgl_state *TLS);
extern const char *pk_path;

2
tgl

@ -1 +1 @@
Subproject commit d78ebeb6c61b63755052ef6d0f08113396173657
Subproject commit cebe2822a2620961692ac45b0ea2ee99d396c5fb

View file

@ -19,12 +19,17 @@
*/
#include "telegram-purple.h"
#include "tgp-2prpl.h"
#include "tgp-structs.h"
#include <server.h>
#include <tgl.h>
#include <msglog.h>
#include <assert.h>
/*
tgp-2prpl.c: Libpurple functions that can be called with tgl data types
*/
static void sanitize_alias(char *buffer) {
size_t len = strlen(buffer);
gchar *curr;
@ -56,11 +61,11 @@ static int user_get_alias (tgl_peer_t *user, char *buffer, int maxlen) {
}
PurpleAccount *tg_get_acc (struct tgl_state *TLS) {
return (PurpleAccount *) ((telegram_conn *)TLS->ev_base)->pa;
return (PurpleAccount *) ((connection_data *)TLS->ev_base)->pa;
}
PurpleConnection *tg_get_conn (struct tgl_state *TLS) {
return (PurpleConnection *) ((telegram_conn *)TLS->ev_base)->gc;
return (PurpleConnection *) ((connection_data *)TLS->ev_base)->gc;
}
static char *peer_strdup_id(tgl_peer_id_t user) {
@ -85,6 +90,12 @@ char *p2tgl_strdup_alias(tgl_peer_t *user) {
return g_alias;
}
int p2tgl_status_is_present (PurpleStatus *status)
{
const char *name = purple_status_get_id (status);
return !(strcmp (name, "unavailable") == 0 || strcmp (name, "away") == 0);
}
static PurpleChat *blist_find_chat_by_hasht_cond(PurpleConnection *gc,
int (*fn)(GHashTable *hasht, void *data), void *data) {
PurpleAccount *account = purple_connection_get_account(gc);
@ -105,12 +116,16 @@ static PurpleChat *blist_find_chat_by_hasht_cond(PurpleConnection *gc,
}
static int hasht_cmp_id(GHashTable *hasht, void *data) {
return !strcmp(g_hash_table_lookup(hasht, "id"), *((char **)data));
gpointer id = g_hash_table_lookup(hasht, "id");
if (!id || !data) {
return 0;
}
return !strcmp(id, ((char *)data));
}
PurpleConversation *p2tgl_got_joined_chat (struct tgl_state *TLS, struct tgl_chat *chat) {
telegram_conn *conn = TLS->ev_base;
connection_data *conn = TLS->ev_base;
gchar *alias = p2tgl_strdup_alias((tgl_peer_t *)chat);
PurpleConversation *conv = serv_got_joined_chat(conn->gc, tgl_get_peer_id(chat->id), alias);
@ -181,7 +196,7 @@ PurpleBuddy *p2tgl_buddy_update (struct tgl_state *TLS, tgl_peer_t *user, unsign
if (!b) {
b = p2tgl_buddy_new (TLS, user);
}
if (flags & TGL_UPDATE_NAME) {
if (flags & (TGL_UPDATE_NAME | TGL_UPDATE_REAL_NAME | TGL_UPDATE_USERNAME)) {
debug ("Update username for id%d (name %s %s)\n", tgl_get_peer_id (user->id), user->user.first_name, user->user.last_name);
char *alias = p2tgl_strdup_alias (user);
purple_blist_alias_buddy(b, alias);
@ -248,7 +263,7 @@ PurpleChat *p2tgl_chat_new (struct tgl_state *TLS, struct tgl_chat *chat) {
PurpleChat *p2tgl_chat_find (struct tgl_state *TLS, tgl_peer_id_t id) {
char *name = peer_strdup_id(id);
PurpleChat *c = blist_find_chat_by_hasht_cond(tg_get_conn(TLS), hasht_cmp_id, &name);
PurpleChat *c = blist_find_chat_by_hasht_cond(tg_get_conn(TLS), hasht_cmp_id, name);
g_free(name);
return c;
}

View file

@ -36,6 +36,7 @@ tgl_peer_t *p2tgl_get_peer (tgl_peer_id_t peer);
tgl_peer_t *p2tgl_get_peer_by_id (int id);
char *p2tgl_strdup_alias(tgl_peer_t *user);
int p2tgl_status_is_present (PurpleStatus *status);
PurpleConversation *p2tgl_got_joined_chat (struct tgl_state *TLS, struct tgl_chat *chat);
void p2tgl_got_chat_invite (PurpleConnection *gc, tgl_peer_t *chat, tgl_peer_id_t inviter, const char *message);

View file

@ -42,6 +42,7 @@
#include <time.h>
#include "tgp-net.h"
#include "tgp-structs.h"
#include <tgl.h>
#include <tgl-inner.h>
@ -83,6 +84,7 @@ static int ping_alarm (gpointer arg) {
static void stop_ping_timer (struct connection *c) {
purple_timeout_remove (c->ping_ev);
c->ping_ev = -1;
}
static void start_ping_timer (struct connection *c) {
@ -333,7 +335,7 @@ struct connection *tgln_create_connection (struct tgl_state *TLS, const char *ho
c->conn_timeout = MIN_EXP_TIMEOUT;
telegram_conn *conn = TLS->ev_base;
connection_data *conn = TLS->ev_base;
c->prpl_data = purple_proxy_connect (conn->gc, conn->pa, host, port, net_on_connected, c);
return c;
@ -346,8 +348,9 @@ static void restart_connection (struct connection *c) {
return;
}
telegram_conn *conn = TLS->ev_base;
c->prpl_data = purple_proxy_connect (conn->gc, conn->pa, c->ip, c->port, net_on_connected, c);
connection_data *conn = TLS->ev_base;
purple_connection_error_reason (conn->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, "Lost connection with server");
// c->prpl_data = purple_proxy_connect (conn->gc, conn->pa, c->ip, c->port, net_on_connected, c);
}
static void fail_connection (struct connection *c) {
@ -383,7 +386,7 @@ static void fail_connection (struct connection *c) {
c->out_bytes = c->in_bytes = 0;
if (c->state == conn_ready) {
telegram_conn *conn = TLS->ev_base;
connection_data *conn = TLS->ev_base;
purple_connection_error_reason(conn->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, "connection fail");
}
c->prpl_data = NULL; // Did not find any destroy code. What should be done here?
@ -457,7 +460,9 @@ static void try_rpc_read (struct connection *c) {
len *= 4;
int op;
assert (tgln_read_in_lookup (c, &op, 4) == 4);
c->methods->execute (TLS, c, op, len);
if (c->methods->execute (TLS, c, op, len) < 0) {
return;
}
}
}
@ -593,6 +598,7 @@ static void tgln_free (struct connection *c) {
purple_input_remove (c->write_ev);
}
if (c->fd >= 0) { close (c->fd); }
c->fd = -1;
}

122
tgp-structs.c Normal file
View file

@ -0,0 +1,122 @@
/*
This file is part of telegram-purple
This program 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 2 of the License, or
(at your option) any later version.
This program 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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
Copyright Matthias Jentsch 2014
*/
#include "tgp-structs.h"
#include "purple.h"
#include "msglog.h"
#include <glib.h>
#include <tgl.h>
/*
tgp-structs.c: Structs that are only used internally by the protocol plugin
*/
void pending_reads_free_cb (gpointer data)
{
free (data);
}
static void pending_reads_cb (struct tgl_state *TLS, void *extra, int success)
{
debug ("ack state: %d", success);
}
static gint pending_reads_compare (gconstpointer a, gconstpointer b)
{
return !memcmp ((tgl_peer_id_t *)a, (tgl_peer_id_t *)b, sizeof(tgl_peer_id_t));
}
void pending_reads_send_all (GQueue *queue, struct tgl_state *TLS)
{
debug ("send all pending ack");
tgl_peer_id_t *pending;
while ((pending = (tgl_peer_id_t*) g_queue_pop_head(queue))) {
tgl_do_mark_read (TLS, *pending, pending_reads_cb, queue);
debug ("tgl_do_mark_read (%d)", pending->id);
free (pending);
}
}
void pending_reads_add (GQueue *queue, tgl_peer_id_t id)
{
tgl_peer_id_t *copy = malloc (sizeof(tgl_peer_id_t));
*copy = id;
if (! g_queue_find_custom (queue, copy, pending_reads_compare)) {
g_queue_push_tail (queue, copy);
}
}
struct message_text *message_text_init (struct tgl_message *M, gchar *text)
{
struct message_text *mt = malloc (sizeof (struct message_text));
mt->M = M;
mt->text = text ? g_strdup (text) : text;
return mt;
}
void message_text_free (gpointer data)
{
struct message_text *mt = (struct message_text*)data;
if (mt->text) {
g_free (mt->text);
}
free (mt);
}
static void used_image_free (gpointer data)
{
int id = GPOINTER_TO_INT(data);
purple_imgstore_unref_by_id (id);
debug ("used_image: unref %d", id);
}
void used_images_add (connection_data *data, gint imgid)
{
data->used_images = g_list_append (data->used_images, GINT_TO_POINTER(imgid));
debug ("used_image: add %d", imgid);
}
connection_data *connection_data_init (struct tgl_state *TLS, PurpleConnection *gc, PurpleAccount *pa)
{
connection_data *conn = g_new0 (connection_data, 1);
conn->TLS = TLS;
conn->gc = gc;
conn->pa = pa;
conn->new_messages = g_queue_new ();
conn->pending_reads = g_queue_new ();
conn->joining_chats = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
return conn;
}
void *connection_data_free (connection_data *conn)
{
purple_timeout_remove(conn->timer);
g_queue_free_full (conn->pending_reads, pending_reads_free_cb);
g_queue_free_full (conn->new_messages, message_text_free);
g_hash_table_destroy (conn->joining_chats);
g_list_free_full (conn->used_images, used_image_free);
tgl_free_all (conn->TLS);
free (conn);
return NULL;
}

64
tgp-structs.h Normal file
View file

@ -0,0 +1,64 @@
/*
This file is part of telegram-purple
This program 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 2 of the License, or
(at your option) any later version.
This program 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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
Copyright Matthias Jentsch 2014
*/
#ifndef __telegram_adium__tgp_data__
#define __telegram_adium__tgp_data__
#include "purple.h"
#include <tgl.h>
#include <glib.h>
typedef struct {
struct tgl_state *TLS;
char *hash;
PurpleAccount *pa;
PurpleConnection *gc;
int updated;
GQueue *new_messages;
GQueue *pending_reads;
GList *used_images;
GHashTable *joining_chats;
guint timer;
int in_fallback_chat;
} connection_data;
struct download_desc {
int type;
void *data;
};
struct message_text {
struct tgl_message *M;
char *text;
};
void pending_reads_send_all (GQueue *queue, struct tgl_state *TLS);
void pending_reads_add (GQueue *queue, tgl_peer_id_t id);
struct message_text *message_text_init (struct tgl_message *M, gchar *text);
void message_text_free (gpointer data);
void used_images_add (connection_data *data, gint imgid);
void *connection_data_free (connection_data *conn);
connection_data *connection_data_init (struct tgl_state *TLS, PurpleConnection *gc, PurpleAccount *pa);
#endif