| 1 /** |
|
| 2 * @file qq.c |
|
| 3 * |
|
| 4 * purple |
|
| 5 * |
|
| 6 * Purple is the legal property of its developers, whose names are too numerous |
|
| 7 * to list here. Please refer to the COPYRIGHT file distributed with this |
|
| 8 * source distribution. |
|
| 9 * |
|
| 10 * This program is free software; you can redistribute it and/or modify |
|
| 11 * it under the terms of the GNU General Public License as published by |
|
| 12 * the Free Software Foundation; either version 2 of the License, or |
|
| 13 * (at your option) any later version. |
|
| 14 * |
|
| 15 * This program is distributed in the hope that it will be useful, |
|
| 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 18 * GNU General Public License for more details. |
|
| 19 * |
|
| 20 * You should have received a copy of the GNU General Public License |
|
| 21 * along with this program; if not, write to the Free Software |
|
| 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
|
| 23 */ |
|
| 24 |
|
| 25 #include "internal.h" |
|
| 26 |
|
| 27 #include "accountopt.h" |
|
| 28 #include "debug.h" |
|
| 29 #include "notify.h" |
|
| 30 #include "prefs.h" |
|
| 31 #include "prpl.h" |
|
| 32 #include "privacy.h" |
|
| 33 #include "request.h" |
|
| 34 #include "roomlist.h" |
|
| 35 #include "server.h" |
|
| 36 #include "util.h" |
|
| 37 |
|
| 38 #include "buddy_info.h" |
|
| 39 #include "buddy_memo.h" |
|
| 40 #include "buddy_opt.h" |
|
| 41 #include "buddy_list.h" |
|
| 42 #include "char_conv.h" |
|
| 43 #include "group.h" |
|
| 44 #include "group_im.h" |
|
| 45 #include "group_info.h" |
|
| 46 #include "group_join.h" |
|
| 47 #include "group_opt.h" |
|
| 48 #include "group_internal.h" |
|
| 49 #include "qq_define.h" |
|
| 50 #include "im.h" |
|
| 51 #include "qq_process.h" |
|
| 52 #include "qq_base.h" |
|
| 53 #include "packet_parse.h" |
|
| 54 #include "qq.h" |
|
| 55 #include "qq_network.h" |
|
| 56 #include "send_file.h" |
|
| 57 #include "utils.h" |
|
| 58 #include "version.h" |
|
| 59 |
|
| 60 #define OPENQ_VERSION "0.3.2-p20" |
|
| 61 |
|
| 62 static GList *server_list_build(gchar select) |
|
| 63 { |
|
| 64 GList *list = NULL; |
|
| 65 |
|
| 66 if ( select == 'T' || select == 'A') { |
|
| 67 list = g_list_append(list, "tcpconn.tencent.com:8000"); |
|
| 68 list = g_list_append(list, "tcpconn2.tencent.com:8000"); |
|
| 69 list = g_list_append(list, "tcpconn3.tencent.com:8000"); |
|
| 70 list = g_list_append(list, "tcpconn4.tencent.com:8000"); |
|
| 71 list = g_list_append(list, "tcpconn5.tencent.com:8000"); |
|
| 72 list = g_list_append(list, "tcpconn6.tencent.com:8000"); |
|
| 73 } |
|
| 74 if ( select == 'U' || select == 'A') { |
|
| 75 list = g_list_append(list, "sz.tencent.com:8000"); |
|
| 76 list = g_list_append(list, "sz2.tencent.com:8000"); |
|
| 77 list = g_list_append(list, "sz3.tencent.com:8000"); |
|
| 78 list = g_list_append(list, "sz4.tencent.com:8000"); |
|
| 79 list = g_list_append(list, "sz5.tencent.com:8000"); |
|
| 80 list = g_list_append(list, "sz6.tencent.com:8000"); |
|
| 81 list = g_list_append(list, "sz7.tencent.com:8000"); |
|
| 82 list = g_list_append(list, "sz8.tencent.com:8000"); |
|
| 83 list = g_list_append(list, "sz9.tencent.com:8000"); |
|
| 84 } |
|
| 85 return list; |
|
| 86 } |
|
| 87 |
|
| 88 static void server_list_create(PurpleAccount *account) |
|
| 89 { |
|
| 90 PurpleConnection *gc; |
|
| 91 qq_data *qd; |
|
| 92 PurpleProxyInfo *gpi; |
|
| 93 const gchar *custom_server; |
|
| 94 |
|
| 95 gc = purple_account_get_connection(account); |
|
| 96 g_return_if_fail(gc != NULL && gc->proto_data != NULL); |
|
| 97 qd = gc->proto_data; |
|
| 98 |
|
| 99 gpi = purple_proxy_get_setup(account); |
|
| 100 |
|
| 101 qd->use_tcp = purple_account_get_bool(account, "use_tcp", TRUE); |
|
| 102 |
|
| 103 custom_server = purple_account_get_string(account, "server", NULL); |
|
| 104 |
|
| 105 if (custom_server != NULL) { |
|
| 106 purple_debug_info("QQ", "Select server '%s'\n", custom_server); |
|
| 107 if (*custom_server != '\0' && g_ascii_strcasecmp(custom_server, "auto") != 0) { |
|
| 108 qd->servers = g_list_append(qd->servers, g_strdup(custom_server)); |
|
| 109 return; |
|
| 110 } |
|
| 111 } |
|
| 112 |
|
| 113 if (qd->use_tcp) { |
|
| 114 qd->servers = server_list_build('T'); |
|
| 115 return; |
|
| 116 } |
|
| 117 |
|
| 118 qd->servers = server_list_build('U'); |
|
| 119 } |
|
| 120 |
|
| 121 static void server_list_remove_all(qq_data *qd) |
|
| 122 { |
|
| 123 g_return_if_fail(qd != NULL); |
|
| 124 |
|
| 125 purple_debug_info("QQ", "free server list\n"); |
|
| 126 g_list_free(qd->servers); |
|
| 127 qd->curr_server = NULL; |
|
| 128 } |
|
| 129 |
|
| 130 static void qq_login(PurpleAccount *account) |
|
| 131 { |
|
| 132 PurpleConnection *gc; |
|
| 133 qq_data *qd; |
|
| 134 PurplePresence *presence; |
|
| 135 const gchar *version_str; |
|
| 136 |
|
| 137 g_return_if_fail(account != NULL); |
|
| 138 |
|
| 139 gc = purple_account_get_connection(account); |
|
| 140 g_return_if_fail(gc != NULL); |
|
| 141 |
|
| 142 gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_AUTO_RESP; |
|
| 143 |
|
| 144 qd = g_new0(qq_data, 1); |
|
| 145 memset(qd, 0, sizeof(qq_data)); |
|
| 146 qd->gc = gc; |
|
| 147 gc->proto_data = qd; |
|
| 148 |
|
| 149 presence = purple_account_get_presence(account); |
|
| 150 if(purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_INVISIBLE)) { |
|
| 151 qd->login_mode = QQ_LOGIN_MODE_HIDDEN; |
|
| 152 } else if(purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_AWAY) |
|
| 153 || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_EXTENDED_AWAY)) { |
|
| 154 qd->login_mode = QQ_LOGIN_MODE_AWAY; |
|
| 155 } else { |
|
| 156 qd->login_mode = QQ_LOGIN_MODE_NORMAL; |
|
| 157 } |
|
| 158 |
|
| 159 server_list_create(account); |
|
| 160 purple_debug_info("QQ", "Server list has %d\n", g_list_length(qd->servers)); |
|
| 161 |
|
| 162 version_str = purple_account_get_string(account, "client_version", NULL); |
|
| 163 qd->client_tag = QQ_CLIENT_0D55; /* set default as QQ2005 */ |
|
| 164 qd->client_version = 2005; |
|
| 165 if (version_str != NULL && strlen(version_str) != 0) { |
|
| 166 if (strcmp(version_str, "qq2007") == 0) { |
|
| 167 qd->client_tag = QQ_CLIENT_111D; |
|
| 168 qd->client_version = 2007; |
|
| 169 } else if (strcmp(version_str, "qq2008") == 0) { |
|
| 170 qd->client_tag = QQ_CLIENT_115B; |
|
| 171 qd->client_version = 2008; |
|
| 172 } |
|
| 173 } |
|
| 174 |
|
| 175 qd->is_show_notice = purple_account_get_bool(account, "show_notice", TRUE); |
|
| 176 qd->is_show_news = purple_account_get_bool(account, "show_news", TRUE); |
|
| 177 qd->is_show_chat = purple_account_get_bool(account, "show_chat", TRUE); |
|
| 178 |
|
| 179 qd->resend_times = purple_prefs_get_int("/plugins/prpl/qq/resend_times"); |
|
| 180 if (qd->resend_times <= 1) qd->itv_config.resend = 4; |
|
| 181 |
|
| 182 qd->itv_config.resend = purple_prefs_get_int("/plugins/prpl/qq/resend_interval"); |
|
| 183 if (qd->itv_config.resend <= 0) qd->itv_config.resend = 3; |
|
| 184 purple_debug_info("QQ", "Resend interval %d, retries %d\n", |
|
| 185 qd->itv_config.resend, qd->resend_times); |
|
| 186 |
|
| 187 qd->itv_config.keep_alive = purple_account_get_int(account, "keep_alive_interval", 60); |
|
| 188 if (qd->itv_config.keep_alive < 30) qd->itv_config.keep_alive = 30; |
|
| 189 qd->itv_config.keep_alive /= qd->itv_config.resend; |
|
| 190 qd->itv_count.keep_alive = qd->itv_config.keep_alive; |
|
| 191 |
|
| 192 qd->itv_config.update = purple_account_get_int(account, "update_interval", 300); |
|
| 193 if (qd->itv_config.update > 0) { |
|
| 194 if (qd->itv_config.update < qd->itv_config.keep_alive) { |
|
| 195 qd->itv_config.update = qd->itv_config.keep_alive; |
|
| 196 } |
|
| 197 qd->itv_config.update /= qd->itv_config.resend; |
|
| 198 qd->itv_count.update = qd->itv_config.update; |
|
| 199 } else { |
|
| 200 qd->itv_config.update = 0; |
|
| 201 } |
|
| 202 |
|
| 203 qd->connect_watcher = purple_timeout_add_seconds(0, qq_connect_later, gc); |
|
| 204 } |
|
| 205 |
|
| 206 /* clean up the given QQ connection and free all resources */ |
|
| 207 static void qq_close(PurpleConnection *gc) |
|
| 208 { |
|
| 209 qq_data *qd; |
|
| 210 |
|
| 211 g_return_if_fail(gc != NULL && gc->proto_data); |
|
| 212 qd = gc->proto_data; |
|
| 213 |
|
| 214 if (qd->check_watcher > 0) { |
|
| 215 purple_timeout_remove(qd->check_watcher); |
|
| 216 qd->check_watcher = 0; |
|
| 217 } |
|
| 218 |
|
| 219 if (qd->connect_watcher > 0) { |
|
| 220 purple_timeout_remove(qd->connect_watcher); |
|
| 221 qd->connect_watcher = 0; |
|
| 222 } |
|
| 223 |
|
| 224 qq_disconnect(gc); |
|
| 225 |
|
| 226 if (qd->redirect) g_free(qd->redirect); |
|
| 227 if (qd->ld.token) g_free(qd->ld.token); |
|
| 228 if (qd->ld.token_ex) g_free(qd->ld.token_ex); |
|
| 229 if (qd->captcha.token) g_free(qd->captcha.token); |
|
| 230 if (qd->captcha.data) g_free(qd->captcha.data); |
|
| 231 |
|
| 232 server_list_remove_all(qd); |
|
| 233 |
|
| 234 g_free(qd); |
|
| 235 gc->proto_data = NULL; |
|
| 236 } |
|
| 237 |
|
| 238 /* returns the icon name for a buddy or protocol */ |
|
| 239 static const gchar *qq_list_icon(PurpleAccount *a, PurpleBuddy *b) |
|
| 240 { |
|
| 241 return "qq"; |
|
| 242 } |
|
| 243 |
|
| 244 |
|
| 245 /* a short status text beside buddy icon*/ |
|
| 246 static gchar *qq_status_text(PurpleBuddy *b) |
|
| 247 { |
|
| 248 qq_buddy_data *bd; |
|
| 249 GString *status; |
|
| 250 |
|
| 251 bd = purple_buddy_get_protocol_data(b); |
|
| 252 if (bd == NULL) |
|
| 253 return NULL; |
|
| 254 |
|
| 255 status = g_string_new(""); |
|
| 256 |
|
| 257 switch(bd->status) { |
|
| 258 case QQ_BUDDY_OFFLINE: |
|
| 259 g_string_append(status, _("Offline")); |
|
| 260 break; |
|
| 261 case QQ_BUDDY_ONLINE_NORMAL: |
|
| 262 g_string_append(status, _("Online")); |
|
| 263 break; |
|
| 264 /* TODO What does this status mean? Labelling it as offline... */ |
|
| 265 case QQ_BUDDY_CHANGE_TO_OFFLINE: |
|
| 266 g_string_append(status, _("Offline")); |
|
| 267 break; |
|
| 268 case QQ_BUDDY_ONLINE_AWAY: |
|
| 269 g_string_append(status, _("Away")); |
|
| 270 break; |
|
| 271 case QQ_BUDDY_ONLINE_INVISIBLE: |
|
| 272 g_string_append(status, _("Invisible")); |
|
| 273 break; |
|
| 274 case QQ_BUDDY_ONLINE_BUSY: |
|
| 275 g_string_append(status, _("Busy")); |
|
| 276 break; |
|
| 277 default: |
|
| 278 g_string_printf(status, _("Unknown-%d"), bd->status); |
|
| 279 } |
|
| 280 |
|
| 281 return g_string_free(status, FALSE); |
|
| 282 } |
|
| 283 |
|
| 284 |
|
| 285 /* a floating text when mouse is on the icon, show connection status here */ |
|
| 286 static void qq_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) |
|
| 287 { |
|
| 288 qq_buddy_data *bd; |
|
| 289 gchar *tmp; |
|
| 290 GString *str; |
|
| 291 |
|
| 292 g_return_if_fail(b != NULL); |
|
| 293 |
|
| 294 bd = purple_buddy_get_protocol_data(b); |
|
| 295 if (bd == NULL) |
|
| 296 return; |
|
| 297 |
|
| 298 /* if (PURPLE_BUDDY_IS_ONLINE(b) && bd != NULL) */ |
|
| 299 if (bd->ip.s_addr != 0) { |
|
| 300 str = g_string_new(NULL); |
|
| 301 g_string_printf(str, "%s:%d", inet_ntoa(bd->ip), bd->port); |
|
| 302 if (bd->comm_flag & QQ_COMM_FLAG_TCP_MODE) { |
|
| 303 g_string_append(str, " TCP"); |
|
| 304 } else { |
|
| 305 g_string_append(str, " UDP"); |
|
| 306 } |
|
| 307 g_string_free(str, TRUE); |
|
| 308 } |
|
| 309 |
|
| 310 tmp = g_strdup_printf("%d", bd->age); |
|
| 311 purple_notify_user_info_add_pair(user_info, _("Age"), tmp); |
|
| 312 g_free(tmp); |
|
| 313 |
|
| 314 switch (bd->gender) { |
|
| 315 case QQ_BUDDY_GENDER_GG: |
|
| 316 purple_notify_user_info_add_pair(user_info, _("Gender"), _("Male")); |
|
| 317 break; |
|
| 318 case QQ_BUDDY_GENDER_MM: |
|
| 319 purple_notify_user_info_add_pair(user_info, _("Gender"), _("Female")); |
|
| 320 break; |
|
| 321 case QQ_BUDDY_GENDER_UNKNOWN: |
|
| 322 purple_notify_user_info_add_pair(user_info, _("Gender"), _("Unknown")); |
|
| 323 break; |
|
| 324 default: |
|
| 325 tmp = g_strdup_printf("Error (%d)", bd->gender); |
|
| 326 purple_notify_user_info_add_pair(user_info, _("Gender"), tmp); |
|
| 327 g_free(tmp); |
|
| 328 } |
|
| 329 |
|
| 330 if (bd->level) { |
|
| 331 tmp = g_strdup_printf("%d", bd->level); |
|
| 332 purple_notify_user_info_add_pair(user_info, _("Level"), tmp); |
|
| 333 g_free(tmp); |
|
| 334 } |
|
| 335 |
|
| 336 str = g_string_new(NULL); |
|
| 337 if (bd->comm_flag & QQ_COMM_FLAG_QQ_MEMBER) { |
|
| 338 g_string_append( str, _("Member") ); |
|
| 339 } |
|
| 340 if (bd->comm_flag & QQ_COMM_FLAG_QQ_VIP) { |
|
| 341 g_string_append( str, _(" VIP") ); |
|
| 342 } |
|
| 343 if (bd->comm_flag & QQ_COMM_FLAG_TCP_MODE) { |
|
| 344 g_string_append( str, _(" TCP") ); |
|
| 345 } |
|
| 346 if (bd->comm_flag & QQ_COMM_FLAG_MOBILE) { |
|
| 347 g_string_append( str, _(" FromMobile") ); |
|
| 348 } |
|
| 349 if (bd->comm_flag & QQ_COMM_FLAG_BIND_MOBILE) { |
|
| 350 g_string_append( str, _(" BindMobile") ); |
|
| 351 } |
|
| 352 if (bd->comm_flag & QQ_COMM_FLAG_VIDEO) { |
|
| 353 g_string_append( str, _(" Video") ); |
|
| 354 } |
|
| 355 |
|
| 356 if (bd->ext_flag & QQ_EXT_FLAG_ZONE) { |
|
| 357 g_string_append( str, _(" Zone") ); |
|
| 358 } |
|
| 359 purple_notify_user_info_add_pair(user_info, _("Flag"), str->str); |
|
| 360 |
|
| 361 g_string_free(str, TRUE); |
|
| 362 |
|
| 363 #ifdef DEBUG |
|
| 364 tmp = g_strdup_printf( "%s (%04X)", |
|
| 365 qq_get_ver_desc(bd->client_tag), |
|
| 366 bd->client_tag ); |
|
| 367 purple_notify_user_info_add_pair(user_info, _("Ver"), tmp); |
|
| 368 g_free(tmp); |
|
| 369 |
|
| 370 tmp = g_strdup_printf( "Ext 0x%X, Comm 0x%X", |
|
| 371 bd->ext_flag, bd->comm_flag ); |
|
| 372 purple_notify_user_info_add_pair(user_info, _("Flag"), tmp); |
|
| 373 g_free(tmp); |
|
| 374 #endif |
|
| 375 } |
|
| 376 |
|
| 377 /* we can show tiny icons on the four corners of buddy icon, */ |
|
| 378 static const char *qq_list_emblem(PurpleBuddy *b) |
|
| 379 { |
|
| 380 PurpleAccount *account; |
|
| 381 PurpleConnection *gc; |
|
| 382 qq_data *qd; |
|
| 383 qq_buddy_data *buddy; |
|
| 384 |
|
| 385 if (!b || !(account = purple_buddy_get_account(b)) || |
|
| 386 !(gc = purple_account_get_connection(account)) || |
|
| 387 !(qd = purple_connection_get_protocol_data(gc))) |
|
| 388 return NULL; |
|
| 389 |
|
| 390 buddy = purple_buddy_get_protocol_data(b); |
|
| 391 if (!buddy) { |
|
| 392 return "not-authorized"; |
|
| 393 } |
|
| 394 |
|
| 395 if (buddy->comm_flag & QQ_COMM_FLAG_MOBILE) |
|
| 396 return "mobile"; |
|
| 397 if (buddy->comm_flag & QQ_COMM_FLAG_VIDEO) |
|
| 398 return "video"; |
|
| 399 if (buddy->comm_flag & QQ_COMM_FLAG_QQ_MEMBER) |
|
| 400 return "qq_member"; |
|
| 401 |
|
| 402 return NULL; |
|
| 403 } |
|
| 404 |
|
| 405 /* QQ away status (used to initiate QQ away packet) */ |
|
| 406 static GList *qq_status_types(PurpleAccount *ga) |
|
| 407 { |
|
| 408 PurpleStatusType *status; |
|
| 409 GList *types = NULL; |
|
| 410 |
|
| 411 status = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, |
|
| 412 "available", _("Available"), TRUE, TRUE, FALSE); |
|
| 413 types = g_list_append(types, status); |
|
| 414 |
|
| 415 status = purple_status_type_new_full(PURPLE_STATUS_AWAY, |
|
| 416 "away", _("Away"), TRUE, TRUE, FALSE); |
|
| 417 types = g_list_append(types, status); |
|
| 418 |
|
| 419 status = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE, |
|
| 420 "invisible", _("Invisible"), TRUE, TRUE, FALSE); |
|
| 421 types = g_list_append(types, status); |
|
| 422 |
|
| 423 status = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, |
|
| 424 "busy", _("Busy"), TRUE, TRUE, FALSE); |
|
| 425 types = g_list_append(types, status); |
|
| 426 |
|
| 427 status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, |
|
| 428 "offline", _("Offline"), TRUE, TRUE, FALSE); |
|
| 429 types = g_list_append(types, status); |
|
| 430 |
|
| 431 status = purple_status_type_new_full(PURPLE_STATUS_MOBILE, |
|
| 432 "mobile", NULL, FALSE, FALSE, TRUE); |
|
| 433 types = g_list_append(types, status); |
|
| 434 |
|
| 435 return types; |
|
| 436 } |
|
| 437 |
|
| 438 /* initiate QQ away with proper change_status packet */ |
|
| 439 static void qq_change_status(PurpleAccount *account, PurpleStatus *status) |
|
| 440 { |
|
| 441 PurpleConnection *gc = purple_account_get_connection(account); |
|
| 442 |
|
| 443 qq_request_change_status(gc, 0); |
|
| 444 } |
|
| 445 |
|
| 446 /* send packet to get who's detailed information */ |
|
| 447 static void qq_show_buddy_info(PurpleConnection *gc, const gchar *who) |
|
| 448 { |
|
| 449 guint32 uid; |
|
| 450 qq_data *qd; |
|
| 451 |
|
| 452 qd = gc->proto_data; |
|
| 453 uid = purple_name_to_uid(who); |
|
| 454 |
|
| 455 if (uid <= 0) { |
|
| 456 purple_debug_error("QQ", "Not valid QQid: %s\n", who); |
|
| 457 purple_notify_error(gc, NULL, _("Invalid name"), NULL); |
|
| 458 return; |
|
| 459 } |
|
| 460 |
|
| 461 if (qd->client_version >= 2007) { |
|
| 462 qq_request_get_level_2007(gc, uid); |
|
| 463 } else { |
|
| 464 qq_request_get_level(gc, uid); |
|
| 465 } |
|
| 466 qq_request_buddy_info(gc, uid, 0, QQ_BUDDY_INFO_DISPLAY); |
|
| 467 } |
|
| 468 |
|
| 469 static void action_update_all_rooms(PurplePluginAction *action) |
|
| 470 { |
|
| 471 PurpleConnection *gc = (PurpleConnection *) action->context; |
|
| 472 qq_data *qd; |
|
| 473 |
|
| 474 g_return_if_fail(NULL != gc && NULL != gc->proto_data); |
|
| 475 qd = (qq_data *) gc->proto_data; |
|
| 476 |
|
| 477 if ( !qd->is_login ) { |
|
| 478 return; |
|
| 479 } |
|
| 480 |
|
| 481 qq_update_all_rooms(gc, 0, 0); |
|
| 482 } |
|
| 483 |
|
| 484 static void action_change_icon(PurplePluginAction *action) |
|
| 485 { |
|
| 486 PurpleConnection *gc = (PurpleConnection *) action->context; |
|
| 487 qq_data *qd; |
|
| 488 gchar *icon_name; |
|
| 489 gchar *icon_path; |
|
| 490 |
|
| 491 g_return_if_fail(NULL != gc && NULL != gc->proto_data); |
|
| 492 qd = (qq_data *) gc->proto_data; |
|
| 493 |
|
| 494 if ( !qd->is_login ) { |
|
| 495 return; |
|
| 496 } |
|
| 497 |
|
| 498 icon_name = qq_get_icon_name(qd->my_icon); |
|
| 499 icon_path = qq_get_icon_path(icon_name); |
|
| 500 g_free(icon_name); |
|
| 501 |
|
| 502 purple_debug_info("QQ", "Change prev icon %s to...\n", icon_path); |
|
| 503 purple_request_file(action, _("Select icon..."), icon_path, |
|
| 504 FALSE, |
|
| 505 G_CALLBACK(qq_change_icon_cb), NULL, |
|
| 506 purple_connection_get_account(gc), NULL, NULL, |
|
| 507 gc); |
|
| 508 g_free(icon_path); |
|
| 509 } |
|
| 510 |
|
| 511 static void action_modify_info_base(PurplePluginAction *action) |
|
| 512 { |
|
| 513 PurpleConnection *gc = (PurpleConnection *) action->context; |
|
| 514 qq_data *qd; |
|
| 515 |
|
| 516 g_return_if_fail(NULL != gc && NULL != gc->proto_data); |
|
| 517 qd = (qq_data *) gc->proto_data; |
|
| 518 qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_BASE); |
|
| 519 } |
|
| 520 |
|
| 521 static void action_modify_info_ext(PurplePluginAction *action) |
|
| 522 { |
|
| 523 PurpleConnection *gc = (PurpleConnection *) action->context; |
|
| 524 qq_data *qd; |
|
| 525 |
|
| 526 g_return_if_fail(NULL != gc && NULL != gc->proto_data); |
|
| 527 qd = (qq_data *) gc->proto_data; |
|
| 528 qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_EXT); |
|
| 529 } |
|
| 530 |
|
| 531 static void action_modify_info_addr(PurplePluginAction *action) |
|
| 532 { |
|
| 533 PurpleConnection *gc = (PurpleConnection *) action->context; |
|
| 534 qq_data *qd; |
|
| 535 |
|
| 536 g_return_if_fail(NULL != gc && NULL != gc->proto_data); |
|
| 537 qd = (qq_data *) gc->proto_data; |
|
| 538 qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_ADDR); |
|
| 539 } |
|
| 540 |
|
| 541 static void action_modify_info_contact(PurplePluginAction *action) |
|
| 542 { |
|
| 543 PurpleConnection *gc = (PurpleConnection *) action->context; |
|
| 544 qq_data *qd; |
|
| 545 |
|
| 546 g_return_if_fail(NULL != gc && NULL != gc->proto_data); |
|
| 547 qd = (qq_data *) gc->proto_data; |
|
| 548 qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_CONTACT); |
|
| 549 } |
|
| 550 |
|
| 551 static void action_change_password(PurplePluginAction *action) |
|
| 552 { |
|
| 553 PurpleConnection *gc = (PurpleConnection *) action->context; |
|
| 554 |
|
| 555 g_return_if_fail(NULL != gc && NULL != gc->proto_data); |
|
| 556 purple_notify_uri(NULL, "https://password.qq.com"); |
|
| 557 } |
|
| 558 |
|
| 559 /* show a brief summary of what we get from login packet */ |
|
| 560 static void action_show_account_info(PurplePluginAction *action) |
|
| 561 { |
|
| 562 PurpleConnection *gc = (PurpleConnection *) action->context; |
|
| 563 qq_data *qd; |
|
| 564 GString *info; |
|
| 565 struct tm *tm_local; |
|
| 566 int index; |
|
| 567 |
|
| 568 g_return_if_fail(NULL != gc && NULL != gc->proto_data); |
|
| 569 qd = (qq_data *) gc->proto_data; |
|
| 570 info = g_string_new("<html><body>"); |
|
| 571 |
|
| 572 tm_local = localtime(&qd->login_time); |
|
| 573 g_string_append_printf(info, _("<b>Login time</b>: %d-%d-%d, %d:%d:%d<br>\n"), |
|
| 574 (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, |
|
| 575 tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); |
|
| 576 g_string_append_printf(info, _("<b>Total Online Buddies</b>: %d<br>\n"), qd->online_total); |
|
| 577 tm_local = localtime(&qd->online_last_update); |
|
| 578 g_string_append_printf(info, _("<b>Last Refresh</b>: %d-%d-%d, %d:%d:%d<br>\n"), |
|
| 579 (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, |
|
| 580 tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); |
|
| 581 |
|
| 582 g_string_append(info, "<hr>"); |
|
| 583 |
|
| 584 g_string_append_printf(info, _("<b>Server</b>: %s<br>\n"), qd->curr_server); |
|
| 585 g_string_append_printf(info, _("<b>Client Tag</b>: %s<br>\n"), qq_get_ver_desc(qd->client_tag)); |
|
| 586 g_string_append_printf(info, _("<b>Connection Mode</b>: %s<br>\n"), qd->use_tcp ? "TCP" : "UDP"); |
|
| 587 g_string_append_printf(info, _("<b>My Internet IP</b>: %s:%d<br>\n"), inet_ntoa(qd->my_ip), qd->my_port); |
|
| 588 |
|
| 589 g_string_append(info, "<hr>"); |
|
| 590 g_string_append(info, "<i>Network Status</i><br>\n"); |
|
| 591 g_string_append_printf(info, _("<b>Sent</b>: %lu<br>\n"), qd->net_stat.sent); |
|
| 592 g_string_append_printf(info, _("<b>Resend</b>: %lu<br>\n"), qd->net_stat.resend); |
|
| 593 g_string_append_printf(info, _("<b>Lost</b>: %lu<br>\n"), qd->net_stat.lost); |
|
| 594 g_string_append_printf(info, _("<b>Received</b>: %lu<br>\n"), qd->net_stat.rcved); |
|
| 595 g_string_append_printf(info, _("<b>Received Duplicate</b>: %lu<br>\n"), qd->net_stat.rcved_dup); |
|
| 596 |
|
| 597 g_string_append(info, "<hr>"); |
|
| 598 g_string_append(info, "<i>Last Login Information</i><br>\n"); |
|
| 599 |
|
| 600 for (index = 0; index < sizeof(qd->last_login_time) / sizeof(time_t); index++) { |
|
| 601 tm_local = localtime(&qd->last_login_time[index]); |
|
| 602 g_string_append_printf(info, _("<b>Time</b>: %d-%d-%d, %d:%d:%d<br>\n"), |
|
| 603 (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, |
|
| 604 tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); |
|
| 605 } |
|
| 606 if (qd->last_login_ip.s_addr != 0) { |
|
| 607 g_string_append_printf(info, _("<b>IP</b>: %s<br>\n"), inet_ntoa(qd->last_login_ip)); |
|
| 608 } |
|
| 609 |
|
| 610 g_string_append(info, "</body></html>"); |
|
| 611 |
|
| 612 purple_notify_formatted(gc, NULL, _("Login Information"), NULL, info->str, NULL, NULL); |
|
| 613 |
|
| 614 g_string_free(info, TRUE); |
|
| 615 } |
|
| 616 |
|
| 617 static void action_about_openq(PurplePluginAction *action) |
|
| 618 { |
|
| 619 PurpleConnection *gc = (PurpleConnection *) action->context; |
|
| 620 qq_data *qd; |
|
| 621 GString *info; |
|
| 622 gchar *title; |
|
| 623 |
|
| 624 g_return_if_fail(NULL != gc && NULL != gc->proto_data); |
|
| 625 qd = (qq_data *) gc->proto_data; |
|
| 626 |
|
| 627 info = g_string_new("<html><body>"); |
|
| 628 g_string_append(info, _("<p><b>Original Author</b>:<br>\n")); |
|
| 629 g_string_append(info, "puzzlebird<br>\n"); |
|
| 630 g_string_append(info, "<br>\n"); |
|
| 631 |
|
| 632 g_string_append(info, _("<p><b>Code Contributors</b>:<br>\n")); |
|
| 633 g_string_append(info, "gfhuang(poppyer) : patches for libpurple 2.0.0beta2, maintainer<br>\n"); |
|
| 634 g_string_append(info, "Yuan Qingyun : patches for libpurple 1.5.0, maintainer<br>\n"); |
|
| 635 g_string_append(info, "henryouly : file transfer, udp sock5 proxy and qq_show, maintainer<br>\n"); |
|
| 636 g_string_append(info, "hzhr : maintainer<br>\n"); |
|
| 637 g_string_append(info, "joymarquis : maintainer<br>\n"); |
|
| 638 g_string_append(info, "arfankai : fixed bugs in char_conv.c<br>\n"); |
|
| 639 g_string_append(info, "rakescar : provided filter for HTML tag<br>\n"); |
|
| 640 g_string_append(info, "yyw : improved performance on PPC linux<br>\n"); |
|
| 641 g_string_append(info, "lvxiang : provided ip to location original code<br>\n"); |
|
| 642 g_string_append(info, "markhuetsch : OpenQ merge into libpurple, maintainer 2006-2007<br>\n"); |
|
| 643 g_string_append(info, "ccpaging : maintainer since 2007<br>\n"); |
|
| 644 g_string_append(info, "icesky : maintainer since 2007<br>\n"); |
|
| 645 g_string_append(info, "csyfek : faces, maintainer since 2007<br>\n"); |
|
| 646 g_string_append(info, "<br>\n"); |
|
| 647 |
|
| 648 g_string_append(info, _("<p><b>Lovely Patch Writers</b>:<br>\n")); |
|
| 649 g_string_append(info, "gnap : message displaying, documentation<br>\n"); |
|
| 650 g_string_append(info, "manphiz : qun processing<br>\n"); |
|
| 651 g_string_append(info, "moo : qun processing<br>\n"); |
|
| 652 g_string_append(info, "Coly Li : qun processing<br>\n"); |
|
| 653 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"); |
|
| 654 g_string_append(info, "Chengming Wang : buddy memo<br>\n"); |
|
| 655 g_string_append(info, "lonicerae : chat room window bugfix, server list bugfix, buddy memo<br>\n"); |
|
| 656 g_string_append(info, "<br>\n"); |
|
| 657 |
|
| 658 g_string_append(info, _("<p><b>Acknowledgement</b>:<br>\n")); |
|
| 659 g_string_append(info, "Shufeng Tan : http://sf.net/projects/perl-oicq<br>\n"); |
|
| 660 g_string_append(info, "Jeff Ye : http://www.sinomac.com<br>\n"); |
|
| 661 g_string_append(info, "Hu Zheng : http://forlinux.yeah.net<br>\n"); |
|
| 662 g_string_append(info, "yunfan : http://www.myswear.net<br>\n"); |
|
| 663 g_string_append(info, "OpenQ Team : http://openq.linuxsir.org<br>\n"); |
|
| 664 g_string_append(info, "LumaQQ Team : http://lumaqq.linuxsir.org<br>\n"); |
|
| 665 g_string_append(info, "Pidgin Team : http://www.pidgin.im<br>\n"); |
|
| 666 g_string_append(info, "Huang Guan : http://home.xxsyzx.com<br>\n"); |
|
| 667 g_string_append(info, "OpenQ Google Group : http://groups.google.com/group/openq<br>\n"); |
|
| 668 g_string_append(info, "<br>\n"); |
|
| 669 |
|
| 670 g_string_append(info, _("<p><b>Scrupulous Testers</b>:<br>\n")); |
|
| 671 g_string_append(info, "yegle<br>\n"); |
|
| 672 g_string_append(info, "cnzhangbx<br>\n"); |
|
| 673 g_string_append(info, "casparant<br>\n"); |
|
| 674 g_string_append(info, "wd<br>\n"); |
|
| 675 g_string_append(info, "x6719620<br>\n"); |
|
| 676 g_string_append(info, "netelk<br>\n"); |
|
| 677 g_string_append(info, _("and more, please let me know... thank you!))")); |
|
| 678 g_string_append(info, "<br>\n<br>\n"); |
|
| 679 g_string_append(info, _("<p><i>And, all the boys in the backroom...</i><br>\n")); |
|
| 680 g_string_append(info, _("<i>Feel free to join us!</i> :)")); |
|
| 681 g_string_append(info, "</body></html>"); |
|
| 682 |
|
| 683 title = g_strdup_printf(_("About OpenQ %s"), OPENQ_VERSION); |
|
| 684 purple_notify_formatted(gc, title, title, NULL, info->str, NULL, NULL); |
|
| 685 |
|
| 686 g_free(title); |
|
| 687 g_string_free(info, TRUE); |
|
| 688 } |
|
| 689 |
|
| 690 /* |
|
| 691 static void _qq_menu_search_or_add_permanent_group(PurplePluginAction *action) |
|
| 692 { |
|
| 693 purple_roomlist_show_with_account(NULL); |
|
| 694 } |
|
| 695 */ |
|
| 696 |
|
| 697 /* |
|
| 698 static void _qq_menu_create_permanent_group(PurplePluginAction * action) |
|
| 699 { |
|
| 700 PurpleConnection *gc = (PurpleConnection *) action->context; |
|
| 701 purple_request_input(gc, _("Create QQ Qun"), |
|
| 702 _("Input Qun name here"), |
|
| 703 _("Only QQ members can create permanent Qun"), |
|
| 704 "OpenQ", FALSE, FALSE, NULL, |
|
| 705 _("Create"), G_CALLBACK(qq_create_room), _("Cancel"), NULL, gc); |
|
| 706 } |
|
| 707 */ |
|
| 708 |
|
| 709 static void action_chat_quit(PurpleBlistNode * node) |
|
| 710 { |
|
| 711 PurpleChat *chat = (PurpleChat *)node; |
|
| 712 PurpleAccount *account = purple_chat_get_account(chat); |
|
| 713 PurpleConnection *gc = purple_account_get_connection(account); |
|
| 714 GHashTable *components = purple_chat_get_components(chat); |
|
| 715 gchar *num_str; |
|
| 716 guint32 room_id; |
|
| 717 |
|
| 718 g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); |
|
| 719 |
|
| 720 g_return_if_fail(components != NULL); |
|
| 721 |
|
| 722 num_str = g_hash_table_lookup(components, QQ_ROOM_KEY_INTERNAL_ID); |
|
| 723 room_id = strtoul(num_str, NULL, 10); |
|
| 724 g_return_if_fail(room_id != 0); |
|
| 725 |
|
| 726 qq_room_quit(gc, room_id); |
|
| 727 } |
|
| 728 |
|
| 729 static void action_chat_get_info(PurpleBlistNode * node) |
|
| 730 { |
|
| 731 PurpleChat *chat = (PurpleChat *)node; |
|
| 732 PurpleAccount *account = purple_chat_get_account(chat); |
|
| 733 PurpleConnection *gc = purple_account_get_connection(account); |
|
| 734 GHashTable *components = purple_chat_get_components(chat); |
|
| 735 gchar *num_str; |
|
| 736 guint32 room_id; |
|
| 737 |
|
| 738 g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); |
|
| 739 |
|
| 740 g_return_if_fail(components != NULL); |
|
| 741 |
|
| 742 num_str = g_hash_table_lookup(components, QQ_ROOM_KEY_INTERNAL_ID); |
|
| 743 room_id = strtoul(num_str, NULL, 10); |
|
| 744 g_return_if_fail(room_id != 0); |
|
| 745 |
|
| 746 qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_INFO, room_id, NULL, 0, |
|
| 747 0, QQ_ROOM_INFO_DISPLAY); |
|
| 748 } |
|
| 749 |
|
| 750 #if 0 |
|
| 751 /* TODO: re-enable this */ |
|
| 752 static void _qq_menu_send_file(PurpleBlistNode * node, gpointer ignored) |
|
| 753 { |
|
| 754 PurpleBuddy *buddy; |
|
| 755 PurpleConnection *gc; |
|
| 756 qq_buddy_data *bd; |
|
| 757 |
|
| 758 g_return_if_fail (PURPLE_BLIST_NODE_IS_BUDDY (node)); |
|
| 759 buddy = (PurpleBuddy *) node; |
|
| 760 bd = (qq_buddy_data *) buddy->proto_data; |
|
| 761 /* if (is_online (bd->status)) { */ |
|
| 762 gc = purple_account_get_connection (buddy->account); |
|
| 763 g_return_if_fail (gc != NULL && gc->proto_data != NULL); |
|
| 764 qq_send_file(gc, buddy->name, NULL); |
|
| 765 /* } */ |
|
| 766 } |
|
| 767 #endif |
|
| 768 |
|
| 769 /* protocol related menus */ |
|
| 770 static GList *qq_actions(PurplePlugin *plugin, gpointer context) |
|
| 771 { |
|
| 772 GList *m; |
|
| 773 PurplePluginAction *act; |
|
| 774 |
|
| 775 m = NULL; |
|
| 776 act = purple_plugin_action_new(_("Change Icon"), action_change_icon); |
|
| 777 m = g_list_append(m, act); |
|
| 778 |
|
| 779 act = purple_plugin_action_new(_("Modify Information"), action_modify_info_base); |
|
| 780 m = g_list_append(m, act); |
|
| 781 |
|
| 782 act = purple_plugin_action_new(_("Modify Extended Information"), action_modify_info_ext); |
|
| 783 m = g_list_append(m, act); |
|
| 784 |
|
| 785 act = purple_plugin_action_new(_("Modify Address"), action_modify_info_addr); |
|
| 786 m = g_list_append(m, act); |
|
| 787 |
|
| 788 act = purple_plugin_action_new(_("Modify Contact"), action_modify_info_contact); |
|
| 789 m = g_list_append(m, act); |
|
| 790 |
|
| 791 act = purple_plugin_action_new(_("Change Password"), action_change_password); |
|
| 792 m = g_list_append(m, act); |
|
| 793 |
|
| 794 act = purple_plugin_action_new(_("Account Information"), action_show_account_info); |
|
| 795 m = g_list_append(m, act); |
|
| 796 |
|
| 797 act = purple_plugin_action_new(_("Update all QQ Quns"), action_update_all_rooms); |
|
| 798 m = g_list_append(m, act); |
|
| 799 |
|
| 800 act = purple_plugin_action_new(_("About OpenQ"), action_about_openq); |
|
| 801 m = g_list_append(m, act); |
|
| 802 /* |
|
| 803 act = purple_plugin_action_new(_("Qun: Search a permanent Qun"), _qq_menu_search_or_add_permanent_group); |
|
| 804 m = g_list_append(m, act); |
|
| 805 |
|
| 806 act = purple_plugin_action_new(_("Qun: Create a permanent Qun"), _qq_menu_create_permanent_group); |
|
| 807 m = g_list_append(m, act); |
|
| 808 */ |
|
| 809 |
|
| 810 return m; |
|
| 811 } |
|
| 812 |
|
| 813 static void qq_add_buddy_from_menu_cb(PurpleBlistNode *node, gpointer data) |
|
| 814 { |
|
| 815 PurpleBuddy *buddy; |
|
| 816 PurpleConnection *gc; |
|
| 817 |
|
| 818 g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); |
|
| 819 |
|
| 820 buddy = (PurpleBuddy *) node; |
|
| 821 gc = purple_account_get_connection(purple_buddy_get_account(buddy)); |
|
| 822 |
|
| 823 qq_add_buddy(gc, buddy, NULL); |
|
| 824 } |
|
| 825 |
|
| 826 static void qq_modify_buddy_memo_from_menu_cb(PurpleBlistNode *node, gpointer data) |
|
| 827 { |
|
| 828 PurpleBuddy *buddy; |
|
| 829 qq_buddy_data *bd; |
|
| 830 PurpleConnection *gc; |
|
| 831 guint32 bd_uid; |
|
| 832 |
|
| 833 g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); |
|
| 834 |
|
| 835 buddy = (PurpleBuddy *)node; |
|
| 836 g_return_if_fail(NULL != buddy); |
|
| 837 |
|
| 838 gc = purple_account_get_connection(purple_buddy_get_account(buddy)); |
|
| 839 g_return_if_fail(NULL != gc); |
|
| 840 |
|
| 841 bd = (qq_buddy_data *)purple_buddy_get_protocol_data(buddy); |
|
| 842 g_return_if_fail(NULL != bd); |
|
| 843 bd_uid = bd->uid; |
|
| 844 |
|
| 845 /* param: gc, uid, update_class, action |
|
| 846 * here, update_class is set to bd_uid. because some memo packages returned |
|
| 847 * without uid, which will make us confused */ |
|
| 848 qq_request_buddy_memo(gc, bd_uid, bd_uid, QQ_BUDDY_MEMO_MODIFY); |
|
| 849 } |
|
| 850 |
|
| 851 static GList *qq_buddy_menu(PurpleBuddy *buddy) |
|
| 852 { |
|
| 853 GList *m = NULL; |
|
| 854 PurpleMenuAction *act; |
|
| 855 qq_buddy_data *bd = purple_buddy_get_protocol_data(buddy); |
|
| 856 |
|
| 857 if (bd == NULL) { |
|
| 858 act = purple_menu_action_new(_("Add Buddy"), |
|
| 859 PURPLE_CALLBACK(qq_add_buddy_from_menu_cb), |
|
| 860 NULL, NULL); |
|
| 861 m = g_list_append(m, act); |
|
| 862 return m; |
|
| 863 } |
|
| 864 |
|
| 865 |
|
| 866 act = purple_menu_action_new(_("Modify Buddy Memo"), |
|
| 867 PURPLE_CALLBACK(qq_modify_buddy_memo_from_menu_cb), |
|
| 868 NULL, NULL); |
|
| 869 m = g_list_append(m, act); |
|
| 870 |
|
| 871 |
|
| 872 /* TODO : not working, temp commented out by gfhuang */ |
|
| 873 #if 0 |
|
| 874 if (bd && is_online(bd->status)) { |
|
| 875 act = purple_menu_action_new(_("Send File"), PURPLE_CALLBACK(_qq_menu_send_file), NULL, NULL); /* add NULL by gfhuang */ |
|
| 876 m = g_list_append(m, act); |
|
| 877 } |
|
| 878 #endif |
|
| 879 return m; |
|
| 880 } |
|
| 881 |
|
| 882 /* chat-related (QQ Qun) menu shown up with right-click */ |
|
| 883 static GList *qq_chat_menu(PurpleBlistNode *node) |
|
| 884 { |
|
| 885 GList *m; |
|
| 886 PurpleMenuAction *act; |
|
| 887 |
|
| 888 m = NULL; |
|
| 889 act = purple_menu_action_new(_("Get Info"), PURPLE_CALLBACK(action_chat_get_info), NULL, NULL); |
|
| 890 m = g_list_append(m, act); |
|
| 891 |
|
| 892 act = purple_menu_action_new(_("Quit Qun"), PURPLE_CALLBACK(action_chat_quit), NULL, NULL); |
|
| 893 m = g_list_append(m, act); |
|
| 894 return m; |
|
| 895 } |
|
| 896 |
|
| 897 /* buddy-related menu shown up with right-click */ |
|
| 898 static GList *qq_blist_node_menu(PurpleBlistNode * node) |
|
| 899 { |
|
| 900 if(PURPLE_BLIST_NODE_IS_CHAT(node)) |
|
| 901 return qq_chat_menu(node); |
|
| 902 |
|
| 903 if(PURPLE_BLIST_NODE_IS_BUDDY(node)) |
|
| 904 return qq_buddy_menu((PurpleBuddy *) node); |
|
| 905 |
|
| 906 return NULL; |
|
| 907 } |
|
| 908 |
|
| 909 /* convert name displayed in a chat channel to original QQ UID */ |
|
| 910 static gchar *chat_name_to_purple_name(const gchar *const name) |
|
| 911 { |
|
| 912 const char *start; |
|
| 913 const char *end; |
|
| 914 gchar *ret; |
|
| 915 |
|
| 916 g_return_val_if_fail(name != NULL, NULL); |
|
| 917 |
|
| 918 /* Sample: (1234567)*/ |
|
| 919 start = strchr(name, '('); |
|
| 920 g_return_val_if_fail(start != NULL, NULL); |
|
| 921 end = strchr(start, ')'); |
|
| 922 g_return_val_if_fail(end != NULL && (end - start) > 1, NULL); |
|
| 923 |
|
| 924 ret = g_strndup(start + 1, end - start - 1); |
|
| 925 |
|
| 926 return ret; |
|
| 927 } |
|
| 928 |
|
| 929 /* convert chat nickname to uid to get this buddy info */ |
|
| 930 /* who is the nickname of buddy in QQ chat-room (Qun) */ |
|
| 931 static void qq_get_chat_buddy_info(PurpleConnection *gc, gint channel, const gchar *who) |
|
| 932 { |
|
| 933 qq_data *qd; |
|
| 934 gchar *uid_str; |
|
| 935 guint32 uid; |
|
| 936 |
|
| 937 purple_debug_info("QQ", "Get chat buddy info of %s\n", who); |
|
| 938 g_return_if_fail(who != NULL); |
|
| 939 |
|
| 940 uid_str = chat_name_to_purple_name(who); |
|
| 941 if (uid_str == NULL) { |
|
| 942 return; |
|
| 943 } |
|
| 944 |
|
| 945 qd = gc->proto_data; |
|
| 946 uid = purple_name_to_uid(uid_str); |
|
| 947 g_free(uid_str); |
|
| 948 |
|
| 949 if (uid <= 0) { |
|
| 950 purple_debug_error("QQ", "Not valid chat name: %s\n", who); |
|
| 951 purple_notify_error(gc, NULL, _("Invalid name"), NULL); |
|
| 952 return; |
|
| 953 } |
|
| 954 |
|
| 955 if (qd->client_version < 2007) { |
|
| 956 qq_request_get_level(gc, uid); |
|
| 957 } |
|
| 958 qq_request_buddy_info(gc, uid, 0, QQ_BUDDY_INFO_DISPLAY); |
|
| 959 } |
|
| 960 |
|
| 961 /* convert chat nickname to uid to invite individual IM to buddy */ |
|
| 962 /* who is the nickname of buddy in QQ chat-room (Qun) */ |
|
| 963 static gchar *qq_get_chat_buddy_real_name(PurpleConnection *gc, gint channel, const gchar *who) |
|
| 964 { |
|
| 965 g_return_val_if_fail(who != NULL, NULL); |
|
| 966 return chat_name_to_purple_name(who); |
|
| 967 } |
|
| 968 |
|
| 969 static PurplePluginProtocolInfo prpl_info = |
|
| 970 { |
|
| 971 OPT_PROTO_CHAT_TOPIC | OPT_PROTO_USE_POINTSIZE, |
|
| 972 NULL, /* user_splits */ |
|
| 973 NULL, /* protocol_options */ |
|
| 974 {"png", 96, 96, 96, 96, 0, PURPLE_ICON_SCALE_SEND}, /* icon_spec */ |
|
| 975 qq_list_icon, /* list_icon */ |
|
| 976 qq_list_emblem, /* list_emblems */ |
|
| 977 qq_status_text, /* status_text */ |
|
| 978 qq_tooltip_text, /* tooltip_text */ |
|
| 979 qq_status_types, /* away_states */ |
|
| 980 qq_blist_node_menu, /* blist_node_menu */ |
|
| 981 qq_chat_info, /* chat_info */ |
|
| 982 qq_chat_info_defaults, /* chat_info_defaults */ |
|
| 983 qq_login, /* open */ |
|
| 984 qq_close, /* close */ |
|
| 985 qq_send_im, /* send_im */ |
|
| 986 NULL, /* set_info */ |
|
| 987 NULL, /* send_typing */ |
|
| 988 qq_show_buddy_info, /* get_info */ |
|
| 989 qq_change_status, /* change status */ |
|
| 990 NULL, /* set_idle */ |
|
| 991 NULL, /* change_passwd */ |
|
| 992 qq_add_buddy, /* add_buddy */ |
|
| 993 NULL, /* add_buddies */ |
|
| 994 qq_remove_buddy, /* remove_buddy */ |
|
| 995 NULL, /* remove_buddies */ |
|
| 996 NULL, /* add_permit */ |
|
| 997 NULL, /* add_deny */ |
|
| 998 NULL, /* rem_permit */ |
|
| 999 NULL, /* rem_deny */ |
|
| 1000 NULL, /* set_permit_deny */ |
|
| 1001 qq_group_join, /* join_chat */ |
|
| 1002 NULL, /* reject chat invite */ |
|
| 1003 NULL, /* get_chat_name */ |
|
| 1004 NULL, /* chat_invite */ |
|
| 1005 NULL, /* chat_leave */ |
|
| 1006 NULL, /* chat_whisper */ |
|
| 1007 qq_chat_send, /* chat_send */ |
|
| 1008 NULL, /* keepalive */ |
|
| 1009 NULL, /* register_user */ |
|
| 1010 qq_get_chat_buddy_info, /* get_cb_info */ |
|
| 1011 NULL, /* get_cb_away */ |
|
| 1012 NULL, /* alias_buddy */ |
|
| 1013 NULL, /* change buddy's group */ |
|
| 1014 NULL, /* rename_group */ |
|
| 1015 NULL, /* buddy_free */ |
|
| 1016 NULL, /* convo_closed */ |
|
| 1017 NULL, /* normalize */ |
|
| 1018 qq_set_custom_icon, |
|
| 1019 NULL, /* remove_group */ |
|
| 1020 qq_get_chat_buddy_real_name, /* get_cb_real_name */ |
|
| 1021 NULL, /* set_chat_topic */ |
|
| 1022 NULL, /* find_blist_chat */ |
|
| 1023 qq_roomlist_get_list, /* roomlist_get_list */ |
|
| 1024 qq_roomlist_cancel, /* roomlist_cancel */ |
|
| 1025 NULL, /* roomlist_expand_category */ |
|
| 1026 NULL, /* can_receive_file */ |
|
| 1027 NULL, /* qq_send_file send_file */ |
|
| 1028 NULL, /* new xfer */ |
|
| 1029 NULL, /* offline_message */ |
|
| 1030 NULL, /* PurpleWhiteboardPrplOps */ |
|
| 1031 NULL, /* send_raw */ |
|
| 1032 NULL, /* roomlist_room_serialize */ |
|
| 1033 NULL, /* unregister_user */ |
|
| 1034 NULL, /* send_attention */ |
|
| 1035 NULL, /* get attention_types */ |
|
| 1036 |
|
| 1037 sizeof(PurplePluginProtocolInfo), /* struct_size */ |
|
| 1038 NULL, /* get_account_text_table */ |
|
| 1039 NULL, /* initiate_media */ |
|
| 1040 NULL /* can_do_media */ |
|
| 1041 }; |
|
| 1042 |
|
| 1043 static PurplePluginInfo info = { |
|
| 1044 PURPLE_PLUGIN_MAGIC, |
|
| 1045 PURPLE_MAJOR_VERSION, |
|
| 1046 PURPLE_MINOR_VERSION, |
|
| 1047 PURPLE_PLUGIN_PROTOCOL, /**< type */ |
|
| 1048 NULL, /**< ui_requirement */ |
|
| 1049 0, /**< flags */ |
|
| 1050 NULL, /**< dependencies */ |
|
| 1051 PURPLE_PRIORITY_DEFAULT, /**< priority */ |
|
| 1052 |
|
| 1053 "prpl-qq", /**< id */ |
|
| 1054 "QQ", /**< name */ |
|
| 1055 DISPLAY_VERSION, /**< version */ |
|
| 1056 /** summary */ |
|
| 1057 N_("QQ Protocol Plugin"), |
|
| 1058 /** description */ |
|
| 1059 N_("QQ Protocol Plugin"), |
|
| 1060 NULL, /**< author */ |
|
| 1061 PURPLE_WEBSITE, /**< homepage */ |
|
| 1062 |
|
| 1063 NULL, /**< load */ |
|
| 1064 NULL, /**< unload */ |
|
| 1065 NULL, /**< destroy */ |
|
| 1066 |
|
| 1067 NULL, /**< ui_info */ |
|
| 1068 &prpl_info, /**< extra_info */ |
|
| 1069 NULL, /**< prefs_info */ |
|
| 1070 qq_actions, |
|
| 1071 |
|
| 1072 /* padding */ |
|
| 1073 NULL, |
|
| 1074 NULL, |
|
| 1075 NULL, |
|
| 1076 NULL |
|
| 1077 }; |
|
| 1078 |
|
| 1079 |
|
| 1080 static void init_plugin(PurplePlugin *plugin) |
|
| 1081 { |
|
| 1082 PurpleAccountOption *option; |
|
| 1083 PurpleKeyValuePair *kvp; |
|
| 1084 GList *server_list = NULL; |
|
| 1085 GList *server_kv_list = NULL; |
|
| 1086 GList *it; |
|
| 1087 /* #ifdef DEBUG */ |
|
| 1088 GList *version_kv_list = NULL; |
|
| 1089 /* #endif */ |
|
| 1090 |
|
| 1091 server_list = server_list_build('A'); |
|
| 1092 |
|
| 1093 purple_prefs_remove("/plugins/prpl/qq/serverlist"); |
|
| 1094 |
|
| 1095 server_kv_list = NULL; |
|
| 1096 kvp = g_new0(PurpleKeyValuePair, 1); |
|
| 1097 kvp->key = g_strdup(_("Auto")); |
|
| 1098 kvp->value = g_strdup("auto"); |
|
| 1099 server_kv_list = g_list_append(server_kv_list, kvp); |
|
| 1100 |
|
| 1101 it = server_list; |
|
| 1102 while(it) { |
|
| 1103 if (it->data != NULL && strlen(it->data) > 0) { |
|
| 1104 kvp = g_new0(PurpleKeyValuePair, 1); |
|
| 1105 kvp->key = g_strdup(it->data); |
|
| 1106 kvp->value = g_strdup(it->data); |
|
| 1107 server_kv_list = g_list_append(server_kv_list, kvp); |
|
| 1108 } |
|
| 1109 it = it->next; |
|
| 1110 } |
|
| 1111 |
|
| 1112 g_list_free(server_list); |
|
| 1113 |
|
| 1114 option = purple_account_option_list_new(_("Select Server"), "server", server_kv_list); |
|
| 1115 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
|
| 1116 |
|
| 1117 kvp = g_new0(PurpleKeyValuePair, 1); |
|
| 1118 kvp->key = g_strdup(_("QQ2005")); |
|
| 1119 kvp->value = g_strdup("qq2005"); |
|
| 1120 version_kv_list = g_list_append(version_kv_list, kvp); |
|
| 1121 |
|
| 1122 kvp = g_new0(PurpleKeyValuePair, 1); |
|
| 1123 kvp->key = g_strdup(_("QQ2007")); |
|
| 1124 kvp->value = g_strdup("qq2007"); |
|
| 1125 version_kv_list = g_list_append(version_kv_list, kvp); |
|
| 1126 |
|
| 1127 kvp = g_new0(PurpleKeyValuePair, 1); |
|
| 1128 kvp->key = g_strdup(_("QQ2008")); |
|
| 1129 kvp->value = g_strdup("qq2008"); |
|
| 1130 version_kv_list = g_list_append(version_kv_list, kvp); |
|
| 1131 |
|
| 1132 option = purple_account_option_list_new(_("Client Version"), "client_version", version_kv_list); |
|
| 1133 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
|
| 1134 |
|
| 1135 option = purple_account_option_bool_new(_("Connect by TCP"), "use_tcp", TRUE); |
|
| 1136 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
|
| 1137 |
|
| 1138 option = purple_account_option_bool_new(_("Show server notice"), "show_notice", TRUE); |
|
| 1139 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
|
| 1140 |
|
| 1141 option = purple_account_option_bool_new(_("Show server news"), "show_news", TRUE); |
|
| 1142 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
|
| 1143 |
|
| 1144 option = purple_account_option_bool_new(_("Show chat room when msg comes"), "show_chat", TRUE); |
|
| 1145 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
|
| 1146 |
|
| 1147 option = purple_account_option_int_new(_("Keep alive interval (seconds)"), "keep_alive_interval", 60); |
|
| 1148 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
|
| 1149 |
|
| 1150 option = purple_account_option_int_new(_("Update interval (seconds)"), "update_interval", 300); |
|
| 1151 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
|
| 1152 |
|
| 1153 purple_prefs_add_none("/plugins/prpl/qq"); |
|
| 1154 purple_prefs_add_bool("/plugins/prpl/qq/show_status_by_icon", TRUE); |
|
| 1155 purple_prefs_add_bool("/plugins/prpl/qq/show_fake_video", FALSE); |
|
| 1156 purple_prefs_add_bool("/plugins/prpl/qq/auto_get_authorize_info", TRUE); |
|
| 1157 purple_prefs_add_int("/plugins/prpl/qq/resend_interval", 3); |
|
| 1158 purple_prefs_add_int("/plugins/prpl/qq/resend_times", 10); |
|
| 1159 } |
|
| 1160 |
|
| 1161 PURPLE_INIT_PLUGIN(qq, init_plugin, info); |
|