00001
00023 #include "internal.h"
00024
00025 #ifdef _WIN32
00026 #define random rand
00027 #endif
00028
00029 #include "debug.h"
00030 #include "notify.h"
00031 #include "prefs.h"
00032 #include "request.h"
00033 #include "accountopt.h"
00034 #include "prpl.h"
00035 #include "gtkroomlist.h"
00036 #include "gtklog.h"
00037 #include "server.h"
00038
00039 #include "utils.h"
00040 #include "buddy_info.h"
00041 #include "buddy_opt.h"
00042 #include "buddy_status.h"
00043 #include "char_conv.h"
00044 #include "group_find.h"
00045 #include "group_im.h"
00046 #include "group_info.h"
00047 #include "group_join.h"
00048 #include "group_opt.h"
00049 #include "group.h"
00050 #include "header_info.h"
00051 #include "im.h"
00052 #include "infodlg.h"
00053 #include "keep_alive.h"
00054 #include "ip_location.h"
00055 #include "login_logout.h"
00056 #include "qq_proxy.h"
00057 #include "send_core.h"
00058 #include "qq.h"
00059 #include "send_file.h"
00060 #include "version.h"
00061
00062 #define OPENQ_VER VERSION
00063 #define OPENQ_AUTHOR "Puzzlebird"
00064 #define OPENQ_WEBSITE "http://openq.linuxsir.org"
00065 #define QQ_TCP_QUERY_PORT "8000"
00066 #define QQ_UDP_PORT "8000"
00067
00068 const gchar *udp_server_list[] = {
00069 "sz.tencent.com",
00070 "sz2.tencent.com",
00071 "sz3.tencent.com",
00072 "sz4.tencent.com",
00073 "sz5.tencent.com",
00074 "sz6.tencent.com",
00075 "sz7.tencent.com",
00076 "202.96.170.64",
00077 "64.144.238.155",
00078 "202.104.129.254"
00079 };
00080 const gint udp_server_amount = (sizeof(udp_server_list) / sizeof(udp_server_list[0]));
00081
00082
00083 const gchar *tcp_server_list[] = {
00084 "tcpconn.tencent.com",
00085 "tcpconn2.tencent.com",
00086 "tcpconn3.tencent.com",
00087 "tcpconn4.tencent.com",
00088 };
00089 const gint tcp_server_amount = (sizeof(tcp_server_list) / sizeof(tcp_server_list[0]));
00090
00091 void _qq_login(GaimAccount * account)
00092 {
00093 const gchar *qq_server, *qq_port;
00094 qq_data *qd;
00095 GaimConnection *gc;
00096 gboolean login_hidden, use_tcp;
00097
00098 g_return_if_fail(account != NULL);
00099
00100 gc = gaim_account_get_connection(account);
00101 g_return_if_fail(gc != NULL);
00102
00103 gc->flags |= GAIM_CONNECTION_HTML | GAIM_CONNECTION_NO_BGCOLOR | GAIM_CONNECTION_AUTO_RESP;
00104
00105 qd = g_new0(qq_data, 1);
00106 gc->proto_data = qd;
00107
00108 qq_server = gaim_account_get_string(account, "server", NULL);
00109 qq_port = gaim_account_get_string(account, "port", NULL);
00110 use_tcp = gaim_account_get_bool(account, "use_tcp", FALSE);
00111 login_hidden = gaim_account_get_bool(account, "hidden", FALSE);
00112
00113 qd->use_tcp = use_tcp;
00114
00115 if (login_hidden)
00116 qd->login_mode = QQ_LOGIN_MODE_HIDDEN;
00117 else
00118 qd->login_mode = QQ_LOGIN_MODE_NORMAL;
00119
00120 if (qq_server == NULL || strlen(qq_server) == 0)
00121 qq_server = use_tcp ?
00122 tcp_server_list[random() % tcp_server_amount] : udp_server_list[random() % udp_server_amount];
00123
00124 if (qq_port == NULL || strtol(qq_port, NULL, 10) == 0)
00125 qq_port = use_tcp ? QQ_TCP_QUERY_PORT : QQ_UDP_PORT;
00126
00127 gaim_connection_update_progress(gc, _("Connecting"), 0, QQ_CONNECT_STEPS);
00128
00129 if (qq_connect(account, qq_server, strtol(qq_port, NULL, 10), use_tcp, FALSE) < 0)
00130 gaim_connection_error(gc, _("Unable to connect."));
00131 }
00132
00133
00134 void _qq_close(GaimConnection * gc)
00135 {
00136 g_return_if_fail(gc != NULL);
00137 qq_disconnect(gc);
00138 }
00139
00140
00141 const gchar *_qq_list_icon(GaimAccount * a, GaimBuddy * b)
00142 {
00143 gchar *filename;
00144 qq_buddy *q_bud;
00145 gchar icon_suffix;
00146
00147
00148 if (b == NULL || b->proto_data == NULL)
00149 return "qq";
00150
00151 q_bud = (qq_buddy *) b->proto_data;
00152 icon_suffix = get_suffix_from_status(q_bud->status);
00153 filename = get_icon_name(q_bud->icon / 3 + 1, icon_suffix);
00154
00155 return filename;
00156 }
00157
00158
00159 gchar *_qq_status_text(GaimBuddy * b)
00160 {
00161 qq_buddy *q_bud;
00162 gboolean show_info, having_video;
00163 GString *status;
00164 gchar *ret;
00165
00166 g_return_val_if_fail(b != NULL, NULL);
00167
00168 show_info = gaim_prefs_get_bool("/plugins/prpl/qq/show_status_by_icon");
00169 if (!show_info)
00170 return NULL;
00171
00172 q_bud = (qq_buddy *) b->proto_data;
00173 if (q_bud == NULL)
00174 return NULL;
00175
00176 status = g_string_new("");
00177
00178 switch (q_bud->gender) {
00179 case QQ_BUDDY_GENDER_GG:
00180 g_string_append(status, " GG");
00181 break;
00182 case QQ_BUDDY_GENDER_MM:
00183 g_string_append(status, " MM");
00184 break;
00185 case QQ_BUDDY_GENDER_UNKNOWN:
00186 g_string_append(status, "^_*");
00187 break;
00188 default:
00189 g_string_append(status, "^_^");
00190 }
00191
00192 g_string_append_printf(status, " Age: %d", q_bud->age);
00193
00194 having_video = q_bud->comm_flag & QQ_COMM_FLAG_VIDEO;
00195
00196
00197
00198 if (having_video)
00199 g_string_append(status, " (video)");
00200
00201 ret = status->str;
00202 g_string_free(status, FALSE);
00203
00204 return ret;
00205 }
00206
00207
00208 gchar *_qq_tooltip_text(GaimBuddy * b)
00209 {
00210 qq_buddy *q_bud;
00211 gchar *ret;
00212 gchar *country, *country_utf8, *city, *city_utf8;
00213 guint32 ip_value;
00214 GString *tooltip;
00215
00216 g_return_val_if_fail(b != NULL, NULL);
00217
00218 q_bud = (qq_buddy *) b->proto_data;
00219 if (q_bud == NULL)
00220 return NULL;
00221
00222 if (is_online(q_bud->status)) {
00223 ip_value = ntohl(*(guint32 *) (q_bud->ip));
00224 tooltip = g_string_new("\n");
00225 if (qq_ip_get_location(ip_value, &country, &city)) {
00226 country_utf8 = qq_to_utf8(country, QQ_CHARSET_DEFAULT);
00227 city_utf8 = qq_to_utf8(city, QQ_CHARSET_DEFAULT);
00228 g_string_append_printf(tooltip, "%s, %s\n", country_utf8, city_utf8);
00229 g_free(country);
00230 g_free(city);
00231 g_free(country_utf8);
00232 g_free(city_utf8);
00233 }
00234 g_string_append(tooltip, "<span foreground=\"blue\" font_desc=\"Courier 10\">");
00235 g_string_append_printf(tooltip, "[%s] %s</span>", (q_bud->comm_flag & QQ_COMM_FLAG_TCP_MODE)
00236 ? "TCP" : "UDP", gen_ip_str(q_bud->ip));
00237 ret = tooltip->str;
00238 g_string_free(tooltip, FALSE);
00239 return ret;
00240 }
00241
00242 return NULL;
00243 }
00244
00245
00246
00247 void _qq_list_emblems(GaimBuddy * b, char **se, char **sw, char **nw, char **ne) {
00248
00249 return;
00250 }
00251
00252
00253 GList *_qq_away_states(GaimConnection * gc)
00254 {
00255 GList *m;
00256
00257 g_return_val_if_fail(gc != NULL, NULL);
00258
00259 m = NULL;
00260 m = g_list_append(m, _("QQ: Available"));
00261 m = g_list_append(m, _("QQ: Away"));
00262 m = g_list_append(m, _("QQ: Invisible"));
00263 m = g_list_append(m, GAIM_AWAY_CUSTOM);
00264
00265 return m;
00266 }
00267
00268
00269 void _qq_set_away(GaimConnection * gc, const char *state, const char *msg)
00270 {
00271 qq_data *qd;
00272
00273 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
00274
00275 qd = (qq_data *) gc->proto_data;
00276 if (gc->away) {
00277 g_free(gc->away);
00278 gc->away = NULL;
00279 }
00280
00281 if (msg) {
00282 qd->status = QQ_SELF_STATUS_CUSTOM;
00283 gc->away = g_strdup(msg);
00284 } else if (state) {
00285 gc->away = g_strdup("");
00286 if (g_ascii_strcasecmp(state, _("QQ: Available")) == 0)
00287 qd->status = QQ_SELF_STATUS_AVAILABLE;
00288 else if (g_ascii_strcasecmp(state, _("QQ: Away")) == 0)
00289 qd->status = QQ_SELF_STATUS_AWAY;
00290 else if (g_ascii_strcasecmp(state, _("QQ: Invisible")) == 0)
00291 qd->status = QQ_SELF_STATUS_INVISIBLE;
00292 else if (g_ascii_strcasecmp(state, GAIM_AWAY_CUSTOM) == 0) {
00293 if (gc->is_idle)
00294 qd->status = QQ_SELF_STATUS_IDLE;
00295 else
00296 qd->status = QQ_SELF_STATUS_AVAILABLE;
00297 }
00298 } else if (gc->is_idle)
00299 qd->status = QQ_SELF_STATUS_IDLE;
00300 else
00301 qd->status = QQ_SELF_STATUS_AVAILABLE;
00302
00303 qq_send_packet_change_status(gc);
00304 }
00305
00306
00307 gint _qq_send_im(GaimConnection * gc, const gchar * who, const gchar * message, GaimConvImFlags flags) {
00308 gint type, to_uid;
00309 gchar *msg, *msg_with_qq_smiley;
00310 qq_data *qd;
00311
00312 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL && who != NULL, -1);
00313
00314 qd = (qq_data *) gc->proto_data;
00315
00316 g_return_val_if_fail(strlen(message) <= QQ_MSG_IM_MAX, -E2BIG);
00317
00318 type = (flags == GAIM_CONV_IM_AUTO_RESP ? QQ_IM_AUTO_REPLY : QQ_IM_TEXT);
00319 to_uid = gaim_name_to_uid(who);
00320
00321
00322 if (to_uid == qd->uid)
00323 serv_got_im(gc, who, message, flags, time(NULL));
00324 else {
00325 msg = utf8_to_qq(message, QQ_CHARSET_DEFAULT);
00326 msg_with_qq_smiley = gaim_smiley_to_qq(msg);
00327 qq_send_packet_im(gc, to_uid, msg_with_qq_smiley, type);
00328 g_free(msg);
00329 g_free(msg_with_qq_smiley);
00330 }
00331
00332 return 1;
00333 }
00334
00335
00336 gint _qq_chat_send(GaimConnection * gc, gint channel, const gchar * message)
00337 {
00338 gchar *msg, *msg_with_qq_smiley;
00339 qq_group *group;
00340
00341 g_return_val_if_fail(gc != NULL && message != NULL, -1);
00342 g_return_val_if_fail(strlen(message) <= QQ_MSG_IM_MAX, -E2BIG);
00343
00344 group = qq_group_find_by_channel(gc, channel);
00345 g_return_val_if_fail(group != NULL, -1);
00346
00347 msg = utf8_to_qq(message, QQ_CHARSET_DEFAULT);
00348 msg_with_qq_smiley = gaim_smiley_to_qq(msg);
00349 qq_send_packet_group_im(gc, group, msg_with_qq_smiley);
00350 g_free(msg);
00351 g_free(msg_with_qq_smiley);
00352
00353 return 1;
00354 }
00355
00356
00357 void _qq_get_info(GaimConnection * gc, const gchar * who)
00358 {
00359 guint32 uid;
00360 qq_data *qd;
00361
00362 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
00363 qd = gc->proto_data;
00364 uid = gaim_name_to_uid(who);
00365
00366 if (uid <= 0) {
00367 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Not valid QQid: %s\n", who);
00368 gaim_notify_error(gc, NULL, _("Invalid name, please input in qq-xxxxxxxx format"), NULL);
00369 return;
00370 }
00371
00372 qq_send_packet_get_info(gc, uid, TRUE);
00373 }
00374
00375
00376 void _qq_menu_get_my_info(GaimPluginAction * action)
00377 {
00378 GaimConnection *gc = (GaimConnection *) action->context;
00379 qq_data *qd;
00380
00381 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
00382
00383 qd = (qq_data *) gc->proto_data;
00384 _qq_get_info(gc, uid_to_gaim_name(qd->uid));
00385 }
00386
00387
00388 void _qq_menu_block_buddy(GaimBlistNode * node, gpointer param_who)
00389 {
00390 guint32 uid;
00391 gc_and_uid *g;
00392 GaimBuddy *buddy;
00393 GaimConnection *gc;
00394 const gchar *who = param_who;
00395
00396 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node));
00397
00398 buddy = (GaimBuddy *) node;
00399 gc = gaim_account_get_connection(buddy->account);
00400 g_return_if_fail(gc != NULL && who != NULL);
00401
00402 uid = gaim_name_to_uid(who);
00403 g_return_if_fail(uid > 0);
00404
00405 g = g_new0(gc_and_uid, 1);
00406 g->gc = gc;
00407 g->uid = uid;
00408
00409 gaim_request_action(gc, _("Block Buddy"),
00410 _("Are you sure to block this buddy?"), NULL,
00411 1, g, 2,
00412 _("Cancel"),
00413 G_CALLBACK(qq_do_nothing_with_gc_and_uid),
00414 _("Block"), G_CALLBACK(qq_block_buddy_with_gc_and_uid));
00415 }
00416
00417
00418 void _qq_menu_show_login_info(GaimPluginAction * action)
00419 {
00420 GaimConnection *gc = (GaimConnection *) action->context;
00421 qq_data *qd;
00422 GString *info;
00423
00424 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
00425
00426 qd = (qq_data *) gc->proto_data;
00427 info = g_string_new("<html><body>\n");
00428
00429 g_string_append_printf(info, _("<b>Current Online</b>: %d<br>\n"), qd->all_online);
00430 g_string_append_printf(info, _("<b>Last Refresh</b>: %s<br>\n"), ctime(&qd->last_get_online));
00431
00432 g_string_append(info, "<hr>\n");
00433
00434 g_string_append_printf(info, _("<b>Connection Mode</b>: %s<br>\n"), qd->use_tcp ? "TCP" : "UDP");
00435 g_string_append_printf(info, _("<b>Server IP</b>: %s: %d<br>\n"), qd->server_ip, qd->server_port);
00436 g_string_append_printf(info, _("<b>My Public IP</b>: %s<br>\n"), qd->my_ip);
00437
00438 g_string_append(info, "<hr>\n");
00439 g_string_append(info, "<i>Information below may not be accurate</i><br>\n");
00440
00441 g_string_append_printf(info, _("<b>Login Time</b>: %s<br>\n"), ctime(&qd->login_time));
00442 g_string_append_printf(info, _("<b>Last Login IP</b>: %s<br>\n"), qd->last_login_ip);
00443 g_string_append_printf(info, _("<b>Last Login Time</b>: %s\n"), ctime(&qd->last_login_time));
00444
00445 g_string_append(info, "</body></html>");
00446
00447 gaim_notify_formatted(gc, NULL, _("Login Information"), NULL, info->str, NULL, NULL);
00448
00449 g_string_free(info, TRUE);
00450 }
00451
00452
00453 void _qq_menu_show_about(GaimPluginAction * action)
00454 {
00455 GaimConnection *gc = (GaimConnection *) action->context;
00456 qq_data *qd;
00457 GString *info;
00458 gchar *head;
00459
00460 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
00461
00462 qd = (qq_data *) gc->proto_data;
00463 info = g_string_new("<html><body>\n");
00464
00465 g_string_append_printf(info, _("<b>Author</b> : %s<br>\n"), OPENQ_AUTHOR);
00466 g_string_append(info, "Copyright (c) 2004. All rights reserved.<br><br>\n");
00467
00468 g_string_append(info, _("<p><b>Code Contributors</b><br>\n"));
00469 g_string_append(info, "henryouly : file transfer, udp sock5 proxy and qq_show<br>\n");
00470 g_string_append(info, "arfankai : fixed bugs in char_conv.c<br>\n");
00471 g_string_append(info, "rakescar : provided filter for HTML tag<br>\n");
00472 g_string_append(info, "yyw : improved performance on PPC linux<br>\n");
00473 g_string_append(info, "lvxiang : provided ip to location original code<br><br>\n");
00474
00475 g_string_append(info, _("<p><b>Acknowledgement</b><br>\n"));
00476 g_string_append(info, "Shufeng Tan : http://sf.net/projects/perl-oicq<br>\n");
00477 g_string_append(info, "Jeff Ye : http://www.sinomac.com<br>\n");
00478 g_string_append(info, "Hu Zheng : http://forlinux.yeah.net<br><br>\n");
00479
00480 g_string_append(info, "<p>And, my parents...\n");
00481
00482 g_string_append(info, "</body></html>");
00483
00484 head = g_strdup_printf("About QQ Plugin Ver %s", OPENQ_VER);
00485 gaim_notify_formatted(gc, NULL, head, NULL, info->str, NULL, NULL);
00486
00487 g_free(head);
00488 g_string_free(info, TRUE);
00489 }
00490
00491
00492 void _qq_menu_any_cmd_send_cb(GaimConnection * gc, GaimRequestFields * fields)
00493 {
00494 GList *groups, *flds;
00495 GaimRequestField *field;
00496 const gchar *id, *value;
00497 gchar *cmd_str, *data_str, **segments;
00498 guint16 cmd;
00499 guint8 *data;
00500 gint i, data_len;
00501
00502 cmd_str = NULL;
00503 data_str = NULL;
00504 cmd = 0x00;
00505 data = NULL;
00506 data_len = 0;
00507
00508 for (groups = gaim_request_fields_get_groups(fields); groups; groups = groups->next) {
00509 for (flds = gaim_request_field_group_get_fields(groups->data); flds; flds = flds->next) {
00510 field = flds->data;
00511 id = gaim_request_field_get_id(field);
00512 value = gaim_request_field_string_get_value(field);
00513
00514 if (!g_ascii_strcasecmp(id, "cmd"))
00515 cmd_str = g_strdup(value);
00516 else if (!g_ascii_strcasecmp(id, "data"))
00517 data_str = g_strdup(value);
00518 }
00519 }
00520
00521 if (cmd_str != NULL)
00522 cmd = (guint16) strtol(cmd_str, NULL, 16);
00523
00524 if (data_str != NULL) {
00525 if (NULL == (segments = split_data(data_str, strlen(data_str), ",", 0))) {
00526 g_free(cmd_str);
00527 g_free(data_str);
00528 return;
00529 }
00530 for (data_len = 0; segments[data_len] != NULL; data_len++) {;
00531 }
00532 data = g_newa(guint8, data_len);
00533 for (i = 0; i < data_len; i++)
00534 data[i] = (guint8) strtol(segments[i], NULL, 16);
00535 g_strfreev(segments);
00536 }
00537
00538 if (cmd && data_len > 0) {
00539 gaim_debug(GAIM_DEBUG_INFO, "QQ",
00540 "Send Any cmd: %s, data dump\n%s", qq_get_cmd_desc(cmd), hex_dump_to_str(data, data_len));
00541 qq_send_cmd(gc, cmd, TRUE, 0, TRUE, data, data_len);
00542 }
00543
00544 g_free(cmd_str);
00545 g_free(data_str);
00546 }
00547
00548
00549 void _qq_menu_any_cmd(GaimPluginAction * action)
00550 {
00551 GaimConnection *gc = (GaimConnection *) action->context;
00552 qq_data *qd;
00553 gchar *tips;
00554 GaimRequestField *field;
00555 GaimRequestFields *fields;
00556 GaimRequestFieldGroup *group;
00557
00558 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
00559 qd = (qq_data *) gc->proto_data;
00560
00561 tips = _("Separate the value with \",\"\nAllow \"0x\" before each value");
00562 fields = gaim_request_fields_new();
00563 group = gaim_request_field_group_new(NULL);
00564 gaim_request_fields_add_group(fields, group);
00565
00566
00567 field = gaim_request_field_string_new("cmd", _("CMD Code"), NULL, FALSE);
00568 gaim_request_field_group_add_field(group, field);
00569
00570
00571
00572 field = gaim_request_field_string_new("data", _("Raw Data"), NULL, FALSE);
00573 gaim_request_field_group_add_field(group, field);
00574
00575 gaim_request_fields(gc, _("QQ Any Command"),
00576 _("Send Arbitrary Command"), tips, fields,
00577 _("Send"), G_CALLBACK(_qq_menu_any_cmd_send_cb), _("Cancel"), NULL, gc);
00578 }
00579
00580
00581 void _qq_menu_search_or_add_permanent_group(GaimPluginAction * action)
00582 {
00583 gaim_gtk_roomlist_dialog_show();
00584 }
00585
00586 void _qq_menu_create_permanent_group(GaimPluginAction * action)
00587 {
00588 GaimConnection *gc = (GaimConnection *) action->context;
00589 g_return_if_fail(gc != NULL);
00590 gaim_request_input(gc, _("Create QQ Qun"),
00591 _("Input Qun name here"),
00592 _("Only QQ member can create permanent Qun"),
00593 "OpenQ", FALSE, FALSE, NULL,
00594 _("Create"), G_CALLBACK(qq_group_create_with_name), _("Cancel"), NULL, gc);
00595 }
00596
00597 void _qq_menu_unsubscribe_group(GaimBlistNode * node, gpointer param_components)
00598 {
00599 GaimBuddy *buddy;
00600 GaimConnection *gc;
00601 GHashTable *components = (GHashTable *) param_components;
00602
00603 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node));
00604
00605 buddy = (GaimBuddy *) node;
00606 gc = gaim_account_get_connection(buddy->account);
00607
00608 g_return_if_fail(gc != NULL && components != NULL);
00609 qq_group_exit(gc, components);
00610 }
00611
00612 void _qq_menu_manage_group(GaimBlistNode * node, gpointer param_components)
00613 {
00614 GaimBuddy *buddy;
00615 GaimConnection *gc;
00616 GHashTable *components = (GHashTable *) param_components;
00617
00618 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node));
00619
00620 buddy = (GaimBuddy *) node;
00621 gc = gaim_account_get_connection(buddy->account);
00622
00623 g_return_if_fail(gc != NULL && components != NULL);
00624 qq_group_manage_group(gc, components);
00625 }
00626
00627 void _qq_menu_show_system_message(GaimPluginAction *action)
00628 {
00629 GaimConnection *gc = (GaimConnection *) action->context;
00630 g_return_if_fail ( gc != NULL );
00631 gaim_gtk_log_show(GAIM_LOG_IM, "systemim", gaim_connection_get_account(gc));
00632 }
00633
00634 void _qq_menu_send_file(GaimBlistNode * node, gpointer ignored)
00635 {
00636 GaimBuddy *buddy;
00637 GaimConnection *gc;
00638 qq_buddy *q_bud;
00639
00640 g_return_if_fail (GAIM_BLIST_NODE_IS_BUDDY (node));
00641 buddy = (GaimBuddy *) node;
00642 q_bud = (qq_buddy *) buddy->proto_data;
00643
00644 gc = gaim_account_get_connection (buddy->account);
00645 g_return_if_fail (gc != NULL && gc->proto_data != NULL);
00646 qq_send_file(gc, buddy->name, NULL);
00647
00648 }
00649
00650
00651 GList *_qq_actions(GaimPlugin * plugin, gpointer context)
00652 {
00653 GList *m;
00654 GaimPluginAction *act;
00655
00656 m = NULL;
00657 act = gaim_plugin_action_new(_("Modify My Information"), _qq_menu_get_my_info);
00658 m = g_list_append(m, act);
00659
00660 act = gaim_plugin_action_new(_("Show Login Information"), _qq_menu_show_login_info);
00661 m = g_list_append(m, act);
00662
00663 act = gaim_plugin_action_new(_("Show System Message"), _qq_menu_show_system_message);
00664 m = g_list_append(m, act);
00665
00666 act = gaim_plugin_action_new(_("Any QQ Command"), _qq_menu_any_cmd);
00667 m = g_list_append(m, act);
00668
00669 act = gaim_plugin_action_new(_("Qun: Search a permanent Qun"), _qq_menu_search_or_add_permanent_group);
00670 m = g_list_append(m, act);
00671
00672 act = gaim_plugin_action_new(_("Qun: Create a permanent Qun"), _qq_menu_create_permanent_group);
00673 m = g_list_append(m, act);
00674
00675 act = gaim_plugin_action_new(_("About QQ Plugin"), _qq_menu_show_about);
00676 m = g_list_append(m, act);
00677
00678 return m;
00679 }
00680
00681
00682 GList *_qq_buddy_menu(GaimBlistNode * node)
00683 {
00684 GList *m;
00685 GaimBlistNodeAction *act;
00686
00687 m = NULL;
00688 act = gaim_blist_node_action_new(_("Block this buddy"), _qq_menu_block_buddy, NULL);
00689 m = g_list_append(m, act);
00690
00691 act = gaim_blist_node_action_new(_("Send File"), _qq_menu_send_file, NULL);
00692 m = g_list_append(m, act);
00693
00694
00695 return m;
00696 }
00697
00698
00699 GList *_qq_chat_menu(GaimConnection * gc, GHashTable * components)
00700 {
00701 GList *m;
00702 GaimBlistNodeAction *act;
00703
00704 m = NULL;
00705 act = gaim_blist_node_action_new(_("Exit this QQ Qun"), _qq_menu_unsubscribe_group, NULL);
00706 m = g_list_append(m, act);
00707
00708 act = gaim_blist_node_action_new(_("Show Details"), _qq_menu_manage_group, NULL);
00709 m = g_list_append(m, act);
00710
00711 return m;
00712 }
00713
00714 void _qq_keep_alive(GaimConnection * gc)
00715 {
00716 qq_group *group;
00717 qq_data *qd;
00718 GList *list;
00719
00720 g_return_if_fail(gc != NULL);
00721 if (NULL == (qd = (qq_data *) gc->proto_data))
00722 return;
00723
00724 list = qd->groups;
00725 while (list != NULL) {
00726 group = (qq_group *) list->data;
00727 if (group->my_status == QQ_GROUP_MEMBER_STATUS_IS_MEMBER ||
00728 group->my_status == QQ_GROUP_MEMBER_STATUS_IS_ADMIN)
00729 qq_send_cmd_group_get_group_info(gc, group);
00730 list = list->next;
00731 }
00732
00733 qq_send_packet_keep_alive(gc);
00734
00735 }
00736
00737
00738
00739 void _qq_get_chat_buddy_info(GaimConnection * gc, gint channel, const gchar * who)
00740 {
00741 gchar *gaim_name;
00742 g_return_if_fail(gc != NULL && gc->proto_data != NULL && who != NULL);
00743
00744 gaim_name = qq_group_find_member_by_channel_and_nickname(gc, channel, who);
00745 if (gaim_name != NULL)
00746 _qq_get_info(gc, gaim_name);
00747
00748 }
00749
00750
00751
00752 gchar *_qq_get_chat_buddy_real_name(GaimConnection * gc, gint channel, const gchar * who) {
00753
00754 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL && who != NULL, NULL);
00755 return qq_group_find_member_by_channel_and_nickname(gc, channel, who);
00756
00757 }
00758
00759 void qq_function_not_implemented(GaimConnection * gc)
00760 {
00761 gaim_notify_warning(gc, NULL, _("This function has not be implemented yet"), _("Please wait for new version"));
00762 }
00763
00764 GaimPluginPrefFrame *get_plugin_pref_frame(GaimPlugin * plugin)
00765 {
00766 GaimPluginPrefFrame *frame;
00767 GaimPluginPref *ppref;
00768
00769 frame = gaim_plugin_pref_frame_new();
00770
00771 ppref = gaim_plugin_pref_new_with_label(_("Convert IP to location"));
00772 gaim_plugin_pref_frame_add(frame, ppref);
00773
00774 ppref = gaim_plugin_pref_new_with_name_and_label("/plugins/prpl/qq/ipfile", _("IP file"));
00775 gaim_plugin_pref_frame_add(frame, ppref);
00776
00777 ppref = gaim_plugin_pref_new_with_label(_("Display Options"));
00778 gaim_plugin_pref_frame_add(frame, ppref);
00779
00780 ppref = gaim_plugin_pref_new_with_name_and_label
00781 ("/plugins/prpl/qq/show_status_by_icon", _("Show gender/age information beside buddy icons"));
00782 gaim_plugin_pref_frame_add(frame, ppref);
00783
00784 ppref = gaim_plugin_pref_new_with_name_and_label
00785 ("/plugins/prpl/qq/show_fake_video", _("Fake an video for GAIM QQ (re-login to activate)"));
00786 gaim_plugin_pref_frame_add(frame, ppref);
00787
00788 ppref = gaim_plugin_pref_new_with_label(_("System Options"));
00789 gaim_plugin_pref_frame_add(frame, ppref);
00790
00791 ppref = gaim_plugin_pref_new_with_name_and_label
00792 ("/plugins/prpl/qq/prompt_for_missing_packet", _("Prompt user for actions if there are missing packets"));
00793 gaim_plugin_pref_frame_add(frame, ppref);
00794
00795 ppref = gaim_plugin_pref_new_with_name_and_label
00796 ("/plugins/prpl/qq/prompt_group_msg_on_recv", _("Pop up Qun chat window when receive Qun message"));
00797 gaim_plugin_pref_frame_add(frame, ppref);
00798
00799 ppref = gaim_plugin_pref_new_with_name_and_label("/plugins/prpl/qq/datadir", _("OpenQ installed directory"));
00800 gaim_plugin_pref_frame_add(frame, ppref);
00801
00802 return frame;
00803
00804 }
00805
00806 GaimPlugin *my_protocol = NULL;
00807 static GaimPluginProtocolInfo prpl_info = {
00808 OPT_PROTO_CHAT_TOPIC | OPT_PROTO_USE_POINTSIZE,
00809 NULL,
00810 NULL,
00811 NO_BUDDY_ICONS,
00812 _qq_list_icon,
00813 _qq_list_emblems,
00814 _qq_status_text,
00815 _qq_tooltip_text,
00816 _qq_away_states,
00817 _qq_buddy_menu,
00818 qq_chat_info,
00819 NULL,
00820 _qq_login,
00821 _qq_close,
00822 _qq_send_im,
00823 NULL,
00824 NULL,
00825 _qq_get_info,
00826 _qq_set_away,
00827 NULL,
00828 NULL,
00829 qq_add_buddy,
00830 NULL,
00831 qq_remove_buddy,
00832 NULL,
00833 NULL,
00834 NULL,
00835 NULL,
00836 NULL,
00837 NULL,
00838 NULL,
00839 qq_group_join,
00840 NULL,
00841 NULL,
00842 NULL,
00843 NULL,
00844 NULL,
00845 _qq_chat_send,
00846 _qq_keep_alive,
00847 NULL,
00848 _qq_get_chat_buddy_info,
00849 NULL,
00850 NULL,
00851 NULL,
00852 NULL,
00853 NULL,
00854 NULL,
00855 NULL,
00856 NULL,
00857 NULL,
00858 _qq_get_chat_buddy_real_name,
00859 NULL,
00860 NULL,
00861 qq_roomlist_get_list,
00862 qq_roomlist_cancel,
00863 NULL,
00864 NULL,
00865 NULL
00866 };
00867
00868 static GaimPluginUiInfo prefs_info = {
00869 get_plugin_pref_frame
00870 };
00871
00872 static GaimPluginInfo info = {
00873 GAIM_PLUGIN_MAGIC,
00874 GAIM_MAJOR_VERSION,
00875 GAIM_MINOR_VERSION,
00876 GAIM_PLUGIN_PROTOCOL,
00877 NULL,
00878 0,
00879 NULL,
00880 GAIM_PRIORITY_DEFAULT,
00882 "prpl-qq",
00883 "QQ",
00884 OPENQ_VER,
00886 N_("QQ Protocol Plugin"),
00888 N_("QQ Protocol Plugin"),
00889 OPENQ_AUTHOR,
00890 OPENQ_WEBSITE,
00892 NULL,
00893 NULL,
00894 NULL,
00896 NULL,
00897 &prpl_info,
00898 &prefs_info,
00899 _qq_actions
00900 };
00901
00902
00903 void init_plugin(GaimPlugin * plugin)
00904 {
00905 GaimAccountOption *option;
00906
00907 bindtextdomain(PACKAGE, LOCALEDIR);
00908 bind_textdomain_codeset(PACKAGE, "UTF-8");
00909
00910 option = gaim_account_option_bool_new(_("Login in TCP"), "use_tcp", FALSE);
00911 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
00912
00913 option = gaim_account_option_bool_new(_("Login Hidden"), "hidden", FALSE);
00914 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
00915
00916 option = gaim_account_option_string_new(_("QQ Server"), "server", NULL);
00917 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
00918
00919 option = gaim_account_option_string_new(_("QQ Port"), "port", NULL);
00920 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
00921
00922 my_protocol = plugin;
00923
00924 gaim_prefs_add_none("/plugins/prpl/qq");
00925 gaim_prefs_add_string("/plugins/prpl/qq/ipfile", NULL);
00926 gaim_prefs_add_bool("/plugins/prpl/qq/show_status_by_icon", TRUE);
00927 gaim_prefs_add_bool("/plugins/prpl/qq/show_fake_video", FALSE);
00928 gaim_prefs_add_string("/plugins/prpl/qq/datadir", DATADIR);
00929 gaim_prefs_add_bool("/plugins/prpl/qq/prompt_for_missing_packet", FALSE);
00930 gaim_prefs_add_bool("/plugins/prpl/qq/prompt_group_msg_on_recv", TRUE);
00931 }
00932
00933 GAIM_INIT_PLUGIN(qq, init_plugin, info);