Mercurial > pidgin
diff libpurple/protocols/qq/qq.c @ 25141:5ace6c024230
propagate from branch 'im.pidgin.pidgin' (head 7821a3549d7d99473e999dc067afc4218addcc1e)
to branch 'local.struct.hiding' (head 4235f268e41a5ad75efa1010b697599c0c0dd28a)
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Fri, 31 Oct 2008 07:59:46 +0000 |
parents | 16734635febf 7c0a56c5fea0 |
children | e35115192593 |
line wrap: on
line diff
--- a/libpurple/protocols/qq/qq.c Sat Oct 04 21:46:10 2008 +0000 +++ b/libpurple/protocols/qq/qq.c Fri Oct 31 07:59:46 2008 +0000 @@ -29,6 +29,7 @@ #include "notify.h" #include "prefs.h" #include "prpl.h" +#include "privacy.h" #include "request.h" #include "roomlist.h" #include "server.h" @@ -39,12 +40,12 @@ #include "buddy_list.h" #include "char_conv.h" #include "group.h" -#include "group_find.h" #include "group_im.h" #include "group_info.h" #include "group_join.h" #include "group_opt.h" -#include "header_info.h" +#include "group_internal.h" +#include "qq_define.h" #include "im.h" #include "qq_process.h" #include "qq_base.h" @@ -56,7 +57,11 @@ #include "version.h" #define OPENQ_AUTHOR "Puzzlebird" -#define OPENQ_WEBSITE "http://openq.sourceforge.net" +#define OPENQ_WEBSITE "http://openq.sourceforge.net" + +#ifndef OPENQ_VERSION +#define OPENQ_VERSION DISPLAY_VERSION +#endif static GList *server_list_build(gchar select) { @@ -128,6 +133,7 @@ PurpleConnection *gc; qq_data *qd; PurplePresence *presence; + const gchar *version_str; g_return_if_fail(account != NULL); @@ -154,6 +160,19 @@ server_list_create(account); purple_debug_info("QQ", "Server list has %d\n", g_list_length(qd->servers)); + version_str = purple_account_get_string(account, "client_version", NULL); + qd->client_tag = QQ_CLIENT_0D55; /* set default as QQ2005 */ + qd->client_version = 2005; + if (version_str != NULL && strlen(version_str) != 0) { + if (strcmp(version_str, "qq2007") == 0) { + qd->client_tag = QQ_CLIENT_111D; + qd->client_version = 2007; + } else if (strcmp(version_str, "qq2008") == 0) { + qd->client_tag = QQ_CLIENT_115B; + qd->client_version = 2008; + } + } + qd->is_show_notice = purple_account_get_bool(account, "show_notice", TRUE); qd->is_show_news = purple_account_get_bool(account, "show_news", TRUE); @@ -203,6 +222,13 @@ } qq_disconnect(gc); + + if (qd->redirect) g_free(qd->redirect); + if (qd->ld.token) g_free(qd->ld.token); + if (qd->ld.token_ex) g_free(qd->ld.token_ex); + if (qd->captcha.token) g_free(qd->captcha.token); + if (qd->captcha.data) g_free(qd->captcha.data); + server_list_remove_all(qd); g_free(qd); @@ -210,25 +236,25 @@ } /* returns the icon name for a buddy or protocol */ -static const gchar *_qq_list_icon(PurpleAccount *a, PurpleBuddy *b) +static const gchar *qq_list_icon(PurpleAccount *a, PurpleBuddy *b) { return "qq"; } /* a short status text beside buddy icon*/ -static gchar *_qq_status_text(PurpleBuddy *b) +static gchar *qq_status_text(PurpleBuddy *b) { - qq_buddy *q_bud; + qq_buddy_data *bd; GString *status; - q_bud = (qq_buddy *) b->proto_data; - if (q_bud == NULL) + bd = (qq_buddy_data *) b->proto_data; + if (bd == NULL) return NULL; status = g_string_new(""); - switch(q_bud->status) { + switch(bd->status) { case QQ_BUDDY_OFFLINE: g_string_append(status, _("Offline")); break; @@ -245,8 +271,11 @@ case QQ_BUDDY_ONLINE_INVISIBLE: g_string_append(status, _("Invisible")); break; + case QQ_BUDDY_ONLINE_BUSY: + g_string_append(status, _("Busy")); + break; default: - g_string_printf(status, _("Unknown-%d"), q_bud->status); + g_string_printf(status, _("Unknown-%d"), bd->status); } return g_string_free(status, FALSE); @@ -254,23 +283,23 @@ /* a floating text when mouse is on the icon, show connection status here */ -static void _qq_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) +static void qq_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) { - qq_buddy *q_bud; + qq_buddy_data *bd; gchar *tmp; GString *str; g_return_if_fail(b != NULL); - q_bud = (qq_buddy *) b->proto_data; - if (q_bud == NULL) + bd = (qq_buddy_data *) b->proto_data; + if (bd == NULL) return; - /* if (PURPLE_BUDDY_IS_ONLINE(b) && q_bud != NULL) */ - if (q_bud->ip.s_addr != 0) { + /* if (PURPLE_BUDDY_IS_ONLINE(b) && bd != NULL) */ + if (bd->ip.s_addr != 0) { str = g_string_new(NULL); - g_string_printf(str, "%s:%d", inet_ntoa(q_bud->ip), q_bud->port); - if (q_bud->comm_flag & QQ_COMM_FLAG_TCP_MODE) { + g_string_printf(str, "%s:%d", inet_ntoa(bd->ip), bd->port); + if (bd->comm_flag & QQ_COMM_FLAG_TCP_MODE) { g_string_append(str, " TCP"); } else { g_string_append(str, " UDP"); @@ -278,11 +307,11 @@ g_string_free(str, TRUE); } - tmp = g_strdup_printf("%d", q_bud->age); + tmp = g_strdup_printf("%d", bd->age); purple_notify_user_info_add_pair(user_info, _("Age"), tmp); g_free(tmp); - switch (q_bud->gender) { + switch (bd->gender) { case QQ_BUDDY_GENDER_GG: purple_notify_user_info_add_pair(user_info, _("Gender"), _("Male")); break; @@ -293,38 +322,38 @@ purple_notify_user_info_add_pair(user_info, _("Gender"), _("Unknown")); break; default: - tmp = g_strdup_printf("Error (%d)", q_bud->gender); + tmp = g_strdup_printf("Error (%d)", bd->gender); purple_notify_user_info_add_pair(user_info, _("Gender"), tmp); g_free(tmp); } - if (q_bud->level) { - tmp = g_strdup_printf("%d", q_bud->level); + if (bd->level) { + tmp = g_strdup_printf("%d", bd->level); purple_notify_user_info_add_pair(user_info, _("Level"), tmp); g_free(tmp); } str = g_string_new(NULL); - if (q_bud->comm_flag & QQ_COMM_FLAG_QQ_MEMBER) { + if (bd->comm_flag & QQ_COMM_FLAG_QQ_MEMBER) { g_string_append( str, _("Member") ); } - if (q_bud->comm_flag & QQ_COMM_FLAG_QQ_VIP) { + if (bd->comm_flag & QQ_COMM_FLAG_QQ_VIP) { g_string_append( str, _(" VIP") ); } - if (q_bud->comm_flag & QQ_COMM_FLAG_TCP_MODE) { + if (bd->comm_flag & QQ_COMM_FLAG_TCP_MODE) { g_string_append( str, _(" TCP") ); } - if (q_bud->comm_flag & QQ_COMM_FLAG_MOBILE) { + if (bd->comm_flag & QQ_COMM_FLAG_MOBILE) { g_string_append( str, _(" FromMobile") ); } - if (q_bud->comm_flag & QQ_COMM_FLAG_BIND_MOBILE) { + if (bd->comm_flag & QQ_COMM_FLAG_BIND_MOBILE) { g_string_append( str, _(" BindMobile") ); } - if (q_bud->comm_flag & QQ_COMM_FLAG_VIDEO) { + if (bd->comm_flag & QQ_COMM_FLAG_VIDEO) { g_string_append( str, _(" Video") ); } - if (q_bud->ext_flag & QQ_EXT_FLAG_ZONE) { + if (bd->ext_flag & QQ_EXT_FLAG_ZONE) { g_string_append( str, _(" Zone") ); } purple_notify_user_info_add_pair(user_info, _("Flag"), str->str); @@ -333,40 +362,47 @@ #ifdef DEBUG tmp = g_strdup_printf( "%s (%04X)", - qq_get_ver_desc(q_bud->client_version), - q_bud->client_version ); + qq_get_ver_desc(bd->client_tag), + bd->client_tag ); purple_notify_user_info_add_pair(user_info, _("Ver"), tmp); g_free(tmp); tmp = g_strdup_printf( "Ext 0x%X, Comm 0x%X", - q_bud->ext_flag, q_bud->comm_flag ); + bd->ext_flag, bd->comm_flag ); purple_notify_user_info_add_pair(user_info, _("Flag"), tmp); g_free(tmp); #endif } /* we can show tiny icons on the four corners of buddy icon, */ -static const char *_qq_list_emblem(PurpleBuddy *b) +static const char *qq_list_emblem(PurpleBuddy *b) { - /* each char** are refering to a filename in pixmaps/purple/status/default/ */ - qq_buddy *q_bud; + PurpleAccount *account; + PurpleConnection *gc; + qq_data *qd; + qq_buddy_data *buddy; - if (!b || !(q_bud = b->proto_data)) { + if (!b || !(account = b->account) || + !(gc = purple_account_get_connection(account)) || !(qd = gc->proto_data)) return NULL; + + buddy = (qq_buddy_data *)b->proto_data; + if (!buddy) { + return "not-authorized"; } - if (q_bud->comm_flag & QQ_COMM_FLAG_MOBILE) + if (buddy->comm_flag & QQ_COMM_FLAG_MOBILE) return "mobile"; - if (q_bud->comm_flag & QQ_COMM_FLAG_VIDEO) + if (buddy->comm_flag & QQ_COMM_FLAG_VIDEO) return "video"; - if (q_bud->comm_flag & QQ_COMM_FLAG_QQ_MEMBER) + if (buddy->comm_flag & QQ_COMM_FLAG_QQ_MEMBER) return "qq_member"; return NULL; } /* QQ away status (used to initiate QQ away packet) */ -static GList *_qq_away_states(PurpleAccount *ga) +static GList *qq_status_types(PurpleAccount *ga) { PurpleStatusType *status; GList *types = NULL; @@ -383,6 +419,10 @@ "invisible", _("Invisible"), FALSE, TRUE, FALSE); types = g_list_append(types, status); + status = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, + "busy", _("Busy"), TRUE, TRUE, FALSE); + types = g_list_append(types, status); + status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, "offline", _("Offline"), FALSE, TRUE, FALSE); types = g_list_append(types, status); @@ -395,18 +435,72 @@ } /* initiate QQ away with proper change_status packet */ -static void _qq_change_status(PurpleAccount *account, PurpleStatus *status) +static void qq_change_status(PurpleAccount *account, PurpleStatus *status) { PurpleConnection *gc = purple_account_get_connection(account); qq_request_change_status(gc, 0); } +static void qq_add_deny(PurpleConnection *gc, const char *who) +{ + qq_data *qd; + g_return_if_fail(NULL != gc && NULL != gc->proto_data); + + qd = (qq_data *) gc->proto_data; + if (!qd->is_login) + return; + + if (!who || who[0] == '\0') + return; + + purple_debug_info("QQ", "Add deny for %s\n", who); +} + +static void qq_rem_deny(PurpleConnection *gc, const char *who) +{ + qq_data *qd; + g_return_if_fail(NULL != gc && NULL != gc->proto_data); + + qd = (qq_data *) gc->proto_data; + if (!qd->is_login) + return; + + if (!who || who[0] == '\0') + return; + + purple_debug_info("QQ", "Rem deny for %s\n", who); +} + +static void qq_set_permit_deny(PurpleConnection *gc) +{ + PurpleAccount *account; + GSList *deny; + + purple_debug_info("QQ", "Set permit deny\n"); + account = purple_connection_get_account(gc); + switch (account->perm_deny) + { + case PURPLE_PRIVACY_ALLOW_ALL: + for (deny = account->deny; deny; deny = deny->next) + qq_rem_deny(gc, deny->data); + break; + + case PURPLE_PRIVACY_ALLOW_BUDDYLIST: + case PURPLE_PRIVACY_ALLOW_USERS: + case PURPLE_PRIVACY_DENY_USERS: + case PURPLE_PRIVACY_DENY_ALL: + for (deny = account->deny; deny; deny = deny->next) + qq_add_deny(gc, deny->data); + break; + } +} + /* IMPORTANT: PurpleConvImFlags -> PurpleMessageFlags */ /* send an instant msg to a buddy */ -static gint _qq_send_im(PurpleConnection *gc, const gchar *who, const gchar *message, PurpleMessageFlags flags) +static gint qq_send_im(PurpleConnection *gc, const gchar *who, const gchar *message, PurpleMessageFlags flags) { - gint type, to_uid; + gint type, uid_to; gchar *msg, *msg_with_qq_smiley; qq_data *qd; @@ -417,15 +511,15 @@ g_return_val_if_fail(strlen(message) <= QQ_MSG_IM_MAX, -E2BIG); type = (flags == PURPLE_MESSAGE_AUTO_RESP ? QQ_IM_AUTO_REPLY : QQ_IM_TEXT); - to_uid = purple_name_to_uid(who); + uid_to = purple_name_to_uid(who); /* if msg is to myself, bypass the network */ - if (to_uid == qd->uid) { + if (uid_to == qd->uid) { serv_got_im(gc, who, message, flags, time(NULL)); } else { msg = utf8_to_qq(message, QQ_CHARSET_DEFAULT); msg_with_qq_smiley = purple_smiley_to_qq(msg); - qq_send_packet_im(gc, to_uid, msg_with_qq_smiley, type); + qq_request_send_im(gc, uid_to, msg_with_qq_smiley, type); g_free(msg); g_free(msg_with_qq_smiley); } @@ -434,21 +528,18 @@ } /* send a chat msg to a QQ Qun */ -static int _qq_chat_send(PurpleConnection *gc, int channel, const char *message, PurpleMessageFlags flags) +static int qq_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags) { gchar *msg, *msg_with_qq_smiley; - qq_group *group; + guint32 room_id = id; g_return_val_if_fail(message != NULL, -1); g_return_val_if_fail(strlen(message) <= QQ_MSG_IM_MAX, -E2BIG); - group = qq_group_find_by_channel(gc, channel); - g_return_val_if_fail(group != NULL, -1); - purple_debug_info("QQ_MESG", "Send qun mesg in utf8: %s\n", message); msg = utf8_to_qq(message, QQ_CHARSET_DEFAULT); msg_with_qq_smiley = purple_smiley_to_qq(msg); - qq_send_packet_group_im(gc, group, msg_with_qq_smiley); + qq_request_room_send_im(gc, room_id, msg_with_qq_smiley); g_free(msg); g_free(msg_with_qq_smiley); @@ -456,7 +547,7 @@ } /* send packet to get who's detailed information */ -static void _qq_get_info(PurpleConnection *gc, const gchar *who) +static void qq_show_buddy_info(PurpleConnection *gc, const gchar *who) { guint32 uid; qq_data *qd; @@ -470,78 +561,135 @@ return; } - qq_request_get_level(gc, uid); - qq_send_packet_get_info(gc, uid, TRUE); + if (qd->client_version >= 2007) { + qq_request_get_level_2007(gc, uid); + } else { + qq_request_get_level(gc, uid); + } + qq_request_buddy_info(gc, uid, 0, QQ_BUDDY_INFO_DISPLAY); +} + +static void action_update_all_rooms(PurplePluginAction *action) +{ + PurpleConnection *gc = (PurpleConnection *) action->context; + qq_data *qd; + + g_return_if_fail(NULL != gc && NULL != gc->proto_data); + qd = (qq_data *) gc->proto_data; + + if ( !qd->is_login ) { + return; + } + + qq_update_all_rooms(gc, 0, 0); } -/* get my own information */ -static void _qq_menu_modify_my_info(PurplePluginAction *action) +static void action_change_icon(PurplePluginAction *action) +{ + PurpleConnection *gc = (PurpleConnection *) action->context; + qq_data *qd; + gchar *icon_name; + gchar *icon_path; + + g_return_if_fail(NULL != gc && NULL != gc->proto_data); + qd = (qq_data *) gc->proto_data; + + if ( !qd->is_login ) { + return; + } + + icon_name = qq_get_icon_name(qd->my_icon); + icon_path = qq_get_icon_path(icon_name); + g_free(icon_name); + + purple_debug_info("QQ", "Change prev icon %s to ...\n", icon_path); + purple_request_file(action, _("Select icon..."), icon_path, + FALSE, + G_CALLBACK(qq_change_icon_cb), NULL, + purple_connection_get_account(gc), NULL, NULL, + gc); + g_free(icon_path); +} + +static void action_modify_info_base(PurplePluginAction *action) +{ + PurpleConnection *gc = (PurpleConnection *) action->context; + qq_data *qd; + + g_return_if_fail(NULL != gc && NULL != gc->proto_data); + qd = (qq_data *) gc->proto_data; + qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_BASE); +} + +static void action_modify_info_ext(PurplePluginAction *action) { PurpleConnection *gc = (PurpleConnection *) action->context; qq_data *qd; + g_return_if_fail(NULL != gc && NULL != gc->proto_data); qd = (qq_data *) gc->proto_data; - qq_prepare_modify_info(gc); + qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_EXT); +} + +static void action_modify_info_addr(PurplePluginAction *action) +{ + PurpleConnection *gc = (PurpleConnection *) action->context; + qq_data *qd; + + g_return_if_fail(NULL != gc && NULL != gc->proto_data); + qd = (qq_data *) gc->proto_data; + qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_ADDR); } -static void _qq_menu_change_password(PurplePluginAction *action) +static void action_modify_info_contact(PurplePluginAction *action) { + PurpleConnection *gc = (PurpleConnection *) action->context; + qq_data *qd; + + g_return_if_fail(NULL != gc && NULL != gc->proto_data); + qd = (qq_data *) gc->proto_data; + qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_CONTACT); +} + +static void action_change_password(PurplePluginAction *action) +{ + PurpleConnection *gc = (PurpleConnection *) action->context; + + g_return_if_fail(NULL != gc && NULL != gc->proto_data); purple_notify_uri(NULL, "https://password.qq.com"); } -/* remove a buddy from my list and remove myself from his list */ -/* TODO: re-enable this -static void _qq_menu_block_buddy(PurpleBlistNode * node) -{ - guint32 uid; - gc_and_uid *g; - PurpleBuddy *buddy; - PurpleConnection *gc; - const gchar *who; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - buddy = (PurpleBuddy *) node; - gc = purple_account_get_connection(buddy->account); - who = buddy->name; - g_return_if_fail(who != NULL); - - uid = purple_name_to_uid(who); - g_return_if_fail(uid > 0); - - g = g_new0(gc_and_uid, 1); - g->gc = gc; - g->uid = uid; - - purple_request_action(gc, _("Block Buddy"), - _("Are you sure you want to block this buddy?"), NULL, - 1, g, 2, - _("Cancel"), - G_CALLBACK(qq_do_nothing_with_gc_and_uid), - _("Block"), G_CALLBACK(qq_block_buddy_with_gc_and_uid)); -} -*/ - /* show a brief summary of what we get from login packet */ -static void _qq_menu_account_info(PurplePluginAction *action) +static void action_show_account_info(PurplePluginAction *action) { PurpleConnection *gc = (PurpleConnection *) action->context; qq_data *qd; GString *info; + struct tm *tm_local; + int index; + g_return_if_fail(NULL != gc && NULL != gc->proto_data); qd = (qq_data *) gc->proto_data; - info = g_string_new("<html><body>\n"); + info = g_string_new("<html><body>"); - g_string_append_printf(info, _("<b>Current Online</b>: %d<br>\n"), qd->total_online); - g_string_append_printf(info, _("<b>Last Refresh</b>: %s<br>\n"), ctime(&qd->last_get_online)); + tm_local = localtime(&qd->login_time); + g_string_append_printf(info, _("<b>Login time</b>: %d-%d-%d, %d:%d:%d<br>\n"), + (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, + tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); + g_string_append_printf(info, _("<b>Total Online Buddies</b>: %d<br>\n"), qd->online_total); + tm_local = localtime(&qd->online_last_update); + g_string_append_printf(info, _("<b>Last Refresh</b>: %d-%d-%d, %d:%d:%d<br>\n"), + (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, + tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); - g_string_append(info, "<hr>\n"); + g_string_append(info, "<hr>"); g_string_append_printf(info, _("<b>Server</b>: %s<br>\n"), qd->curr_server); + g_string_append_printf(info, _("<b>Client Tag</b>: %s<br>\n"), qq_get_ver_desc(qd->client_tag)); g_string_append_printf(info, _("<b>Connection Mode</b>: %s<br>\n"), qd->use_tcp ? "TCP" : "UDP"); - g_string_append_printf(info, _("<b>My Internet Address</b>: %s<br>\n"), inet_ntoa(qd->my_ip)); + g_string_append_printf(info, _("<b>My Internet IP</b>: %s:%d<br>\n"), inet_ntoa(qd->my_ip), qd->my_port); - g_string_append(info, "<hr>\n"); + g_string_append(info, "<hr>"); g_string_append(info, "<i>Network Status</i><br>\n"); g_string_append_printf(info, _("<b>Sent</b>: %lu<br>\n"), qd->net_stat.sent); g_string_append_printf(info, _("<b>Resend</b>: %lu<br>\n"), qd->net_stat.resend); @@ -549,12 +697,18 @@ g_string_append_printf(info, _("<b>Received</b>: %lu<br>\n"), qd->net_stat.rcved); g_string_append_printf(info, _("<b>Received Duplicate</b>: %lu<br>\n"), qd->net_stat.rcved_dup); - g_string_append(info, "<hr>\n"); - g_string_append(info, "<i>Information below may not be accurate</i><br>\n"); + g_string_append(info, "<hr>"); + g_string_append(info, "<i>Last Login Information</i><br>\n"); - g_string_append_printf(info, _("<b>Login Time</b>: %s<br>\n"), ctime(&qd->login_time)); - g_string_append_printf(info, _("<b>Last Login IP</b>: %s<br>\n"), qd->last_login_ip); - g_string_append_printf(info, _("<b>Last Login Time</b>: %s\n"), ctime(&qd->last_login_time)); + for (index = 0; index < sizeof(qd->last_login_time) / sizeof(time_t); index++) { + tm_local = localtime(&qd->last_login_time[index]); + g_string_append_printf(info, _("<b>Time</b>: %d-%d-%d, %d:%d:%d<br>\n"), + (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, + tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); + } + if (qd->last_login_ip.s_addr != 0) { + g_string_append_printf(info, _("<b>IP</b>: %s<br>\n"), inet_ntoa(qd->last_login_ip)); + } g_string_append(info, "</body></html>"); @@ -563,6 +717,65 @@ g_string_free(info, TRUE); } +static void action_about_openq(PurplePluginAction *action) +{ + PurpleConnection *gc = (PurpleConnection *) action->context; + qq_data *qd; + GString *info; + gchar *title; + + g_return_if_fail(NULL != gc && NULL != gc->proto_data); + qd = (qq_data *) gc->proto_data; + + info = g_string_new("<html><body>"); + g_string_append(info, _("<p><b>Original Author</b>:<br>\n")); + g_string_append(info, "puzzlebird<br>\n"); + g_string_append(info, "<br>\n"); + g_string_append(info, _("<p><b>Code Contributors</b>:<br>\n")); + g_string_append(info, "gfhuang : patches for libpurple 2.0.0beta2, maintainer<br>\n"); + g_string_append(info, "Yuan Qingyun : patches for libpurple 1.5.0, maintainer<br>\n"); + g_string_append(info, "henryouly : file transfer, udp sock5 proxy and qq_show, maintainer<br>\n"); + g_string_append(info, "hzhr : maintainer<br>\n"); + g_string_append(info, "joymarquis : maintainer<br>\n"); + g_string_append(info, "arfankai : fixed bugs in char_conv.c<br>\n"); + g_string_append(info, "rakescar : provided filter for HTML tag<br>\n"); + g_string_append(info, "yyw : improved performance on PPC linux<br>\n"); + g_string_append(info, "lvxiang : provided ip to location original code<br>\n"); + g_string_append(info, "markhuetsch : OpenQ merge into libpurple, maintainer 2006-2007<br>\n"); + g_string_append(info, "ccpaging : maintainer since 2007<br>\n"); + g_string_append(info, "icesky : maintainer since 2007<br>\n"); + g_string_append(info, "csyfek : faces, maintainer since 2007<br>\n"); + g_string_append(info, "<br>\n"); + g_string_append(info, _("<p><b>Lovely Patch Writers</b>:<br>\n")); + g_string_append(info, "gnap : message displaying, documentation<br>\n"); + g_string_append(info, "manphiz : qun processing<br>\n"); + g_string_append(info, "moo : qun processing<br>\n"); + g_string_append(info, "Coly Li : qun processing<br>\n"); + g_string_append(info, "Emil Alexiev : captcha verification on login based on LumaQQ for MAC (2007), login, add buddy, remove buddy, message exchange and logout<br>\n"); + g_string_append(info, "<br>\n"); + g_string_append(info, _("<p><b>Acknowledgement</b>:<br>\n")); + g_string_append(info, "Shufeng Tan : http://sf.net/projects/perl-oicq<br>\n"); + g_string_append(info, "Jeff Ye : http://www.sinomac.com<br>\n"); + g_string_append(info, "Hu Zheng : http://forlinux.yeah.net<br>\n"); + g_string_append(info, "yunfan : http://www.myswear.net<br>\n"); + g_string_append(info, "OpenQ Team : http://openq.linuxsir.org<br>\n"); + g_string_append(info, "LumaQQ Team : http://lumaqq.linuxsir.org<br>\n"); + g_string_append(info, "khc(at)pidgin.im<br>\n"); + g_string_append(info, "qulogic(at)pidgin.im<br>\n"); + g_string_append(info, "rlaager(at)pidgin.im<br>\n"); + g_string_append(info, "OpenQ Google Group : http://groups.google.com/group/openq<br>\n"); + g_string_append(info, "<br>\n"); + g_string_append(info, _("<p><i>And, all the boys in the backroom...</i><br>\n")); + g_string_append(info, _("<i>Feel free to join us!</i> :)")); + g_string_append(info, "</body></html>"); + + title = g_strdup_printf(_("About OpenQ r%s"), OPENQ_VERSION); + purple_notify_formatted(gc, NULL, title, NULL, info->str, NULL, NULL); + + g_free(title); + g_string_free(info, TRUE); +} + /* static void _qq_menu_search_or_add_permanent_group(PurplePluginAction *action) { @@ -578,38 +791,48 @@ _("Input Qun name here"), _("Only QQ members can create permanent Qun"), "OpenQ", FALSE, FALSE, NULL, - _("Create"), G_CALLBACK(qq_room_create_new), _("Cancel"), NULL, gc); + _("Create"), G_CALLBACK(qq_create_room), _("Cancel"), NULL, gc); } */ -static void _qq_menu_unsubscribe_group(PurpleBlistNode * node) -{ - PurpleChat *chat = (PurpleChat *)node; - PurpleConnection *gc; - GHashTable *components; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - gc = purple_account_get_connection(purple_chat_get_account(chat)); - components = purple_chat_get_components(chat); - - g_return_if_fail(components != NULL); - qq_group_exit(gc, components); -} - -/* -static void _qq_menu_manage_group(PurpleBlistNode * node) +static void action_chat_quit(PurpleBlistNode * node) { PurpleChat *chat = (PurpleChat *)node; PurpleConnection *gc = purple_account_get_connection(chat->account); GHashTable *components = chat -> components; + gchar *num_str; + guint32 room_id; g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); g_return_if_fail(components != NULL); - qq_group_manage_group(gc, components); + + num_str = g_hash_table_lookup(components, QQ_ROOM_KEY_INTERNAL_ID); + room_id = strtol(num_str, NULL, 10); + g_return_if_fail(room_id != 0); + + qq_room_quit(gc, room_id); } -*/ + +static void action_chat_get_info(PurpleBlistNode * node) +{ + PurpleChat *chat = (PurpleChat *)node; + PurpleConnection *gc = purple_account_get_connection(chat->account); + GHashTable *components = chat -> components; + gchar *num_str; + guint32 room_id; + + g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); + + g_return_if_fail(components != NULL); + + num_str = g_hash_table_lookup(components, QQ_ROOM_KEY_INTERNAL_ID); + room_id = strtol(num_str, NULL, 10); + g_return_if_fail(room_id != 0); + + qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_INFO, room_id, NULL, 0, + 0, QQ_ROOM_INFO_DISPLAY); +} #if 0 /* TODO: re-enable this */ @@ -617,12 +840,12 @@ { PurpleBuddy *buddy; PurpleConnection *gc; - qq_buddy *q_bud; + qq_buddy_data *bd; g_return_if_fail (PURPLE_BLIST_NODE_IS_BUDDY (node)); buddy = (PurpleBuddy *) node; - q_bud = (qq_buddy *) buddy->proto_data; -/* if (is_online (q_bud->status)) { */ + bd = (qq_buddy_data *) buddy->proto_data; +/* if (is_online (bd->status)) { */ gc = purple_account_get_connection (buddy->account); g_return_if_fail (gc != NULL && gc->proto_data != NULL); qq_send_file(gc, buddy->name, NULL); @@ -631,21 +854,38 @@ #endif /* protocol related menus */ -static GList *_qq_actions(PurplePlugin *plugin, gpointer context) +static GList *qq_actions(PurplePlugin *plugin, gpointer context) { GList *m; PurplePluginAction *act; m = NULL; - act = purple_plugin_action_new(_("Set My Information"), _qq_menu_modify_my_info); + act = purple_plugin_action_new(_("Change Icon"), action_change_icon); + m = g_list_append(m, act); + + act = purple_plugin_action_new(_("Modify Information"), action_modify_info_base); + m = g_list_append(m, act); + + act = purple_plugin_action_new(_("Modify Extend Information"), action_modify_info_ext); + m = g_list_append(m, act); + + act = purple_plugin_action_new(_("Modify Address"), action_modify_info_addr); m = g_list_append(m, act); - act = purple_plugin_action_new(_("Change Password"), _qq_menu_change_password); + act = purple_plugin_action_new(_("Modify Contact"), action_modify_info_contact); + m = g_list_append(m, act); + + act = purple_plugin_action_new(_("Change Password"), action_change_password); m = g_list_append(m, act); - act = purple_plugin_action_new(_("Account Information"), _qq_menu_account_info); + act = purple_plugin_action_new(_("Account Information"), action_show_account_info); m = g_list_append(m, act); + act = purple_plugin_action_new(_("Update all QQ Quns"), action_update_all_rooms); + m = g_list_append(m, act); + + act = purple_plugin_action_new(_("About OpenQ"), action_about_openq); + m = g_list_append(m, act); /* act = purple_plugin_action_new(_("Qun: Search a permanent Qun"), _qq_menu_search_or_add_permanent_group); m = g_list_append(m, act); @@ -657,63 +897,131 @@ return m; } +static void qq_add_buddy_from_menu_cb(PurpleBlistNode *node, gpointer data) +{ + PurpleBuddy *buddy; + PurpleConnection *gc; + + g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + + buddy = (PurpleBuddy *) node; + gc = purple_account_get_connection(buddy->account); + + qq_add_buddy(gc, buddy, NULL); +} + +static GList *qq_buddy_menu(PurpleBuddy *buddy) +{ + GList *m = NULL; + PurpleMenuAction *act; + /* + PurpleConnection *gc = purple_account_get_connection(buddy->account); + qq_data *qd = gc->proto_data; + */ + qq_buddy_data *bd = (qq_buddy_data *)buddy->proto_data; + + if (bd == NULL) { + act = purple_menu_action_new(_("Add Buddy"), + PURPLE_CALLBACK(qq_add_buddy_from_menu_cb), + NULL, NULL); + m = g_list_append(m, act); + + return m; + + } + +/* TODO : not working, temp commented out by gfhuang */ +#if 0 + if (bd && is_online(bd->status)) { + act = purple_menu_action_new(_("Send File"), PURPLE_CALLBACK(_qq_menu_send_file), NULL, NULL); /* add NULL by gfhuang */ + m = g_list_append(m, act); + } +#endif + return m; +} + /* chat-related (QQ Qun) menu shown up with right-click */ -static GList *_qq_chat_menu(PurpleBlistNode *node) +static GList *qq_chat_menu(PurpleBlistNode *node) { GList *m; PurpleMenuAction *act; m = NULL; - act = purple_menu_action_new(_("Leave the QQ Qun"), PURPLE_CALLBACK(_qq_menu_unsubscribe_group), NULL, NULL); + act = purple_menu_action_new(_("Get Info"), PURPLE_CALLBACK(action_chat_get_info), NULL, NULL); m = g_list_append(m, act); - /* TODO: enable this - act = purple_menu_action_new(_("Show Details"), PURPLE_CALLBACK(_qq_menu_manage_group), NULL, NULL); + act = purple_menu_action_new(_("Quit Qun"), PURPLE_CALLBACK(action_chat_quit), NULL, NULL); m = g_list_append(m, act); - */ - return m; } /* buddy-related menu shown up with right-click */ -static GList *_qq_buddy_menu(PurpleBlistNode * node) +static GList *qq_blist_node_menu(PurpleBlistNode * node) { - GList *m; + if(PURPLE_BLIST_NODE_IS_CHAT(node)) + return qq_chat_menu(node); - if(PURPLE_BLIST_NODE_IS_CHAT(node)) - return _qq_chat_menu(node); + if(PURPLE_BLIST_NODE_IS_BUDDY(node)) + return qq_buddy_menu((PurpleBuddy *) node); - m = NULL; + return NULL; +} -/* TODO : not working, temp commented out by gfhuang */ -#if 0 +/* convert name displayed in a chat channel to original QQ UID */ +static gchar *chat_name_to_purple_name(const gchar *const name) +{ + const char *start; + const char *end; + gchar *ret; + + g_return_val_if_fail(name != NULL, NULL); - act = purple_menu_action_new(_("Block this buddy"), PURPLE_CALLBACK(_qq_menu_block_buddy), NULL, NULL); /* add NULL by gfhuang */ - m = g_list_append(m, act); -/* if (q_bud && is_online(q_bud->status)) { */ - act = purple_menu_action_new(_("Send File"), PURPLE_CALLBACK(_qq_menu_send_file), NULL, NULL); /* add NULL by gfhuang */ - m = g_list_append(m, act); -/* } */ -#endif + /* Sample: (1234567)*/ + start = strchr(name, '('); + g_return_val_if_fail(start != NULL, NULL); + end = strchr(start, ')'); + g_return_val_if_fail(end != NULL && (end - start) > 1, NULL); - return m; + ret = g_strndup(start + 1, end - start - 1); + + return ret; } -/* convert chat nickname to qq-uid to get this buddy info */ +/* convert chat nickname to uid to get this buddy info */ /* who is the nickname of buddy in QQ chat-room (Qun) */ -static void _qq_get_chat_buddy_info(PurpleConnection *gc, gint channel, const gchar *who) +static void qq_get_chat_buddy_info(PurpleConnection *gc, gint channel, const gchar *who) { - gchar *purple_name; + qq_data *qd; + gchar *uid_str; + guint32 uid; + + purple_debug_info("QQ", "Get chat buddy info of %s\n", who); g_return_if_fail(who != NULL); - purple_name = chat_name_to_purple_name(who); - if (purple_name != NULL) - _qq_get_info(gc, purple_name); + uid_str = chat_name_to_purple_name(who); + if (uid_str == NULL) { + return; + } + + qd = gc->proto_data; + uid = purple_name_to_uid(uid_str); + g_free(uid_str); + + if (uid <= 0) { + purple_debug_error("QQ", "Not valid chat name: %s\n", who); + purple_notify_error(gc, NULL, _("Invalid name"), NULL); + return; + } + + if (qd->client_version < 2007) { + qq_request_get_level(gc, uid); + } + qq_request_buddy_info(gc, uid, 0, QQ_BUDDY_INFO_DISPLAY); } -/* convert chat nickname to qq-uid to invite individual IM to buddy */ +/* convert chat nickname to uid to invite individual IM to buddy */ /* who is the nickname of buddy in QQ chat-room (Qun) */ -static gchar *_qq_get_chat_buddy_real_name(PurpleConnection *gc, gint channel, const gchar *who) +static gchar *qq_get_chat_buddy_real_name(PurpleConnection *gc, gint channel, const gchar *who) { g_return_val_if_fail(who != NULL, NULL); return chat_name_to_purple_name(who); @@ -725,21 +1033,21 @@ NULL, /* user_splits */ NULL, /* protocol_options */ {"png", 96, 96, 96, 96, 0, PURPLE_ICON_SCALE_SEND}, /* icon_spec */ - _qq_list_icon, /* list_icon */ - _qq_list_emblem, /* list_emblems */ - _qq_status_text, /* status_text */ - _qq_tooltip_text, /* tooltip_text */ - _qq_away_states, /* away_states */ - _qq_buddy_menu, /* blist_node_menu */ + qq_list_icon, /* list_icon */ + qq_list_emblem, /* list_emblems */ + qq_status_text, /* status_text */ + qq_tooltip_text, /* tooltip_text */ + qq_status_types, /* away_states */ + qq_blist_node_menu, /* blist_node_menu */ qq_chat_info, /* chat_info */ qq_chat_info_defaults, /* chat_info_defaults */ qq_login, /* open */ qq_close, /* close */ - _qq_send_im, /* send_im */ + qq_send_im, /* send_im */ NULL, /* set_info */ NULL, /* send_typing */ - _qq_get_info, /* get_info */ - _qq_change_status, /* change status */ + qq_show_buddy_info, /* get_info */ + qq_change_status, /* change status */ NULL, /* set_idle */ NULL, /* change_passwd */ qq_add_buddy, /* add_buddy */ @@ -747,30 +1055,30 @@ qq_remove_buddy, /* remove_buddy */ NULL, /* remove_buddies */ NULL, /* add_permit */ - NULL, /* add_deny */ + qq_add_deny, /* add_deny */ NULL, /* rem_permit */ NULL, /* rem_deny */ - NULL, /* set_permit_deny */ + qq_set_permit_deny, /* set_permit_deny */ qq_group_join, /* join_chat */ NULL, /* reject chat invite */ NULL, /* get_chat_name */ NULL, /* chat_invite */ NULL, /* chat_leave */ NULL, /* chat_whisper */ - _qq_chat_send, /* chat_send */ + qq_chat_send, /* chat_send */ NULL, /* keepalive */ NULL, /* register_user */ - _qq_get_chat_buddy_info, /* get_cb_info */ + qq_get_chat_buddy_info, /* get_cb_info */ NULL, /* get_cb_away */ NULL, /* alias_buddy */ - NULL, /* group_buddy */ + NULL, /* change buddy's group */ NULL, /* rename_group */ NULL, /* buddy_free */ NULL, /* convo_closed */ NULL, /* normalize */ - qq_set_my_buddy_icon, /* set_buddy_icon */ + qq_set_custom_icon, NULL, /* remove_group */ - _qq_get_chat_buddy_real_name, /* get_cb_real_name */ + qq_get_chat_buddy_real_name, /* get_cb_real_name */ NULL, /* set_chat_topic */ NULL, /* find_blist_chat */ qq_roomlist_get_list, /* roomlist_get_list */ @@ -818,7 +1126,7 @@ NULL, /**< ui_info */ &prpl_info, /**< extra_info */ NULL, /**< prefs_info */ - _qq_actions, + qq_actions, /* padding */ NULL, @@ -832,35 +1140,60 @@ { PurpleAccountOption *option; PurpleKeyValuePair *kvp; - GList *list = NULL; - GList *kvlist = NULL; - GList *entry; + GList *server_list = NULL; + GList *server_kv_list = NULL; + GList *it; +//#ifdef DEBUG + GList *version_kv_list = NULL; +//#endif - list = server_list_build('A'); + server_list = server_list_build('A'); - purple_prefs_add_string_list("/plugins/prpl/qq/serverlist", list); - list = purple_prefs_get_string_list("/plugins/prpl/qq/serverlist"); + purple_prefs_add_string_list("/plugins/prpl/qq/serverlist", server_list); + server_list = purple_prefs_get_string_list("/plugins/prpl/qq/serverlist"); - kvlist = NULL; + server_kv_list = NULL; kvp = g_new0(PurpleKeyValuePair, 1); kvp->key = g_strdup(_("Auto")); kvp->value = g_strdup("auto"); - kvlist = g_list_append(kvlist, kvp); + server_kv_list = g_list_append(server_kv_list, kvp); - entry = list; - while(entry) { - if (entry->data != NULL && strlen(entry->data) > 0) { + it = server_list; + while(it) { + if (it->data != NULL && strlen(it->data) > 0) { kvp = g_new0(PurpleKeyValuePair, 1); - kvp->key = g_strdup(entry->data); - kvp->value = g_strdup(entry->data); - kvlist = g_list_append(kvlist, kvp); + kvp->key = g_strdup(it->data); + kvp->value = g_strdup(it->data); + server_kv_list = g_list_append(server_kv_list, kvp); } - entry = entry->next; + it = it->next; } - option = purple_account_option_list_new(_("Server"), "server", kvlist); + g_list_free(server_list); + + option = purple_account_option_list_new(_("Select Server"), "server", server_kv_list); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); +//#ifdef DEBUG + kvp = g_new0(PurpleKeyValuePair, 1); + kvp->key = g_strdup(_("QQ2005")); + kvp->value = g_strdup("qq2005"); + version_kv_list = g_list_append(version_kv_list, kvp); + + kvp = g_new0(PurpleKeyValuePair, 1); + kvp->key = g_strdup(_("QQ2007")); + kvp->value = g_strdup("qq2007"); + version_kv_list = g_list_append(version_kv_list, kvp); + + kvp = g_new0(PurpleKeyValuePair, 1); + kvp->key = g_strdup(_("QQ2008")); + kvp->value = g_strdup("qq2008"); + version_kv_list = g_list_append(version_kv_list, kvp); + + option = purple_account_option_list_new(_("Client Version"), "client_version", version_kv_list); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); +//#endif + option = purple_account_option_bool_new(_("Connect by TCP"), "use_tcp", TRUE); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); @@ -879,9 +1212,10 @@ purple_prefs_add_none("/plugins/prpl/qq"); purple_prefs_add_bool("/plugins/prpl/qq/show_status_by_icon", TRUE); purple_prefs_add_bool("/plugins/prpl/qq/show_fake_video", FALSE); - purple_prefs_add_bool("/plugins/prpl/qq/show_room_when_newin", TRUE); + purple_prefs_add_bool("/plugins/prpl/qq/auto_popup_conversation", FALSE); + purple_prefs_add_bool("/plugins/prpl/qq/auto_get_authorize_info", TRUE); purple_prefs_add_int("/plugins/prpl/qq/resend_interval", 3); - purple_prefs_add_int("/plugins/prpl/qq/resend_times", 4); + purple_prefs_add_int("/plugins/prpl/qq/resend_times", 10); } PURPLE_INIT_PLUGIN(qq, init_plugin, info);