comparison libpurple/protocols/qq/qq.c @ 24088:147ada94a1d8

2008.08.16 - ccpaging <ecc_hy(at)hotmail.com> * Rename group to room. If you used pidginqq before, this may create a new room with same title, you may delete old one * Replace purple_debug with purple_debug_info, purple_debug_warning, purple_debug_error * Add server notice and server new, and two options to turn on/off * Minor modify for reducing transaction's debug infor * Minor modifies for system notice and QQ news. * Add 4 new strings need translate compare with p10.
author SHiNE CsyFeK <csyfek@gmail.com>
date Thu, 11 Sep 2008 13:25:07 +0000
parents e16982ad923f
children 2f5a7edd8f68 25f62d21b3f8
comparison
equal deleted inserted replaced
24087:40a4e02027f4 24088:147ada94a1d8
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 */ 23 */
24 24
25 #include "internal.h" 25 #include "internal.h"
26 26
27 #ifdef _WIN32
28 #define random rand
29 #endif
30
31 #include "accountopt.h" 27 #include "accountopt.h"
32 #include "debug.h" 28 #include "debug.h"
33 #include "notify.h" 29 #include "notify.h"
34 #include "prefs.h" 30 #include "prefs.h"
35 #include "prpl.h" 31 #include "prpl.h"
60 #include "version.h" 56 #include "version.h"
61 57
62 #define OPENQ_AUTHOR "Puzzlebird" 58 #define OPENQ_AUTHOR "Puzzlebird"
63 #define OPENQ_WEBSITE "http://openq.sourceforge.net" 59 #define OPENQ_WEBSITE "http://openq.sourceforge.net"
64 60
65 #define QQ_TCP_PORT 8000 61 static GList *server_list_build(gchar select)
66 #define QQ_UDP_PORT 8000 62 {
67 63 GList *list = NULL;
68 static void server_list_create(PurpleAccount *account) { 64
65 if ( select == 'T' || select == 'A') {
66 list = g_list_append(list, "tcpconn.tencent.com:8000");
67 list = g_list_append(list, "tcpconn2.tencent.com:8000");
68 list = g_list_append(list, "tcpconn3.tencent.com:8000");
69 list = g_list_append(list, "tcpconn4.tencent.com:8000");
70 list = g_list_append(list, "tcpconn5.tencent.com:8000");
71 list = g_list_append(list, "tcpconn6.tencent.com:8000");
72 }
73 if ( select == 'U' || select == 'A') {
74 list = g_list_append(list, "sz.tencent.com:8000");
75 list = g_list_append(list, "sz2.tencent.com:8000");
76 list = g_list_append(list, "sz3.tencent.com:8000");
77 list = g_list_append(list, "sz4.tencent.com:8000");
78 list = g_list_append(list, "sz5.tencent.com:8000");
79 list = g_list_append(list, "sz6.tencent.com:8000");
80 list = g_list_append(list, "sz7.tencent.com:8000");
81 list = g_list_append(list, "sz8.tencent.com:8000");
82 list = g_list_append(list, "sz9.tencent.com:8000");
83 }
84 return list;
85 }
86
87 static void server_list_create(PurpleAccount *account)
88 {
69 PurpleConnection *gc; 89 PurpleConnection *gc;
70 qq_data *qd; 90 qq_data *qd;
91 PurpleProxyInfo *gpi;
71 const gchar *user_server; 92 const gchar *user_server;
72 int port; 93
73
74 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Create server list\n");
75 gc = purple_account_get_connection(account); 94 gc = purple_account_get_connection(account);
76 g_return_if_fail(gc != NULL && gc->proto_data != NULL); 95 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
77 qd = gc->proto_data; 96 qd = gc->proto_data;
78 97
79 qd->use_tcp = purple_account_get_bool(account, "use_tcp", TRUE); 98 gpi = purple_proxy_get_setup(account);
80 port = purple_account_get_int(account, "port", 0); 99
81 if (port == 0) { 100 qd->use_tcp = TRUE;
82 if (qd->use_tcp) { 101 if (purple_proxy_info_get_type(gpi) == PURPLE_PROXY_UDP) {
83 port = QQ_TCP_PORT; 102 qd->use_tcp = FALSE;
84 } else { 103 }
85 port = QQ_UDP_PORT; 104
86 }
87 }
88 qd->user_port = port;
89
90 g_return_if_fail(qd->user_server == NULL);
91 user_server = purple_account_get_string(account, "server", NULL); 105 user_server = purple_account_get_string(account, "server", NULL);
92 if (user_server != NULL && strlen(user_server) > 0) { 106 purple_debug_info("QQ", "Select server '%s'\n", user_server);
93 qd->user_server = g_strdup(user_server); 107 if ( (user_server != NULL && strlen(user_server) > 0) && strcasecmp(user_server, "auto") != 0) {
94 } 108 qd->servers = g_list_append(qd->servers, g_strdup(user_server));
95
96 if (qd->user_server != NULL) {
97 qd->servers = g_list_append(qd->servers, qd->user_server);
98 return; 109 return;
99 } 110 }
111
100 if (qd->use_tcp) { 112 if (qd->use_tcp) {
101 qd->servers = g_list_append(qd->servers, "tcpconn.tencent.com"); 113 qd->servers = server_list_build('T');
102 qd->servers = g_list_append(qd->servers, "tcpconn2.tencent.com");
103 qd->servers = g_list_append(qd->servers, "tcpconn3.tencent.com");
104 qd->servers = g_list_append(qd->servers, "tcpconn4.tencent.com");
105 qd->servers = g_list_append(qd->servers, "tcpconn5.tencent.com");
106 qd->servers = g_list_append(qd->servers, "tcpconn6.tencent.com");
107 return; 114 return;
108 } 115 }
109 116
110 qd->servers = g_list_append(qd->servers, "sz.tencent.com"); 117 qd->servers = server_list_build('U');
111 qd->servers = g_list_append(qd->servers, "sz2.tencent.com"); 118 }
112 qd->servers = g_list_append(qd->servers, "sz3.tencent.com"); 119
113 qd->servers = g_list_append(qd->servers, "sz4.tencent.com"); 120 static void server_list_remove_all(qq_data *qd)
114 qd->servers = g_list_append(qd->servers, "sz5.tencent.com"); 121 {
115 qd->servers = g_list_append(qd->servers, "sz6.tencent.com");
116 qd->servers = g_list_append(qd->servers, "sz7.tencent.com");
117 qd->servers = g_list_append(qd->servers, "sz8.tencent.com");
118 qd->servers = g_list_append(qd->servers, "sz9.tencent.com");
119 }
120
121 static void server_list_remove_all(qq_data *qd) {
122 g_return_if_fail(qd != NULL); 122 g_return_if_fail(qd != NULL);
123 123
124 if (qd->real_hostname) { 124 purple_debug_info("QQ", "free server list\n");
125 purple_debug(PURPLE_DEBUG_INFO, "QQ", "free real_hostname\n");
126 g_free(qd->real_hostname);
127 qd->real_hostname = NULL;
128 }
129
130 if (qd->user_server != NULL) {
131 purple_debug(PURPLE_DEBUG_INFO, "QQ", "free user_server\n");
132 g_free(qd->user_server);
133 qd->user_server = NULL;
134 }
135
136 purple_debug(PURPLE_DEBUG_INFO, "QQ", "free server list\n");
137 g_list_free(qd->servers); 125 g_list_free(qd->servers);
126 qd->curr_server = NULL;
138 } 127 }
139 128
140 static void qq_login(PurpleAccount *account) 129 static void qq_login(PurpleAccount *account)
141 { 130 {
142 PurpleConnection *gc; 131 PurpleConnection *gc;
149 g_return_if_fail(gc != NULL); 138 g_return_if_fail(gc != NULL);
150 139
151 gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_AUTO_RESP; 140 gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_AUTO_RESP;
152 141
153 qd = g_new0(qq_data, 1); 142 qd = g_new0(qq_data, 1);
143 memset(qd, 0, sizeof(qq_data));
154 qd->gc = gc; 144 qd->gc = gc;
155 gc->proto_data = qd; 145 gc->proto_data = qd;
156 146
157 presence = purple_account_get_presence(account); 147 presence = purple_account_get_presence(account);
158 if(purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_INVISIBLE)) { 148 if(purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_INVISIBLE)) {
163 } else { 153 } else {
164 qd->login_mode = QQ_LOGIN_MODE_NORMAL; 154 qd->login_mode = QQ_LOGIN_MODE_NORMAL;
165 } 155 }
166 156
167 server_list_create(account); 157 server_list_create(account);
168 purple_debug(PURPLE_DEBUG_INFO, "QQ", 158 purple_debug_info("QQ", "Server list has %d\n", g_list_length(qd->servers));
169 "Server list has %d\n", g_list_length(qd->servers)); 159
170 160 qd->is_show_notice = purple_account_get_bool(account, "show_notice", TRUE);
171 qq_connect(account); 161 qd->is_show_news = purple_account_get_bool(account, "show_news", TRUE);
162
163 qd->itv_config.resend = purple_account_get_int(account, "resend_interval", 10);
164 if (qd->itv_config.resend <= 0) qd->itv_config.resend = 10;
165
166 qd->itv_config.keep_alive = purple_account_get_int(account, "keep_alive_interval", 60);
167 if (qd->itv_config.keep_alive < 30) qd->itv_config.keep_alive = 30;
168 qd->itv_config.keep_alive /= qd->itv_config.resend;
169 qd->itv_count.keep_alive = qd->itv_config.keep_alive;
170
171 qd->itv_config.update = purple_account_get_int(account, "update_interval", 300);
172 if (qd->itv_config.update > 0) {
173 if (qd->itv_config.update < qd->itv_config.keep_alive) {
174 qd->itv_config.update = qd->itv_config.keep_alive;
175 }
176 qd->itv_config.update /= qd->itv_config.resend;
177 qd->itv_count.update = qd->itv_config.update;
178 } else {
179 qd->itv_config.update = 0;
180 }
181
182 qd->connect_watcher = purple_timeout_add_seconds(0, qq_connect_later, gc);
172 } 183 }
173 184
174 /* clean up the given QQ connection and free all resources */ 185 /* clean up the given QQ connection and free all resources */
175 static void qq_close(PurpleConnection *gc) 186 static void qq_close(PurpleConnection *gc)
176 { 187 {
177 qq_data *qd; 188 qq_data *qd;
178 189
179 g_return_if_fail(gc != NULL && gc->proto_data); 190 g_return_if_fail(gc != NULL && gc->proto_data);
180 qd = gc->proto_data; 191 qd = gc->proto_data;
181 192
193 if (qd->check_watcher > 0) {
194 purple_timeout_remove(qd->check_watcher);
195 qd->check_watcher = 0;
196 }
197
198 if (qd->connect_watcher > 0) {
199 purple_timeout_remove(qd->connect_watcher);
200 qd->connect_watcher = 0;
201 }
202
182 qq_disconnect(gc); 203 qq_disconnect(gc);
183
184 server_list_remove_all(qd); 204 server_list_remove_all(qd);
185 205
186 g_free(qd); 206 g_free(qd);
187
188 gc->proto_data = NULL; 207 gc->proto_data = NULL;
189 } 208 }
190 209
191 /* returns the icon name for a buddy or protocol */ 210 /* returns the icon name for a buddy or protocol */
192 static const gchar *_qq_list_icon(PurpleAccount *a, PurpleBuddy *b) 211 static const gchar *_qq_list_icon(PurpleAccount *a, PurpleBuddy *b)
210 switch(q_bud->status) { 229 switch(q_bud->status) {
211 case QQ_BUDDY_OFFLINE: 230 case QQ_BUDDY_OFFLINE:
212 g_string_append(status, _("Offline")); 231 g_string_append(status, _("Offline"));
213 break; 232 break;
214 case QQ_BUDDY_ONLINE_NORMAL: 233 case QQ_BUDDY_ONLINE_NORMAL:
215 return NULL; 234 g_string_append(status, _("Online"));
216 break; 235 break;
217 /* TODO What does this status mean? Labelling it as offline... */ 236 /* TODO What does this status mean? Labelling it as offline... */
218 case QQ_BUDDY_ONLINE_OFFLINE: 237 case QQ_BUDDY_ONLINE_OFFLINE:
219 g_string_append(status, _("Offline")); 238 g_string_append(status, _("Offline"));
220 break; 239 break;
301 } 320 }
302 if (q_bud->comm_flag & QQ_COMM_FLAG_VIDEO) { 321 if (q_bud->comm_flag & QQ_COMM_FLAG_VIDEO) {
303 g_string_append( str, _(" Video") ); 322 g_string_append( str, _(" Video") );
304 } 323 }
305 324
306 if (q_bud->ext_flag & QQ_EXT_FLAG_SPACE) { 325 if (q_bud->ext_flag & QQ_EXT_FLAG_ZONE) {
307 g_string_append( str, _(" Space") ); 326 g_string_append( str, _(" Zone") );
308 } 327 }
309 purple_notify_user_info_add_pair(user_info, _("Flag"), str->str); 328 purple_notify_user_info_add_pair(user_info, _("Flag"), str->str);
310 329
311 g_string_free(str, TRUE); 330 g_string_free(str, TRUE);
312 331
327 /* we can show tiny icons on the four corners of buddy icon, */ 346 /* we can show tiny icons on the four corners of buddy icon, */
328 static const char *_qq_list_emblem(PurpleBuddy *b) 347 static const char *_qq_list_emblem(PurpleBuddy *b)
329 { 348 {
330 /* each char** are refering to a filename in pixmaps/purple/status/default/ */ 349 /* each char** are refering to a filename in pixmaps/purple/status/default/ */
331 qq_buddy *q_bud; 350 qq_buddy *q_bud;
332 351
333 if (!b || !(q_bud = b->proto_data)) { 352 if (!b || !(q_bud = b->proto_data)) {
334 return NULL; 353 return NULL;
335 } 354 }
336 355
337 if (q_bud->comm_flag & QQ_COMM_FLAG_MOBILE) 356 if (q_bud->comm_flag & QQ_COMM_FLAG_MOBILE)
372 391
373 return types; 392 return types;
374 } 393 }
375 394
376 /* initiate QQ away with proper change_status packet */ 395 /* initiate QQ away with proper change_status packet */
377 static void _qq_set_away(PurpleAccount *account, PurpleStatus *status) 396 static void _qq_change_status(PurpleAccount *account, PurpleStatus *status)
378 { 397 {
379 PurpleConnection *gc = purple_account_get_connection(account); 398 PurpleConnection *gc = purple_account_get_connection(account);
380 399
381 qq_send_packet_change_status(gc); 400 qq_request_change_status(gc, 0);
382 } 401 }
383 402
384 /* IMPORTANT: PurpleConvImFlags -> PurpleMessageFlags */ 403 /* IMPORTANT: PurpleConvImFlags -> PurpleMessageFlags */
385 /* send an instant msg to a buddy */ 404 /* send an instant msg to a buddy */
386 static gint _qq_send_im(PurpleConnection *gc, const gchar *who, const gchar *message, PurpleMessageFlags flags) 405 static gint _qq_send_im(PurpleConnection *gc, const gchar *who, const gchar *message, PurpleMessageFlags flags)
442 461
443 qd = gc->proto_data; 462 qd = gc->proto_data;
444 uid = purple_name_to_uid(who); 463 uid = purple_name_to_uid(who);
445 464
446 if (uid <= 0) { 465 if (uid <= 0) {
447 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Not valid QQid: %s\n", who); 466 purple_debug_error("QQ", "Not valid QQid: %s\n", who);
448 purple_notify_error(gc, NULL, _("Invalid name"), NULL); 467 purple_notify_error(gc, NULL, _("Invalid name"), NULL);
449 return; 468 return;
450 } 469 }
451 470
452 qq_send_packet_get_level(gc, uid); 471 qq_send_packet_get_level(gc, uid);
514 g_string_append_printf(info, _("<b>Current Online</b>: %d<br>\n"), qd->total_online); 533 g_string_append_printf(info, _("<b>Current Online</b>: %d<br>\n"), qd->total_online);
515 g_string_append_printf(info, _("<b>Last Refresh</b>: %s<br>\n"), ctime(&qd->last_get_online)); 534 g_string_append_printf(info, _("<b>Last Refresh</b>: %s<br>\n"), ctime(&qd->last_get_online));
516 535
517 g_string_append(info, "<hr>\n"); 536 g_string_append(info, "<hr>\n");
518 537
519 g_string_append_printf(info, _("<b>Server</b>: %s: %d<br>\n"), qd->server_name, qd->real_port); 538 g_string_append_printf(info, _("<b>Server</b>: %s<br>\n"), qd->curr_server);
520 g_string_append_printf(info, _("<b>Connection Mode</b>: %s<br>\n"), qd->use_tcp ? "TCP" : "UDP"); 539 g_string_append_printf(info, _("<b>Connection Mode</b>: %s<br>\n"), qd->use_tcp ? "TCP" : "UDP");
521 g_string_append_printf(info, _("<b>Real hostname</b>: %s: %d<br>\n"), qd->real_hostname, qd->real_port);
522 g_string_append_printf(info, _("<b>My Public IP</b>: %s<br>\n"), inet_ntoa(qd->my_ip)); 540 g_string_append_printf(info, _("<b>My Public IP</b>: %s<br>\n"), inet_ntoa(qd->my_ip));
523 541
524 g_string_append(info, "<hr>\n"); 542 g_string_append(info, "<hr>\n");
525 g_string_append(info, "<i>Information below may not be accurate</i><br>\n"); 543 g_string_append(info, "<i>Information below may not be accurate</i><br>\n");
526 544
631 { 649 {
632 GList *m; 650 GList *m;
633 PurpleMenuAction *act; 651 PurpleMenuAction *act;
634 652
635 m = NULL; 653 m = NULL;
636 act = purple_menu_action_new(_("Leave this QQ Qun"), PURPLE_CALLBACK(_qq_menu_unsubscribe_group), NULL, NULL); 654 act = purple_menu_action_new(_("Leave the QQ Qun"), PURPLE_CALLBACK(_qq_menu_unsubscribe_group), NULL, NULL);
637 m = g_list_append(m, act); 655 m = g_list_append(m, act);
638 656
639 /* TODO: enable this 657 /* TODO: enable this
640 act = purple_menu_action_new(_("Show Details"), PURPLE_CALLBACK(_qq_menu_manage_group), NULL, NULL); 658 act = purple_menu_action_new(_("Show Details"), PURPLE_CALLBACK(_qq_menu_manage_group), NULL, NULL);
641 m = g_list_append(m, act); 659 m = g_list_append(m, act);
706 qq_close, /* close */ 724 qq_close, /* close */
707 _qq_send_im, /* send_im */ 725 _qq_send_im, /* send_im */
708 NULL, /* set_info */ 726 NULL, /* set_info */
709 NULL, /* send_typing */ 727 NULL, /* send_typing */
710 _qq_get_info, /* get_info */ 728 _qq_get_info, /* get_info */
711 _qq_set_away, /* set_away */ 729 _qq_change_status, /* change status */
712 NULL, /* set_idle */ 730 NULL, /* set_idle */
713 NULL, /* change_passwd */ 731 NULL, /* change_passwd */
714 qq_add_buddy, /* add_buddy */ 732 qq_add_buddy, /* add_buddy */
715 NULL, /* add_buddies */ 733 NULL, /* add_buddies */
716 qq_remove_buddy, /* remove_buddy */ 734 qq_remove_buddy, /* remove_buddy */
798 816
799 817
800 static void init_plugin(PurplePlugin *plugin) 818 static void init_plugin(PurplePlugin *plugin)
801 { 819 {
802 PurpleAccountOption *option; 820 PurpleAccountOption *option;
803 821 PurpleKeyValuePair *kvp;
822 GList *list = NULL;
823 GList *kvlist = NULL;
824 GList *entry;
825
826 list = server_list_build('A');
827
828 purple_prefs_add_string_list("/plugins/prpl/qq/serverlist", list);
829 list = purple_prefs_get_string_list("/plugins/prpl/qq/serverlist");
830
831 kvlist = NULL;
832 kvp = g_new0(PurpleKeyValuePair, 1);
833 kvp->key = g_strdup(_("Auto"));
834 kvp->value = g_strdup("auto");
835 kvlist = g_list_append(kvlist, kvp);
836
837 entry = list;
838 while(entry) {
839 if (entry->data != NULL && strlen(entry->data) > 0) {
840 kvp = g_new0(PurpleKeyValuePair, 1);
841 kvp->key = g_strdup(entry->data);
842 kvp->value = g_strdup(entry->data);
843 kvlist = g_list_append(kvlist, kvp);
844 }
845 entry = entry->next;
846 }
847
848 /*
804 option = purple_account_option_string_new(_("Server"), "server", NULL); 849 option = purple_account_option_string_new(_("Server"), "server", NULL);
805 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); 850 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
806 851
807 option = purple_account_option_int_new(_("Port"), "port", 0); 852 option = purple_account_option_int_new(_("Port"), "port", 0);
808 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); 853 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
809 854 */
810 option = purple_account_option_bool_new(_("Connect using TCP"), "use_tcp", TRUE); 855 option = purple_account_option_list_new(_("Server"), "server", kvlist);
811 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); 856 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
812 857
813 option = purple_account_option_int_new(_("resend interval(s)"), "resend_interval", 10); 858 option = purple_account_option_bool_new(_("Show server notice"), "show_notice", TRUE);
859 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
860
861 option = purple_account_option_bool_new(_("Show server news"), "show_news", TRUE);
862 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
863
864 option = purple_account_option_int_new(_("Resend interval(s)"), "resend_interval", 10);
814 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); 865 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
815 866
816 option = purple_account_option_int_new(_("Keep alive interval(s)"), "keep_alive_interval", 60); 867 option = purple_account_option_int_new(_("Keep alive interval(s)"), "keep_alive_interval", 60);
817 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); 868 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
818 869
821 872
822 purple_prefs_add_none("/plugins/prpl/qq"); 873 purple_prefs_add_none("/plugins/prpl/qq");
823 purple_prefs_add_bool("/plugins/prpl/qq/show_status_by_icon", TRUE); 874 purple_prefs_add_bool("/plugins/prpl/qq/show_status_by_icon", TRUE);
824 purple_prefs_add_bool("/plugins/prpl/qq/show_fake_video", FALSE); 875 purple_prefs_add_bool("/plugins/prpl/qq/show_fake_video", FALSE);
825 purple_prefs_add_bool("/plugins/prpl/qq/prompt_group_msg_on_recv", TRUE); 876 purple_prefs_add_bool("/plugins/prpl/qq/prompt_group_msg_on_recv", TRUE);
877
826 } 878 }
827 879
828 PURPLE_INIT_PLUGIN(qq, init_plugin, info); 880 PURPLE_INIT_PLUGIN(qq, init_plugin, info);