summaryrefslogtreecommitdiff
path: root/libpurple/protocols/gg/gg.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpurple/protocols/gg/gg.c')
-rw-r--r--libpurple/protocols/gg/gg.c493
1 files changed, 299 insertions, 194 deletions
diff --git a/libpurple/protocols/gg/gg.c b/libpurple/protocols/gg/gg.c
index 5522ce04b8..4ef1e45511 100644
--- a/libpurple/protocols/gg/gg.c
+++ b/libpurple/protocols/gg/gg.c
@@ -61,7 +61,6 @@ static PurplePlugin *my_protocol = NULL;
*
* @return Zero if proxy setup is valid, otherwise -1.
*/
-/* static int ggp_setup_proxy(PurpleAccount *account) {{{ */
static int ggp_setup_proxy(PurpleAccount *account)
{
PurpleProxyInfo *gpi;
@@ -88,11 +87,7 @@ static int ggp_setup_proxy(PurpleAccount *account)
return 0;
}
-/* }}} */
-/*
- */
-/* static void ggp_async_token_handler(gpointer _gc, gint fd, PurpleInputCondition cond) {{{ */
static void ggp_async_token_handler(gpointer _gc, gint fd, PurpleInputCondition cond)
{
PurpleConnection *gc = _gc;
@@ -157,11 +152,7 @@ static void ggp_async_token_handler(gpointer _gc, gint fd, PurpleInputCondition
token->cb = NULL;
cb(gc);
}
-/* }}} */
-/*
- */
-/* static void ggp_token_request(PurpleConnection *gc, GGPTokenCallback cb) {{{ */
static void ggp_token_request(PurpleConnection *gc, GGPTokenCallback cb)
{
PurpleAccount *account;
@@ -199,7 +190,6 @@ static void ggp_token_request(PurpleConnection *gc, GGPTokenCallback cb)
*
* @param Current action handler.
*/
-/* static void ggp_action_buddylist_get(PurplePluginAction *action) {{{ */
static void ggp_action_buddylist_get(PurplePluginAction *action)
{
PurpleConnection *gc = (PurpleConnection *)action->context;
@@ -209,14 +199,12 @@ static void ggp_action_buddylist_get(PurplePluginAction *action)
gg_userlist_request(info->session, GG_USERLIST_GET, NULL);
}
-/* }}} */
/**
* Upload the buddylist to the server.
*
* @param action Current action handler.
*/
-/* static void ggp_action_buddylist_put(PurplePluginAction *action) {{{ */
static void ggp_action_buddylist_put(PurplePluginAction *action)
{
PurpleConnection *gc = (PurpleConnection *)action->context;
@@ -232,14 +220,12 @@ static void ggp_action_buddylist_put(PurplePluginAction *action)
gg_userlist_request(info->session, GG_USERLIST_PUT, buddylist);
g_free(buddylist);
}
-/* }}} */
/**
* Delete buddylist from the server.
*
* @param action Current action handler.
*/
-/* static void ggp_action_buddylist_delete(PurplePluginAction *action) {{{ */
static void ggp_action_buddylist_delete(PurplePluginAction *action)
{
PurpleConnection *gc = (PurpleConnection *)action->context;
@@ -249,11 +235,7 @@ static void ggp_action_buddylist_delete(PurplePluginAction *action)
gg_userlist_request(info->session, GG_USERLIST_PUT, NULL);
}
-/* }}} */
-/*
- */
-/* static void ggp_callback_buddylist_save_ok(PurpleConnection *gc, const char *file) {{{ */
static void ggp_callback_buddylist_save_ok(PurpleConnection *gc, const char *filename)
{
PurpleAccount *account = purple_connection_get_account(gc);
@@ -284,11 +266,7 @@ static void ggp_callback_buddylist_save_ok(PurpleConnection *gc, const char *fil
g_free(buddylist);
}
-/* }}} */
-/*
- */
-/* static void ggp_callback_buddylist_load_ok(PurpleConnection *gc, gchar *file) {{{ */
static void ggp_callback_buddylist_load_ok(PurpleConnection *gc, gchar *file)
{
PurpleAccount *account = purple_connection_get_account(gc);
@@ -334,11 +312,7 @@ static void ggp_action_buddylist_save(PurplePluginAction *action)
purple_connection_get_account(gc), NULL, NULL,
gc);
}
-/* }}} */
-/*
- */
-/* static void ggp_action_buddylist_load(PurplePluginAction *action) {{{ */
static void ggp_action_buddylist_load(PurplePluginAction *action)
{
PurpleConnection *gc = (PurpleConnection *)action->context;
@@ -349,11 +323,7 @@ static void ggp_action_buddylist_load(PurplePluginAction *action)
purple_connection_get_account(gc), NULL, NULL,
gc);
}
-/* }}} */
-/*
- */
-/* static void ggp_callback_register_account_ok(PurpleConnection *gc, PurpleRequestFields *fields) {{{ */
static void ggp_callback_register_account_ok(PurpleConnection *gc,
PurpleRequestFields *fields)
{
@@ -435,11 +405,7 @@ exit_err:
g_free(token->id);
g_free(token);
}
-/* }}} */
-/*
- */
-/* static void ggp_callback_register_account_cancel(PurpleConnection *gc, PurpleRequestFields *fields) {{{ */
static void ggp_callback_register_account_cancel(PurpleConnection *gc,
PurpleRequestFields *fields)
{
@@ -453,11 +419,7 @@ static void ggp_callback_register_account_cancel(PurpleConnection *gc,
g_free(token);
}
-/* }}} */
-/*
- */
-/* static void ggp_register_user_dialog(PurpleConnection *gc) {{{ */
static void ggp_register_user_dialog(PurpleConnection *gc)
{
PurpleAccount *account;
@@ -510,13 +472,9 @@ static void ggp_register_user_dialog(PurpleConnection *gc)
purple_connection_get_account(gc), NULL, NULL,
gc);
}
-/* }}} */
/* ----- PUBLIC DIRECTORY SEARCH ---------------------------------------- */
-/*
- */
-/* static void ggp_callback_show_next(PurpleConnection *gc, GList *row, gpointer user_data) {{{ */
static void ggp_callback_show_next(PurpleConnection *gc, GList *row, gpointer user_data)
{
GGPInfo *info = gc->proto_data;
@@ -533,21 +491,13 @@ static void ggp_callback_show_next(PurpleConnection *gc, GList *row, gpointer us
ggp_search_add(info->searches, seq, form);
purple_debug_info("gg", "ggp_callback_show_next(): Added seq %u", seq);
}
-/* }}} */
-/*
- */
-/* static void ggp_callback_add_buddy(PurpleConnection *gc, GList *row, gpointer user_data) {{{ */
static void ggp_callback_add_buddy(PurpleConnection *gc, GList *row, gpointer user_data)
{
purple_blist_request_add_buddy(purple_connection_get_account(gc),
g_list_nth_data(row, 0), NULL, NULL);
}
-/* }}} */
-/*
- */
-/* static void ggp_callback_im(PurpleConnection *gc, GList *row, gpointer user_data) {{{ */
static void ggp_callback_im(PurpleConnection *gc, GList *row, gpointer user_data)
{
PurpleAccount *account;
@@ -560,11 +510,7 @@ static void ggp_callback_im(PurpleConnection *gc, GList *row, gpointer user_data
conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, name);
purple_conversation_present(conv);
}
-/* }}} */
-/*
- */
-/* static void ggp_callback_find_buddies(PurpleConnection *gc, PurpleRequestFields *fields) {{{ */
static void ggp_callback_find_buddies(PurpleConnection *gc, PurpleRequestFields *fields)
{
GGPInfo *info = gc->proto_data;
@@ -611,11 +557,7 @@ static void ggp_callback_find_buddies(PurpleConnection *gc, PurpleRequestFields
ggp_search_add(info->searches, seq, form);
purple_debug_info("gg", "ggp_callback_find_buddies(): Added seq %u", seq);
}
-/* }}} */
-/*
- */
-/* static void ggp_find_buddies(PurplePluginAction *action) {{{ */
static void ggp_find_buddies(PurplePluginAction *action)
{
PurpleConnection *gc = (PurpleConnection *)action->context;
@@ -672,13 +614,9 @@ static void ggp_find_buddies(PurplePluginAction *action)
purple_connection_get_account(gc), NULL, NULL,
gc);
}
-/* }}} */
/* ----- CHANGE PASSWORD ------------------------------------------------ */
-/*
- */
-/* static void ggp_callback_change_passwd_ok(PurpleConnection *gc, PurpleRequestFields *fields) {{{ */
static void ggp_callback_change_passwd_ok(PurpleConnection *gc, PurpleRequestFields *fields)
{
PurpleAccount *account;
@@ -750,11 +688,7 @@ exit_err:
g_free(info->token->data);
g_free(info->token);
}
-/* }}} */
-/*
- */
-/* static void ggp_change_passwd_dialog(PurpleConnection *gc) {{{ */
static void ggp_change_passwd_dialog(PurpleConnection *gc)
{
PurpleRequestFields *fields;
@@ -811,24 +745,16 @@ static void ggp_change_passwd_dialog(PurpleConnection *gc)
g_free(msg);
}
-/* }}} */
-/*
- */
-/* static void ggp_change_passwd(PurplePluginAction *action) {{{ */
static void ggp_change_passwd(PurplePluginAction *action)
{
PurpleConnection *gc = (PurpleConnection *)action->context;
ggp_token_request(gc, ggp_change_passwd_dialog);
}
-/* }}} */
/* ----- CONFERENCES ---------------------------------------------------- */
-/*
- */
-/* static void ggp_callback_add_to_chat_ok(PurpleConnection *gc, PurpleRequestFields *fields) {{{ */
static void ggp_callback_add_to_chat_ok(PurpleConnection *gc, PurpleRequestFields *fields)
{
PurpleRequestField *field;
@@ -842,11 +768,7 @@ static void ggp_callback_add_to_chat_ok(PurpleConnection *gc, PurpleRequestField
ggp_confer_participants_add_uin(gc, sel->data,
GPOINTER_TO_INT(purple_request_field_list_get_data(field, sel->data)));
}
-/* }}} */
-/*
- */
-/* static void ggp_bmenu_add_to_chat(PurpleBlistNode *node, gpointer ignored) {{{ */
static void ggp_bmenu_add_to_chat(PurpleBlistNode *node, gpointer ignored)
{
PurpleBuddy *buddy;
@@ -889,13 +811,9 @@ static void ggp_bmenu_add_to_chat(PurpleBlistNode *node, gpointer ignored)
gc);
g_free(msg);
}
-/* }}} */
/* ----- BLOCK BUDDIES -------------------------------------------------- */
-/*
- */
-/* static void ggp_bmenu_block(PurpleBlistNode *node, gpointer ignored) {{{ */
static void ggp_bmenu_block(PurpleBlistNode *node, gpointer ignored)
{
PurpleConnection *gc;
@@ -921,7 +839,6 @@ static void ggp_bmenu_block(PurpleBlistNode *node, gpointer ignored)
purple_debug_info("gg", "send: uin=%d; mode=BLOCKED\n", uin);
}
}
-/* }}} */
/* ---------------------------------------------------------------------- */
/* ----- INTERNAL CALLBACKS --------------------------------------------- */
@@ -940,7 +857,6 @@ static int ggp_to_gg_status(PurpleStatus *status, char **msg);
* @param status ID of the status.
* @param descr Description.
*/
-/* static void ggp_generic_status_handler(PurpleConnection *gc, uin_t uin, int status, const char *descr) {{{ */
static void ggp_generic_status_handler(PurpleConnection *gc, uin_t uin,
int status, const char *descr)
{
@@ -980,11 +896,7 @@ static void ggp_generic_status_handler(PurpleConnection *gc, uin_t uin,
g_free(from);
g_free(msg);
}
-/* }}} */
-/*
- */
-/* static void ggp_sr_close_cb(gpointer user_data) {{{ */
static void ggp_sr_close_cb(gpointer user_data)
{
GGPSearchForm *form = user_data;
@@ -994,7 +906,6 @@ static void ggp_sr_close_cb(gpointer user_data)
purple_debug_info("gg", "ggp_sr_close_cb(): Removed seq %u", form->seq);
ggp_search_form_destroy(form);
}
-/* }}} */
/**
* Translate a status' ID to a more user-friendly name.
@@ -1003,7 +914,6 @@ static void ggp_sr_close_cb(gpointer user_data)
*
* @return The user-friendly name of the status.
*/
-/* static const char *ggp_status_by_id(unsigned int id) {{{ */
static const char *ggp_status_by_id(unsigned int id)
{
const char *st;
@@ -1026,11 +936,7 @@ static const char *ggp_status_by_id(unsigned int id)
return st;
}
-/* }}} */
-/*
- */
-/* static void ggp_pubdir_handle_info(PurpleConnection *gc, gg_pubdir50_t req, GGPSearchForm *form) {{{ */
static void ggp_pubdir_handle_info(PurpleConnection *gc, gg_pubdir50_t req,
GGPSearchForm *form)
{
@@ -1089,11 +995,7 @@ static void ggp_pubdir_handle_info(PurpleConnection *gc, gg_pubdir50_t req,
g_free(who);
purple_notify_user_info_destroy(user_info);
}
-/* }}} */
-/*
- */
-/* static void ggp_pubdir_handle_full(PurpleConnection *gc, gg_pubdir50_t req, GGPSearchForm *form) {{{ */
static void ggp_pubdir_handle_full(PurpleConnection *gc, gg_pubdir50_t req,
GGPSearchForm *form)
{
@@ -1193,11 +1095,7 @@ static void ggp_pubdir_handle_full(PurpleConnection *gc, gg_pubdir50_t req,
purple_notify_searchresults_new_rows(gc, results, form->window);
}
}
-/* }}} */
-/*
- */
-/* static void ggp_pubdir_reply_handler(PurpleConnection *gc, gg_pubdir50_t req) {{{ */
static void ggp_pubdir_reply_handler(PurpleConnection *gc, gg_pubdir50_t req)
{
GGPInfo *info = gc->proto_data;
@@ -1236,15 +1134,56 @@ static void ggp_pubdir_reply_handler(PurpleConnection *gc, gg_pubdir50_t req)
break;
}
}
-/* }}} */
+
+static void ggp_recv_image_handler(PurpleConnection *gc, const struct gg_event *ev)
+{
+ gint imgid = 0;
+ GGPInfo *info = gc->proto_data;
+ GList *entry = g_list_first(info->pending_richtext_messages);
+ gchar *handlerid = g_strdup_printf("IMGID_HANDLER-%i", ev->event.image_reply.crc32);
+
+ imgid = purple_imgstore_add_with_id(
+ g_memdup(ev->event.image_reply.image, ev->event.image_reply.size),
+ ev->event.image_reply.size,
+ ev->event.image_reply.filename);
+
+ purple_debug_info("gg", "ggp_recv_image_handler: got image with crc32: %u\n", ev->event.image_reply.crc32);
+
+ while(entry) {
+ if (strstr((gchar *)entry->data, handlerid) != NULL) {
+ gchar **split = g_strsplit((gchar *)entry->data, handlerid, 3);
+ gchar *text = g_strdup_printf("%s%i%s", split[0], imgid, split[1]);
+ purple_debug_info("gg", "ggp_recv_image_handler: found message matching crc32: %s\n", (gchar *)entry->data);
+ g_strfreev(split);
+ info->pending_richtext_messages = g_list_remove(info->pending_richtext_messages, entry->data);
+ /* We don't have any more images to download */
+ if (strstr(text, "<IMG ID=\"IMGID_HANDLER") == NULL) {
+ gchar *buf = g_strdup_printf("%lu", (unsigned long int)ev->event.msg.sender);
+ serv_got_im(gc, buf, text, PURPLE_MESSAGE_IMAGES, ev->event.msg.time);
+ g_free(buf);
+ purple_debug_info("gg", "ggp_recv_image_handler: richtext message: %s\n", text);
+ g_free(text);
+ break;
+ }
+ info->pending_richtext_messages = g_list_append(info->pending_richtext_messages, text);
+ break;
+ }
+ entry = g_list_next(entry);
+ }
+ g_free(handlerid);
+
+ return;
+}
+
/**
* Dispatch a message received from a buddy.
*
* @param gc PurpleConnection.
* @param ev Gadu-Gadu event structure.
+ *
+ * Image receiving, some code borrowed from Kadu http://www.kadu.net
*/
-/* static void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event *ev) {{{ */
static void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event *ev)
{
GGPInfo *info = gc->proto_data;
@@ -1261,7 +1200,109 @@ static void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event
msg = g_markup_escape_text(tmp, -1);
g_free(tmp);
- purple_debug_info("gg", "msg form (%s): %s (class = %d; rcpt_count = %d)\n",
+ /* We got richtext message */
+ if (ev->event.msg.formats_length)
+ {
+ gboolean got_image = FALSE, bold = FALSE, italic = FALSE, under = FALSE;
+ char *cformats = (char *)ev->event.msg.formats;
+ char *cformats_end = cformats + ev->event.msg.formats_length;
+ gint increased_len = 0;
+ struct gg_msg_richtext_format *actformat;
+ struct gg_msg_richtext_image *actimage;
+ GString *message = g_string_new(msg);
+ gchar *handlerid;
+
+ purple_debug_info("gg", "ggp_recv_message_handler: richtext msg from (%s): %s %i formats\n", from, msg, ev->event.msg.formats_length);
+
+ while (cformats < cformats_end)
+ {
+ gint byteoffset;
+ actformat = (struct gg_msg_richtext_format *)cformats;
+ cformats += sizeof(struct gg_msg_richtext_format);
+ byteoffset = g_utf8_offset_to_pointer(message->str, actformat->position + increased_len) - message->str;
+
+ if(actformat->position == 0 && actformat->font == 0) {
+ purple_debug_warning("gg", "ggp_recv_message_handler: bogus formatting (inc: %i)\n", increased_len);
+ continue;
+ }
+ purple_debug_info("gg", "ggp_recv_message_handler: format at pos: %i, image:%i, bold:%i, italic: %i, under:%i (inc: %i)\n",
+ actformat->position,
+ (actformat->font & GG_FONT_IMAGE) != 0,
+ (actformat->font & GG_FONT_BOLD) != 0,
+ (actformat->font & GG_FONT_ITALIC) != 0,
+ (actformat->font & GG_FONT_UNDERLINE) != 0,
+ increased_len);
+
+ if (actformat->font & GG_FONT_IMAGE) {
+ got_image = TRUE;
+ actimage = (struct gg_msg_richtext_image*)(cformats);
+ cformats += sizeof(struct gg_msg_richtext_image);
+ purple_debug_info("gg", "ggp_recv_message_handler: image received, size: %d, crc32: %i\n", actimage->size, actimage->crc32);
+
+ /* Checking for errors, image size shouldn't be
+ * larger than 255.000 bytes */
+ if (actimage->size > 255000) {
+ purple_debug_warning("gg", "ggp_recv_message_handler: received image large than 255 kb\n");
+ continue;
+ }
+
+ gg_image_request(info->session, ev->event.msg.sender,
+ actimage->size, actimage->crc32);
+
+ handlerid = g_strdup_printf("<IMG ID=\"IMGID_HANDLER-%i\">", actimage->crc32);
+ g_string_insert(message, byteoffset, handlerid);
+ increased_len += strlen(handlerid);
+ g_free(handlerid);
+ continue;
+ }
+
+ if (actformat->font & GG_FONT_BOLD) {
+ if (bold == FALSE) {
+ g_string_insert(message, byteoffset, "<b>");
+ increased_len += 3;
+ bold = TRUE;
+ }
+ } else if (bold) {
+ g_string_insert(message, byteoffset, "</b>");
+ increased_len += 4;
+ bold = FALSE;
+ }
+
+ if (actformat->font & GG_FONT_ITALIC) {
+ if (italic == FALSE) {
+ g_string_insert(message, byteoffset, "<i>");
+ increased_len += 3;
+ italic = TRUE;
+ }
+ } else if (italic) {
+ g_string_insert(message, byteoffset, "</i>");
+ increased_len += 4;
+ italic = FALSE;
+ }
+
+ if (actformat->font & GG_FONT_UNDERLINE) {
+ if (under == FALSE) {
+ g_string_insert(message, byteoffset, "<u>");
+ increased_len += 3;
+ under = TRUE;
+ }
+ } else if (under) {
+ g_string_insert(message, byteoffset, "</u>");
+ increased_len += 4;
+ under = FALSE;
+ }
+ }
+
+ msg = message->str;
+ g_string_free(message, FALSE);
+
+ if (got_image) {
+ info->pending_richtext_messages = g_list_append(info->pending_richtext_messages, msg);
+ return;
+ }
+ }
+
+ purple_debug_info("gg", "ggp_recv_message_handler: msg from (%s): %s (class = %d; rcpt_count = %d)\n",
from, msg, ev->event.msg.msgclass,
ev->event.msg.recipients_count);
@@ -1298,11 +1339,32 @@ static void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event
g_free(msg);
g_free(from);
}
-/* }}} */
-/*
- */
-/* static void ggp_callback_recv(gpointer _gc, gint fd, PurpleInputCondition cond) {{{ */
+static void ggp_send_image_handler(PurpleConnection *gc, const struct gg_event *ev)
+{
+ GGPInfo *info = gc->proto_data;
+ PurpleStoredImage *image;
+ gint imgid = GPOINTER_TO_INT(g_hash_table_lookup(info->pending_images, &ev->event.image_request.crc32));
+
+ purple_debug_info("gg", "ggp_send_image_handler: image request received, crc32: %u\n", ev->event.image_request.crc32);
+
+ if(imgid)
+ {
+ if((image = purple_imgstore_find_by_id(imgid))) {
+ gint image_size = purple_imgstore_get_size(image);
+ gconstpointer image_bin = purple_imgstore_get_data(image);
+ const char *image_filename = purple_imgstore_get_filename(image);
+
+ purple_debug_info("gg", "ggp_send_image_handler: sending image imgid: %i, crc: %u\n", imgid, ev->event.image_request.crc32);
+ gg_image_reply(info->session, (unsigned long int)ev->event.image_request.sender, image_filename, image_bin, image_size);
+ purple_imgstore_unref(image);
+ } else {
+ purple_debug_error("gg", "ggp_send_image_handler: image imgid: %i, crc: %u in hash but not found in imgstore!\n", imgid, ev->event.image_request.crc32);
+ }
+ g_hash_table_remove(info->pending_images, &ev->event.image_request.crc32);
+ }
+}
+
static void ggp_callback_recv(gpointer _gc, gint fd, PurpleInputCondition cond)
{
PurpleConnection *gc = _gc;
@@ -1327,11 +1389,18 @@ static void ggp_callback_recv(gpointer _gc, gint fd, PurpleInputCondition cond)
ggp_recv_message_handler(gc, ev);
break;
case GG_EVENT_ACK:
+ /* Changing %u to %i fixes compiler warning */
purple_debug_info("gg",
- "message sent to: %u, delivery status=%d, seq=%d\n",
+ "ggp_callback_recv: message sent to: %i, delivery status=%d, seq=%d\n",
ev->event.ack.recipient, ev->event.ack.status,
ev->event.ack.seq);
break;
+ case GG_EVENT_IMAGE_REPLY:
+ ggp_recv_image_handler(gc, ev);
+ break;
+ case GG_EVENT_IMAGE_REQUEST:
+ ggp_send_image_handler(gc, ev);
+ break;
case GG_EVENT_NOTIFY:
case GG_EVENT_NOTIFY_DESCR:
{
@@ -1423,11 +1492,7 @@ static void ggp_callback_recv(gpointer _gc, gint fd, PurpleInputCondition cond)
gg_free_event(ev);
}
-/* }}} */
-/*
- */
-/* static void ggp_async_login_handler(gpointer _gc, gint fd, PurpleInputCondition cond) {{{ */
static void ggp_async_login_handler(gpointer _gc, gint fd, PurpleInputCondition cond)
{
PurpleConnection *gc = _gc;
@@ -1516,20 +1581,16 @@ static void ggp_async_login_handler(gpointer _gc, gint fd, PurpleInputCondition
gg_free_event(ev);
}
-/* }}} */
/* ---------------------------------------------------------------------- */
/* ----- PurplePluginProtocolInfo ----------------------------------------- */
/* ---------------------------------------------------------------------- */
-/* static const char *ggp_list_icon(PurpleAccount *account, PurpleBuddy *buddy) {{{ */
static const char *ggp_list_icon(PurpleAccount *account, PurpleBuddy *buddy)
{
return "gadu-gadu";
}
-/* }}} */
-/* static char *ggp_status_text(PurpleBuddy *b) {{{ */
static char *ggp_status_text(PurpleBuddy *b)
{
PurpleStatus *status;
@@ -1555,20 +1616,21 @@ static char *ggp_status_text(PurpleBuddy *b)
return text;
}
}
-/* }}} */
-/* static void ggp_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) {{{ */
static void ggp_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
{
PurpleStatus *status;
char *text, *tmp;
- const char *msg, *name;
+ const char *msg, *name, *alias;
g_return_if_fail(b != NULL);
status = purple_presence_get_active_status(purple_buddy_get_presence(b));
msg = purple_status_get_attr_string(status, "message");
name = purple_status_get_name(status);
+ alias = purple_buddy_get_alias(b);
+
+ purple_notify_user_info_add_pair (user_info, _("Alias"), alias);
if (msg != NULL) {
text = g_markup_escape_text(msg, -1);
@@ -1585,9 +1647,7 @@ static void ggp_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gb
purple_notify_user_info_add_pair(user_info, _("Status"), name);
}
}
-/* }}} */
-/* static GList *ggp_status_types(PurpleAccount *account) {{{ */
static GList *ggp_status_types(PurpleAccount *account)
{
PurpleStatusType *type;
@@ -1631,9 +1691,7 @@ static GList *ggp_status_types(PurpleAccount *account)
return types;
}
-/* }}} */
-/* static GList *ggp_blist_node_menu(PurpleBlistNode *node) {{{ */
static GList *ggp_blist_node_menu(PurpleBlistNode *node)
{
PurpleMenuAction *act;
@@ -1663,9 +1721,7 @@ static GList *ggp_blist_node_menu(PurpleBlistNode *node)
return m;
}
-/* }}} */
-/* static GList *ggp_chat_info(PurpleConnection *gc) {{{ */
static GList *ggp_chat_info(PurpleConnection *gc)
{
GList *m = NULL;
@@ -1679,9 +1735,7 @@ static GList *ggp_chat_info(PurpleConnection *gc)
return m;
}
-/* }}} */
-/* static void ggp_login(PurpleAccount *account) {{{ */
static void ggp_login(PurpleAccount *account)
{
PurpleConnection *gc;
@@ -1703,11 +1757,14 @@ static void ggp_login(PurpleAccount *account)
info->chats_count = 0;
info->token = NULL;
info->searches = ggp_search_new();
+ info->pending_richtext_messages = NULL;
+ info->pending_images = g_hash_table_new(g_int_hash, g_int_equal);
gc->proto_data = info;
glp->uin = ggp_get_uin(account);
glp->password = (char *)purple_account_get_password(account);
+ glp->image_size = 255;
presence = purple_account_get_presence(account);
status = purple_presence_get_active_status(presence);
@@ -1727,9 +1784,7 @@ static void ggp_login(PurpleAccount *account)
gc->inpa = purple_input_add(info->session->fd, PURPLE_INPUT_READ,
ggp_async_login_handler, gc);
}
-/* }}} */
-/* static void ggp_close(PurpleConnection *gc) {{{ */
static void ggp_close(PurpleConnection *gc)
{
@@ -1757,6 +1812,8 @@ static void ggp_close(PurpleConnection *gc)
purple_notify_close_with_handle(gc);
ggp_search_destroy(info->searches);
+ g_list_free(info->pending_richtext_messages);
+ g_hash_table_destroy(info->pending_images);
g_free(info);
gc->proto_data = NULL;
}
@@ -1768,25 +1825,108 @@ static void ggp_close(PurpleConnection *gc)
purple_debug_info("gg", "Connection closed.\n");
}
-/* }}} */
-/* static int ggp_send_im(PurpleConnection *gc, const char *who, const char *msg, PurpleMessageFlags flags) {{{ */
static int ggp_send_im(PurpleConnection *gc, const char *who, const char *msg,
PurpleMessageFlags flags)
{
GGPInfo *info = gc->proto_data;
char *tmp, *plain;
- int ret = 0;
-
- if (strlen(msg) == 0) {
+ int ret = 1;
+ unsigned char format[1024];
+ unsigned int format_length = sizeof(struct gg_msg_richtext);
+ gint pos = 0;
+ GData *attribs;
+ const char *start, *end = NULL, *last;
+
+ if (msg == NULL || *msg == '\0') {
return 0;
}
- purple_debug_info("gg", "ggp_send_im: msg = %s\n", msg);
- plain = purple_unescape_html(msg);
+ last = msg;
+
+ /* Check if the message is richtext */
+ /* TODO: Check formatting, too */
+ if(purple_markup_find_tag("img", last, &start, &end, &attribs)) {
+
+ GString *string_buffer = g_string_new(NULL);
+ struct gg_msg_richtext fmt;
+
+ do {
+ PurpleStoredImage *image;
+ const char *id;
+
+ /* Add text before the image */
+ if(start - last) {
+ pos = pos + g_utf8_strlen(last, start - last);
+ g_string_append_len(string_buffer, last, start - last);
+ }
+
+ if((id = g_datalist_get_data(&attribs, "id")) && (image = purple_imgstore_find_by_id(atoi(id)))) {
+ struct gg_msg_richtext_format actformat;
+ struct gg_msg_richtext_image actimage;
+ gint image_size = purple_imgstore_get_size(image);
+ gconstpointer image_bin = purple_imgstore_get_data(image);
+ const char *image_filename = purple_imgstore_get_filename(image);
+ uint32_t crc32 = gg_crc32(0, image_bin, image_size);
+
+ g_hash_table_insert(info->pending_images, &crc32, GINT_TO_POINTER(atoi(id)));
+ purple_imgstore_ref(image);
+ purple_debug_info("gg", "ggp_send_im_richtext: got crc: %i for imgid: %i\n", crc32, atoi(id));
+
+ actformat.font = GG_FONT_IMAGE;
+ actformat.position = pos;
+
+ actimage.unknown1 = 0x0109;
+ actimage.size = gg_fix32(image_size);
+ actimage.crc32 = gg_fix32(crc32);
+
+ if (actimage.size > 255000) {
+ purple_debug_warning("gg", "ggp_send_im_richtext: image over 255kb!\n");
+ continue;
+ }
+
+ purple_debug_info("gg", "ggp_send_im_richtext: adding images to richtext, size: %i, crc32: %u, name: %s\n", actimage.size, actimage.crc32, image_filename);
+
+ memcpy(format + format_length, &actformat, sizeof(actformat));
+ format_length += sizeof(actformat);
+ memcpy(format + format_length, &actimage, sizeof(actimage));
+ format_length += sizeof(actimage);
+ } else {
+ purple_debug_error("gg", "ggp_send_im_richtext: image not found in the image store!");
+ }
+
+ last = end + 1;
+ g_datalist_clear(&attribs);
+
+ } while(purple_markup_find_tag("img", last, &start, &end, &attribs));
+
+ /* Add text after the images */
+ if(last && *last) {
+ pos = pos + g_utf8_strlen(last, -1);
+ g_string_append(string_buffer, last);
+ }
+
+ fmt.flag = 2;
+ fmt.length = format_length - sizeof(fmt);
+ memcpy(format, &fmt, sizeof(fmt));
+
+ purple_debug_info("gg", "ggp_send_im: richtext msg = %s\n", string_buffer->str);
+ plain = purple_unescape_html(string_buffer->str);
+ g_string_free(string_buffer, TRUE);
+ } else {
+ purple_debug_info("gg", "ggp_send_im: msg = %s\n", msg);
+ plain = purple_unescape_html(msg);
+ }
+
tmp = charset_convert(plain, "UTF-8", "CP1250");
- if (NULL == tmp || strlen(tmp) == 0) {
+ if (tmp && (format_length - sizeof(struct gg_msg_richtext))) {
+ if(gg_send_message_richtext(info->session, GG_CLASS_CHAT, ggp_str_to_uin(who), (unsigned char *)tmp, format, format_length) < 0) {
+ ret = -1;
+ } else {
+ ret = 1;
+ }
+ } else if (NULL == tmp || *tmp == 0) {
ret = 0;
} else if (strlen(tmp) > GG_MSG_MAXSIZE) {
ret = -E2BIG;
@@ -1802,9 +1942,7 @@ static int ggp_send_im(PurpleConnection *gc, const char *who, const char *msg,
return ret;
}
-/* }}} */
-/* static void ggp_get_info(PurpleConnection *gc, const char *name) { {{{ */
static void ggp_get_info(PurpleConnection *gc, const char *name)
{
GGPInfo *info = gc->proto_data;
@@ -1822,9 +1960,7 @@ static void ggp_get_info(PurpleConnection *gc, const char *name)
ggp_search_add(info->searches, seq, form);
purple_debug_info("gg", "ggp_get_info(): Added seq %u", seq);
}
-/* }}} */
-/* static void ggp_set_status(PurpleAccount *account, PurpleStatus *status) {{{ */
static int ggp_to_gg_status(PurpleStatus *status, char **msg)
{
const char *status_id = purple_status_get_id(status);
@@ -1869,9 +2005,7 @@ static int ggp_to_gg_status(PurpleStatus *status, char **msg)
return new_status;
}
}
-/* }}} */
-/* static void ggp_set_status(PurpleAccount *account, PurpleStatus *status) {{{ */
static void ggp_set_status(PurpleAccount *account, PurpleStatus *status)
{
PurpleConnection *gc;
@@ -1897,9 +2031,7 @@ static void ggp_set_status(PurpleAccount *account, PurpleStatus *status)
ggp_status_fake_to_self(account);
}
-/* }}} */
-/* static void ggp_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) {{{ */
static void ggp_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
{
PurpleAccount *account;
@@ -1912,9 +2044,7 @@ static void ggp_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup
ggp_status_fake_to_self(account);
}
}
-/* }}} */
-/* static void ggp_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) {{{ */
static void ggp_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
PurpleGroup *group)
{
@@ -1922,9 +2052,7 @@ static void ggp_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
gg_remove_notify(info->session, ggp_str_to_uin(buddy->name));
}
-/* }}} */
-/* static void ggp_join_chat(PurpleConnection *gc, GHashTable *data) {{{ */
static void ggp_join_chat(PurpleConnection *gc, GHashTable *data)
{
GGPInfo *info = gc->proto_data;
@@ -1957,15 +2085,11 @@ static void ggp_join_chat(PurpleConnection *gc, GHashTable *data)
purple_account_get_username(account), NULL,
PURPLE_CBFLAGS_NONE, TRUE);
}
-/* }}} */
-/* static char *ggp_get_chat_name(GHashTable *data) { {{{ */
static char *ggp_get_chat_name(GHashTable *data) {
return g_strdup(g_hash_table_lookup(data, "name"));
}
-/* }}} */
-/* static int ggp_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags) {{{ */
static int ggp_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
{
PurpleConversation *conv;
@@ -2017,9 +2141,7 @@ static int ggp_chat_send(PurpleConnection *gc, int id, const char *message, Purp
return 0;
}
-/* }}} */
-/* static void ggp_keepalive(PurpleConnection *gc) {{{ */
static void ggp_keepalive(PurpleConnection *gc)
{
GGPInfo *info = gc->proto_data;
@@ -2034,9 +2156,7 @@ static void ggp_keepalive(PurpleConnection *gc)
_("Not connected to the server."));
}
}
-/* }}} */
-/* static void ggp_register_user(PurpleAccount *account) {{{ */
static void ggp_register_user(PurpleAccount *account)
{
PurpleConnection *gc = purple_account_get_connection(account);
@@ -2046,9 +2166,7 @@ static void ggp_register_user(PurpleAccount *account)
ggp_token_request(gc, ggp_register_user_dialog);
}
-/* }}} */
-/* static GList *ggp_actions(PurplePlugin *plugin, gpointer context) {{{ */
static GList *ggp_actions(PurplePlugin *plugin, gpointer context)
{
GList *m = NULL;
@@ -2088,19 +2206,15 @@ static GList *ggp_actions(PurplePlugin *plugin, gpointer context)
return m;
}
-/* }}} */
-/* static gboolean ggp_offline_message(const PurpleBuddy *buddy) {{{ */
static gboolean ggp_offline_message(const PurpleBuddy *buddy)
{
return TRUE;
}
-/* }}} */
-/* prpl_info setup {{{ */
static PurplePluginProtocolInfo prpl_info =
{
- OPT_PROTO_REGISTER_NOSCREENNAME,
+ OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_IM_IMAGE,
NULL, /* user_splits */
NULL, /* protocol_options */
{"png", 32, 32, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
@@ -2170,36 +2284,34 @@ static PurplePluginProtocolInfo prpl_info =
sizeof(PurplePluginProtocolInfo), /* struct_size */
NULL
};
-/* }}} */
-/* PurplePluginInfo setup {{{ */
static PurplePluginInfo info = {
- PURPLE_PLUGIN_MAGIC, /* magic */
- PURPLE_MAJOR_VERSION, /* major_version */
- PURPLE_MINOR_VERSION, /* minor_version */
- PURPLE_PLUGIN_PROTOCOL, /* plugin type */
- NULL, /* ui_requirement */
- 0, /* flags */
- NULL, /* dependencies */
+ PURPLE_PLUGIN_MAGIC, /* magic */
+ PURPLE_MAJOR_VERSION, /* major_version */
+ PURPLE_MINOR_VERSION, /* minor_version */
+ PURPLE_PLUGIN_PROTOCOL, /* plugin type */
+ NULL, /* ui_requirement */
+ 0, /* flags */
+ NULL, /* dependencies */
PURPLE_PRIORITY_DEFAULT, /* priority */
- "prpl-gg", /* id */
- "Gadu-Gadu", /* name */
- DISPLAY_VERSION, /* version */
+ "prpl-gg", /* id */
+ "Gadu-Gadu", /* name */
+ DISPLAY_VERSION, /* version */
N_("Gadu-Gadu Protocol Plugin"), /* summary */
N_("Polish popular IM"), /* description */
- "boler@sourceforge.net", /* author */
- PURPLE_WEBSITE, /* homepage */
+ "boler@sourceforge.net", /* author */
+ PURPLE_WEBSITE, /* homepage */
- NULL, /* load */
- NULL, /* unload */
- NULL, /* destroy */
+ NULL, /* load */
+ NULL, /* unload */
+ NULL, /* destroy */
- NULL, /* ui_info */
- &prpl_info, /* extra_info */
- NULL, /* prefs_info */
- ggp_actions, /* actions */
+ NULL, /* ui_info */
+ &prpl_info, /* extra_info */
+ NULL, /* prefs_info */
+ ggp_actions, /* actions */
/* padding */
NULL,
@@ -2207,9 +2319,7 @@ static PurplePluginInfo info = {
NULL,
NULL
};
-/* }}} */
-/* static void purple_gg_debug_handler(int level, const char * format, va_list args) {{{ */
static void purple_gg_debug_handler(int level, const char * format, va_list args) {
PurpleDebugLevel purple_level;
char *msg = g_strdup_vprintf(format, args);
@@ -2232,11 +2342,7 @@ static void purple_gg_debug_handler(int level, const char * format, va_list args
purple_debug(purple_level, "gg", "%s", msg);
g_free(msg);
}
-/* }}} */
-/*
- */
-/* static void init_plugin(PurplePlugin *plugin) {{{ */
static void init_plugin(PurplePlugin *plugin)
{
PurpleAccountOption *option;
@@ -2250,7 +2356,6 @@ static void init_plugin(PurplePlugin *plugin)
gg_debug_handler = purple_gg_debug_handler;
}
-/* }}} */
PURPLE_INIT_PLUGIN(gg, init_plugin, info);