comparison src/protocols/qq/login_logout.c @ 14021:ef8490f9e823

[gaim-migrate @ 16618] Replaced all C++-style comments with C-style ones. Cleaned up some comments and implemented a more consistent formatting scheme. committer: Tailor Script <tailor@pidgin.im>
author Mark Huetsch <markhuetsch>
date Wed, 02 Aug 2006 15:35:36 +0000
parents e9fe337fa9aa
children
comparison
equal deleted inserted replaced
14020:13e7ba964993 14021:ef8490f9e823
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */ 21 */
22 22
23 #include "debug.h" // gaim_debug 23 #include "debug.h"
24 #include "internal.h" // memcpy, _("get_text") 24 #include "internal.h"
25 #include "server.h" // serv_finish_login 25 #include "server.h"
26 26
27 #include "utils.h" // gen_ip_str 27 #include "buddy_info.h"
28 #include "packet_parse.h" // create_packet 28 #include "buddy_list.h"
29 #include "buddy_info.h" // qq_send_packet_get_info 29 #include "buddy_status.h"
30 #include "buddy_list.h" // qq_send_packet_get_buddies_list 30 #include "char_conv.h"
31 #include "buddy_status.h" // QQ_SELF_STATUS_AVAILABLE 31 #include "crypt.h"
32 #include "char_conv.h" // qq_to_utf8 32 #include "group.h"
33 #include "crypt.h" // qq_crypt 33 #include "header_info.h"
34 #include "group.h" // qq_group_init
35 #include "header_info.h" // QQ_CMD_LOGIN
36 #include "login_logout.h" 34 #include "login_logout.h"
37 #include "qq_proxy.h" // qq_connect 35 #include "packet_parse.h"
38 #include "send_core.h" // qq_send_cmd 36 #include "qq.h"
39 #include "qq.h" // qq_data 37 #include "qq_proxy.h"
38 #include "send_core.h"
39 #include "utils.h"
40 40
41 #define QQ_LOGIN_DATA_LENGTH 416 41 #define QQ_LOGIN_DATA_LENGTH 416
42 #define QQ_LOGIN_REPLY_OK_PACKET_LEN 139 42 #define QQ_LOGIN_REPLY_OK_PACKET_LEN 139
43 #define QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN 11 43 #define QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN 11
44 44
45 #define QQ_REQUEST_LOGIN_TOKEN_REPLY_OK 0x00 45 #define QQ_REQUEST_LOGIN_TOKEN_REPLY_OK 0x00
46 46
47 #define QQ_LOGIN_REPLY_OK 0x00 47 #define QQ_LOGIN_REPLY_OK 0x00
48 #define QQ_LOGIN_REPLY_REDIRECT 0x01 48 #define QQ_LOGIN_REPLY_REDIRECT 0x01
49 #define QQ_LOGIN_REPLY_PWD_ERROR 0x05 49 #define QQ_LOGIN_REPLY_PWD_ERROR 0x05
50 #define QQ_LOGIN_REPLY_MISC_ERROR 0xff // defined by myself 50 #define QQ_LOGIN_REPLY_MISC_ERROR 0xff /* defined by myself */
51 51
52 // for QQ 2003iii 0117, fixed value 52 /* for QQ 2003iii 0117, fixed value */
53 /* static const guint8 login_23_51[29] = { 53 /* static const guint8 login_23_51[29] = {
54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55 0x00, 0x00, 0x00, 0x00, 0xbf, 0x14, 0x11, 0x20, 55 0x00, 0x00, 0x00, 0x00, 0xbf, 0x14, 0x11, 0x20,
56 0x03, 0x9d, 0xb2, 0xe6, 0xb3, 0x11, 0xb7, 0x13, 56 0x03, 0x9d, 0xb2, 0xe6, 0xb3, 0x11, 0xb7, 0x13,
57 0x95, 0x67, 0xda, 0x2c, 0x01 57 0x95, 0x67, 0xda, 0x2c, 0x01
58 }; */ 58 }; */
59 59
60 // for QQ 2003iii 0304, fixed value 60 /* for QQ 2003iii 0304, fixed value */
61 /* 61 /*
62 static const guint8 login_23_51[29] = { 62 static const guint8 login_23_51[29] = {
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 0x00, 0x00, 0x00, 0x00, 0x9a, 0x93, 0xfe, 0x85, 64 0x00, 0x00, 0x00, 0x00, 0x9a, 0x93, 0xfe, 0x85,
65 0xd3, 0xd9, 0x2a, 0x41, 0xc8, 0x0d, 0xff, 0xb6, 65 0xd3, 0xd9, 0x2a, 0x41, 0xc8, 0x0d, 0xff, 0xb6,
66 0x40, 0xb8, 0xac, 0x32, 0x01 66 0x40, 0xb8, 0xac, 0x32, 0x01
67 }; 67 };
68 */ 68 */
69 69
70 //for QQ 2005? copy from lumaqq 70 /* for QQ 2005? copy from lumaqq */
71 static const gint8 login_23_51[29] = { 71 static const gint8 login_23_51[29] = {
72 0, 0, 0, 72 0, 0, 0,
73 0, 0, 0, 0, 0, 0, 0, 0, 0, -122, 73 0, 0, 0, 0, 0, 0, 0, 0, 0, -122,
74 -52, 76, 53, 44, -45, 115, 108, 20, -10, -10, 74 -52, 76, 53, 44, -45, 115, 108, 20, -10, -10,
75 -81, -61, -6, 51, -92, 1 75 -81, -61, -6, 51, -92, 1
92 0, 0, 0, 1, -18, 3, 0, 0, 0, 0, 92 0, 0, 0, 1, -18, 3, 0, 0, 0, 0,
93 0, 0, 1, -17, 3, 0, 0, 0, 0, 0, 93 0, 0, 1, -17, 3, 0, 0, 0, 0, 0,
94 0, 1, -21, 3, 0, 0, 0, 0, 0 94 0, 1, -21, 3, 0, 0, 0, 0, 0
95 }; 95 };
96 96
97 // fixed value, not affected by version, or mac address 97 /* fixed value, not affected by version, or mac address */
98 /* 98 /*
99 static const guint8 login_53_68[16] = { 99 static const guint8 login_53_68[16] = {
100 0x82, 0x2a, 0x91, 0xfd, 0xa5, 0xca, 0x67, 0x4c, 100 0x82, 0x2a, 0x91, 0xfd, 0xa5, 0xca, 0x67, 0x4c,
101 0xac, 0x81, 0x1f, 0x6f, 0x52, 0x05, 0xa7, 0xbf 101 0xac, 0x81, 0x1f, 0x6f, 0x52, 0x05, 0xa7, 0xbf
102 }; 102 };
108 108
109 struct _qq_login_reply_ok { 109 struct _qq_login_reply_ok {
110 guint8 result; 110 guint8 result;
111 guint8 *session_key; 111 guint8 *session_key;
112 guint32 uid; 112 guint32 uid;
113 guint8 client_ip[4]; // those detected by server 113 guint8 client_ip[4]; /* those detected by server */
114 guint16 client_port; 114 guint16 client_port;
115 guint8 server_ip[4]; 115 guint8 server_ip[4];
116 guint16 server_port; 116 guint16 server_port;
117 time_t login_time; 117 time_t login_time;
118 guint8 unknown1[26]; 118 guint8 unknown1[26];
119 guint8 unknown_server1_ip[4]; 119 guint8 unknown_server1_ip[4];
120 guint16 unknown_server1_port; 120 guint16 unknown_server1_port;
121 guint8 unknown_server2_ip[4]; 121 guint8 unknown_server2_ip[4];
122 guint16 unknown_server2_port; 122 guint16 unknown_server2_port;
123 guint16 unknown2; // 0x0001 123 guint16 unknown2; /* 0x0001 */
124 guint16 unknown3; // 0x0000 124 guint16 unknown3; /* 0x0000 */
125 guint8 unknown4[32]; 125 guint8 unknown4[32];
126 guint8 unknown5[12]; 126 guint8 unknown5[12];
127 guint8 last_client_ip[4]; 127 guint8 last_client_ip[4];
128 time_t last_login_time; 128 time_t last_login_time;
129 guint8 unknown6[8]; 129 guint8 unknown6[8];
134 guint32 uid; 134 guint32 uid;
135 guint8 new_server_ip[4]; 135 guint8 new_server_ip[4];
136 guint16 new_server_port; 136 guint16 new_server_port;
137 }; 137 };
138 138
139 extern gint // defined in send_core.c 139 extern gint /* defined in send_core.c */
140 _create_packet_head_seq(guint8 * buf, 140 _create_packet_head_seq(guint8 *buf,
141 guint8 ** cursor, GaimConnection * gc, guint16 cmd, gboolean is_auto_seq, guint16 * seq); 141 guint8 **cursor, GaimConnection *gc, guint16 cmd, gboolean is_auto_seq, guint16 *seq);
142 extern gint // defined in send_core.c 142 extern gint /* defined in send_core.c */
143 _qq_send_packet(GaimConnection * gc, guint8 * buf, gint len, guint16 cmd); 143 _qq_send_packet(GaimConnection *gc, guint8 *buf, gint len, guint16 cmd);
144 144
145 /*****************************************************************************/ 145 /* It is fixed to 16 bytes 0x01 for QQ2003,
146 // It is fixed to 16 bytes 0x01 for QQ2003, 146 * Any value works (or a random 16 bytes string) */
147 // Any value works (or a random 16 bytes string)
148 static guint8 *_gen_login_key(void) 147 static guint8 *_gen_login_key(void)
149 { 148 {
150 return (guint8 *) g_strnfill(QQ_KEY_LENGTH, 0x01); 149 return (guint8 *) g_strnfill(QQ_KEY_LENGTH, 0x01);
151 } 150 }
152 151
153 // process login reply which says OK 152 /* process login reply which says OK */
154 static gint _qq_process_login_ok(GaimConnection * gc, guint8 * data, gint len) 153 static gint _qq_process_login_ok(GaimConnection *gc, guint8 *data, gint len)
155 { 154 {
156 gint bytes; 155 gint bytes;
157 guint8 *cursor; 156 guint8 *cursor;
158 qq_data *qd; 157 qq_data *qd;
159 qq_login_reply_ok_packet lrop; 158 qq_login_reply_ok_packet lrop;
162 161
163 qd = (qq_data *) gc->proto_data; 162 qd = (qq_data *) gc->proto_data;
164 cursor = data; 163 cursor = data;
165 bytes = 0; 164 bytes = 0;
166 165
167 // 000-000: reply code 166 /* 000-000: reply code */
168 bytes += read_packet_b(data, &cursor, len, &lrop.result); 167 bytes += read_packet_b(data, &cursor, len, &lrop.result);
169 // 001-016: session key 168 /* 001-016: session key */
170 lrop.session_key = g_memdup(cursor, QQ_KEY_LENGTH); 169 lrop.session_key = g_memdup(cursor, QQ_KEY_LENGTH);
171 cursor += QQ_KEY_LENGTH; 170 cursor += QQ_KEY_LENGTH;
172 bytes += QQ_KEY_LENGTH; 171 bytes += QQ_KEY_LENGTH;
173 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Get session_key done\n"); 172 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Get session_key done\n");
174 // 017-020: login uid 173 /* 017-020: login uid */
175 bytes += read_packet_dw(data, &cursor, len, &lrop.uid); 174 bytes += read_packet_dw(data, &cursor, len, &lrop.uid);
176 // 021-024: server detected user public IP 175 /* 021-024: server detected user public IP */
177 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.client_ip, 4); 176 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.client_ip, 4);
178 // 025-026: server detected user port 177 /* 025-026: server detected user port */
179 bytes += read_packet_w(data, &cursor, len, &lrop.client_port); 178 bytes += read_packet_w(data, &cursor, len, &lrop.client_port);
180 // 027-030: server detected itself ip 127.0.0.1 ? 179 /* 027-030: server detected itself ip 127.0.0.1 ? */
181 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.server_ip, 4); 180 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.server_ip, 4);
182 // 031-032: server listening port 181 /* 031-032: server listening port */
183 bytes += read_packet_w(data, &cursor, len, &lrop.server_port); 182 bytes += read_packet_w(data, &cursor, len, &lrop.server_port);
184 // 033-036: login time for current session 183 /* 033-036: login time for current session */
185 bytes += read_packet_dw(data, &cursor, len, (guint32 *) & lrop.login_time); 184 bytes += read_packet_dw(data, &cursor, len, (guint32 *) & lrop.login_time);
186 // 037-062: 26 bytes, unknown 185 /* 037-062: 26 bytes, unknown */
187 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.unknown1, 26); 186 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.unknown1, 26);
188 // 063-066: unknown server1 ip address 187 /* 063-066: unknown server1 ip address */
189 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.unknown_server1_ip, 4); 188 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.unknown_server1_ip, 4);
190 // 067-068: unknown server1 port 189 /* 067-068: unknown server1 port */
191 bytes += read_packet_w(data, &cursor, len, &lrop.unknown_server1_port); 190 bytes += read_packet_w(data, &cursor, len, &lrop.unknown_server1_port);
192 // 069-072: unknown server2 ip address 191 /* 069-072: unknown server2 ip address */
193 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.unknown_server2_ip, 4); 192 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.unknown_server2_ip, 4);
194 // 073-074: unknown server2 port 193 /* 073-074: unknown server2 port */
195 bytes += read_packet_w(data, &cursor, len, &lrop.unknown_server2_port); 194 bytes += read_packet_w(data, &cursor, len, &lrop.unknown_server2_port);
196 // 075-076: 2 bytes unknown 195 /* 075-076: 2 bytes unknown */
197 bytes += read_packet_w(data, &cursor, len, &lrop.unknown2); 196 bytes += read_packet_w(data, &cursor, len, &lrop.unknown2);
198 // 077-078: 2 bytes unknown 197 /* 077-078: 2 bytes unknown */
199 bytes += read_packet_w(data, &cursor, len, &lrop.unknown3); 198 bytes += read_packet_w(data, &cursor, len, &lrop.unknown3);
200 // 079-110: 32 bytes unknown 199 /* 079-110: 32 bytes unknown */
201 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.unknown4, 32); 200 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.unknown4, 32);
202 // 111-122: 12 bytes unknown 201 /* 111-122: 12 bytes unknown */
203 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.unknown5, 12); 202 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.unknown5, 12);
204 // 123-126: login IP of last session 203 /* 123-126: login IP of last session */
205 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.last_client_ip, 4); 204 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.last_client_ip, 4);
206 // 127-130: login time of last session 205 /* 127-130: login time of last session */
207 bytes += read_packet_dw(data, &cursor, len, (guint32 *) & lrop.last_login_time); 206 bytes += read_packet_dw(data, &cursor, len, (guint32 *) & lrop.last_login_time);
208 // 131-138: 8 bytes unknown 207 /* 131-138: 8 bytes unknown */
209 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.unknown6, 8); 208 bytes += read_packet_data(data, &cursor, len, (guint8 *) & lrop.unknown6, 8);
210 209
211 if (bytes != QQ_LOGIN_REPLY_OK_PACKET_LEN) { // fail parsing login info 210 if (bytes != QQ_LOGIN_REPLY_OK_PACKET_LEN) { /* fail parsing login info */
212 gaim_debug(GAIM_DEBUG_WARNING, "QQ", 211 gaim_debug(GAIM_DEBUG_WARNING, "QQ",
213 "Fail parsing login info, expect %d bytes, read %d bytes\n", 212 "Fail parsing login info, expect %d bytes, read %d bytes\n",
214 QQ_LOGIN_REPLY_OK_PACKET_LEN, bytes); 213 QQ_LOGIN_REPLY_OK_PACKET_LEN, bytes);
215 } // but we still go on as login OK 214 } /* but we still go on as login OK */
216 215
217 qd->session_key = g_memdup(lrop.session_key, QQ_KEY_LENGTH); 216 qd->session_key = g_memdup(lrop.session_key, QQ_KEY_LENGTH);
218 qd->my_ip = gen_ip_str(lrop.client_ip); 217 qd->my_ip = gen_ip_str(lrop.client_ip);
219 qd->my_port = lrop.client_port; 218 qd->my_port = lrop.client_port;
220 qd->login_time = lrop.login_time; 219 qd->login_time = lrop.login_time;
222 qd->last_login_ip = gen_ip_str(lrop.last_client_ip); 221 qd->last_login_ip = gen_ip_str(lrop.last_client_ip);
223 222
224 g_free(lrop.session_key); 223 g_free(lrop.session_key);
225 224
226 gaim_connection_set_state(gc, GAIM_CONNECTED); 225 gaim_connection_set_state(gc, GAIM_CONNECTED);
227 qd->logged_in = TRUE; // must be defined after sev_finish_login 226 qd->logged_in = TRUE; /* must be defined after sev_finish_login */
228 227
229 // now initiate QQ Qun, do it first as it may take longer to finish 228 /* now initiate QQ Qun, do it first as it may take longer to finish */
230 qq_group_init(gc); 229 qq_group_init(gc);
231 230
232 // Now goes on updating my icon/nickname, not showing info_window 231 /* Now goes on updating my icon/nickname, not showing info_window */
233 qq_send_packet_get_info(gc, qd->uid, FALSE); 232 qq_send_packet_get_info(gc, qd->uid, FALSE);
234 // change my status manually, even server may broadcast my online 233 /* change my status manually, even server may broadcast my online */
235 qd->status = (qd->login_mode == QQ_LOGIN_MODE_HIDDEN) ? QQ_SELF_STATUS_INVISIBLE : QQ_SELF_STATUS_AVAILABLE; 234 qd->status = (qd->login_mode == QQ_LOGIN_MODE_HIDDEN) ? QQ_SELF_STATUS_INVISIBLE : QQ_SELF_STATUS_AVAILABLE;
236 qq_send_packet_change_status(gc); 235 qq_send_packet_change_status(gc);
237 // now refresh buddy list 236 /* now refresh buddy list */
238 237
239 //changed by gfhuang, using With Qun version, error, not working still 238 /* changed by gfhuang, using With Qun version, error, not working still */
240 qq_send_packet_get_buddies_list(gc, QQ_FRIENDS_LIST_POSITION_START); 239 qq_send_packet_get_buddies_list(gc, QQ_FRIENDS_LIST_POSITION_START);
241 //qq_send_packet_get_all_list_with_group(gc, QQ_FRIENDS_LIST_POSITION_START); 240 /* qq_send_packet_get_all_list_with_group(gc, QQ_FRIENDS_LIST_POSITION_START); */
242 241
243 return QQ_LOGIN_REPLY_OK; 242 return QQ_LOGIN_REPLY_OK;
244 } 243 }
245 244
246 // process login reply packet which includes redirected new server address 245 /* process login reply packet which includes redirected new server address */
247 static gint _qq_process_login_redirect(GaimConnection * gc, guint8 * data, gint len) 246 static gint _qq_process_login_redirect(GaimConnection *gc, guint8 *data, gint len)
248 { 247 {
249 gint bytes, ret; 248 gint bytes, ret;
250 guint8 *cursor; 249 guint8 *cursor;
251 gchar *new_server_str; 250 gchar *new_server_str;
252 qq_data *qd; 251 qq_data *qd;
255 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_MISC_ERROR); 254 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_MISC_ERROR);
256 255
257 qd = (qq_data *) gc->proto_data; 256 qd = (qq_data *) gc->proto_data;
258 cursor = data; 257 cursor = data;
259 bytes = 0; 258 bytes = 0;
260 // 000-000: reply code 259 /* 000-000: reply code */
261 bytes += read_packet_b(data, &cursor, len, &lrrp.result); 260 bytes += read_packet_b(data, &cursor, len, &lrrp.result);
262 // 001-004: login uid 261 /* 001-004: login uid */
263 bytes += read_packet_dw(data, &cursor, len, &lrrp.uid); 262 bytes += read_packet_dw(data, &cursor, len, &lrrp.uid);
264 // 005-008: redirected new server IP 263 /* 005-008: redirected new server IP */
265 bytes += read_packet_data(data, &cursor, len, lrrp.new_server_ip, 4); 264 bytes += read_packet_data(data, &cursor, len, lrrp.new_server_ip, 4);
266 // 009-010: redirected new server port 265 /* 009-010: redirected new server port */
267 bytes += read_packet_w(data, &cursor, len, &lrrp.new_server_port); 266 bytes += read_packet_w(data, &cursor, len, &lrrp.new_server_port);
268 267
269 if (bytes != QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN) { 268 if (bytes != QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN) {
270 gaim_debug(GAIM_DEBUG_ERROR, "QQ", 269 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
271 "Fail parsing login redirect packet, expect %d bytes, read %d bytes\n", 270 "Fail parsing login redirect packet, expect %d bytes, read %d bytes\n",
272 QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN, bytes); 271 QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN, bytes);
273 ret = QQ_LOGIN_REPLY_MISC_ERROR; 272 ret = QQ_LOGIN_REPLY_MISC_ERROR;
274 } else { // start new connection 273 } else { /* start new connection */
275 new_server_str = gen_ip_str(lrrp.new_server_ip); 274 new_server_str = gen_ip_str(lrrp.new_server_ip);
276 gaim_debug(GAIM_DEBUG_WARNING, "QQ", 275 gaim_debug(GAIM_DEBUG_WARNING, "QQ",
277 "Redirected to new server: %s:%d\n", new_server_str, lrrp.new_server_port); 276 "Redirected to new server: %s:%d\n", new_server_str, lrrp.new_server_port);
278 qq_connect(gc->account, new_server_str, lrrp.new_server_port, qd->use_tcp, TRUE); 277 qq_connect(gc->account, new_server_str, lrrp.new_server_port, qd->use_tcp, TRUE);
279 g_free(new_server_str); 278 g_free(new_server_str);
281 } 280 }
282 281
283 return ret; 282 return ret;
284 } 283 }
285 284
286 // process login reply which says wrong password 285 /* process login reply which says wrong password */
287 static gint _qq_process_login_wrong_pwd(GaimConnection * gc, guint8 * data, gint len) 286 static gint _qq_process_login_wrong_pwd(GaimConnection * gc, guint8 * data, gint len)
288 { 287 {
289 gchar *server_reply, *server_reply_utf8; 288 gchar *server_reply, *server_reply_utf8;
290 server_reply = g_new0(gchar, len); 289 server_reply = g_new0(gchar, len);
291 g_memmove(server_reply, data + 1, len - 1); 290 g_memmove(server_reply, data + 1, len - 1);
295 g_free(server_reply_utf8); 294 g_free(server_reply_utf8);
296 295
297 return QQ_LOGIN_REPLY_PWD_ERROR; 296 return QQ_LOGIN_REPLY_PWD_ERROR;
298 } 297 }
299 298
300 // request before login 299 /* request before login */
301 void qq_send_packet_request_login_token(GaimConnection *gc) 300 void qq_send_packet_request_login_token(GaimConnection *gc)
302 { 301 {
303 qq_data *qd; 302 qq_data *qd;
304 guint8 *buf, *cursor; 303 guint8 *buf, *cursor;
305 guint16 seq_ret; 304 guint16 seq_ret;
315 bytes += _create_packet_head_seq(buf, &cursor, gc, QQ_CMD_REQUEST_LOGIN_TOKEN, TRUE, &seq_ret); 314 bytes += _create_packet_head_seq(buf, &cursor, gc, QQ_CMD_REQUEST_LOGIN_TOKEN, TRUE, &seq_ret);
316 bytes += create_packet_dw(buf, &cursor, qd->uid); 315 bytes += create_packet_dw(buf, &cursor, qd->uid);
317 bytes += create_packet_b(buf, &cursor, 0); 316 bytes += create_packet_b(buf, &cursor, 0);
318 bytes += create_packet_b(buf, &cursor, QQ_PACKET_TAIL); 317 bytes += create_packet_b(buf, &cursor, QQ_PACKET_TAIL);
319 318
320 if (bytes == (cursor - buf)) // packet creation OK 319 if (bytes == (cursor - buf)) /* packet creation OK */
321 _qq_send_packet(gc, buf, bytes, QQ_CMD_REQUEST_LOGIN_TOKEN); 320 _qq_send_packet(gc, buf, bytes, QQ_CMD_REQUEST_LOGIN_TOKEN);
322 else 321 else
323 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Fail create request login token packet\n"); 322 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Fail create request login token packet\n");
324 } 323 }
325 324
326 // TODO: The login packet and its response have changed by QQ2006 Beta2. In that version, 325 /* TODO: The login packet and its response have changed by QQ2006 Beta2. In that version,
327 // the login OK response packet does not appear to be decryptable with qd->pwkey or qd->inikey. 326 * the login OK response packet does not appear to be decryptable with qd->pwkey or qd->inikey.
328 // Fortunately, this older system still works. 327 * Fortunately, this older system still works. */
329 328
330 // send login packet to QQ server 329 /* send login packet to QQ server */
331 static void qq_send_packet_login(GaimConnection * gc, guint8 token_length, guint8 *token) 330 static void qq_send_packet_login(GaimConnection *gc, guint8 token_length, guint8 *token)
332 { 331 {
333 qq_data *qd; 332 qq_data *qd;
334 guint8 *buf, *cursor, *raw_data, *encrypted_data; 333 guint8 *buf, *cursor, *raw_data, *encrypted_data;
335 guint16 seq_ret; 334 guint16 seq_ret;
336 gint encrypted_len, bytes; 335 gint encrypted_len, bytes;
339 g_return_if_fail(gc != NULL && gc->proto_data != NULL); 338 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
340 339
341 qd = (qq_data *) gc->proto_data; 340 qd = (qq_data *) gc->proto_data;
342 buf = g_newa(guint8, MAX_PACKET_SIZE); 341 buf = g_newa(guint8, MAX_PACKET_SIZE);
343 raw_data = g_newa(guint8, QQ_LOGIN_DATA_LENGTH); 342 raw_data = g_newa(guint8, QQ_LOGIN_DATA_LENGTH);
344 encrypted_data = g_newa(guint8, QQ_LOGIN_DATA_LENGTH + 16); // 16 bytes more 343 encrypted_data = g_newa(guint8, QQ_LOGIN_DATA_LENGTH + 16); /* 16 bytes more */
345 qd->inikey = _gen_login_key(); 344 qd->inikey = _gen_login_key();
346 345
347 // now generate the encrypted data 346 /* now generate the encrypted data
348 // 000-015 use pwkey as key to encrypt empty string 347 * 000-015 use pwkey as key to encrypt empty string */
349 qq_crypt(ENCRYPT, (guint8 *) "", 0, qd->pwkey, raw_data, &encrypted_len); 348 qq_crypt(ENCRYPT, (guint8 *) "", 0, qd->pwkey, raw_data, &encrypted_len);
350 // 016-016 349 /* 016-016 */
351 raw_data[16] = 0x00; 350 raw_data[16] = 0x00;
352 // 017-020, used to be IP, now zero 351 /* 017-020, used to be IP, now zero */
353 *((guint32 *) (raw_data + 17)) = 0x00000000; 352 *((guint32 *) (raw_data + 17)) = 0x00000000;
354 // 021-022, used to be port, now zero 353 /* 021-022, used to be port, now zero */
355 *((guint16 *) (raw_data + 21)) = 0x0000; 354 *((guint16 *) (raw_data + 21)) = 0x0000;
356 // 023-051, fixed value, unknown 355 /* 023-051, fixed value, unknown */
357 g_memmove(raw_data + 23, login_23_51, 29); 356 g_memmove(raw_data + 23, login_23_51, 29);
358 // 052-052, login mode 357 /* 052-052, login mode */
359 raw_data[52] = qd->login_mode; 358 raw_data[52] = qd->login_mode;
360 // 053-068, fixed value, maybe related to per machine 359 /* 053-068, fixed value, maybe related to per machine */
361 g_memmove(raw_data + 53, login_53_68, 16); 360 g_memmove(raw_data + 53, login_53_68, 16);
362 361
363 // 069, login token length 362 /* 069, login token length */
364 raw_data[69] = token_length; 363 raw_data[69] = token_length;
365 pos = 70; 364 pos = 70;
366 // 070-093, login token //normally 24 bytes 365 /* 070-093, login token, normally 24 bytes */
367 g_memmove(raw_data + pos, token, token_length); 366 g_memmove(raw_data + pos, token, token_length);
368 pos += token_length; 367 pos += token_length;
369 // 100 bytes unknown 368 /* 100 bytes unknown */
370 g_memmove(raw_data + pos, login_100_bytes, 100); 369 g_memmove(raw_data + pos, login_100_bytes, 100);
371 pos += 100; 370 pos += 100;
372 // all zero left 371 /* all zero left */
373 memset(raw_data+pos, 0, QQ_LOGIN_DATA_LENGTH - pos); 372 memset(raw_data+pos, 0, QQ_LOGIN_DATA_LENGTH - pos);
374 373
375 qq_crypt(ENCRYPT, raw_data, QQ_LOGIN_DATA_LENGTH, qd->inikey, encrypted_data, &encrypted_len); 374 qq_crypt(ENCRYPT, raw_data, QQ_LOGIN_DATA_LENGTH, qd->inikey, encrypted_data, &encrypted_len);
376 375
377 cursor = buf; 376 cursor = buf;
380 bytes += create_packet_dw(buf, &cursor, qd->uid); 379 bytes += create_packet_dw(buf, &cursor, qd->uid);
381 bytes += create_packet_data(buf, &cursor, qd->inikey, QQ_KEY_LENGTH); 380 bytes += create_packet_data(buf, &cursor, qd->inikey, QQ_KEY_LENGTH);
382 bytes += create_packet_data(buf, &cursor, encrypted_data, encrypted_len); 381 bytes += create_packet_data(buf, &cursor, encrypted_data, encrypted_len);
383 bytes += create_packet_b(buf, &cursor, QQ_PACKET_TAIL); 382 bytes += create_packet_b(buf, &cursor, QQ_PACKET_TAIL);
384 383
385 if (bytes == (cursor - buf)) // packet creation OK 384 if (bytes == (cursor - buf)) /* packet creation OK */
386 _qq_send_packet(gc, buf, bytes, QQ_CMD_LOGIN); 385 _qq_send_packet(gc, buf, bytes, QQ_CMD_LOGIN);
387 else 386 else
388 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Fail create login packet\n"); 387 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Fail create login packet\n");
389 } 388 }
390 389
391 void qq_process_request_login_token_reply(guint8 * buf, gint buf_len, GaimConnection * gc) 390 void qq_process_request_login_token_reply(guint8 *buf, gint buf_len, GaimConnection *gc)
392 { 391 {
393 qq_data *qd; 392 qq_data *qd;
394 393
395 g_return_if_fail(gc != NULL && gc->proto_data != NULL); 394 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
396 g_return_if_fail(buf != NULL && buf_len != 0); 395 g_return_if_fail(buf != NULL && buf_len != 0);
415 try_dump_as_gbk(buf, buf_len); 414 try_dump_as_gbk(buf, buf_len);
416 gaim_connection_error(gc, _("Request login token error!")); 415 gaim_connection_error(gc, _("Request login token error!"));
417 } 416 }
418 } 417 }
419 418
420 // send logout packets to QQ server 419 /* send logout packets to QQ server */
421 void qq_send_packet_logout(GaimConnection * gc) 420 void qq_send_packet_logout(GaimConnection *gc)
422 { 421 {
423 gint i; 422 gint i;
424 qq_data *qd; 423 qq_data *qd;
425 424
426 g_return_if_fail(gc != NULL && gc->proto_data != NULL); 425 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
427 426
428 qd = (qq_data *) gc->proto_data; 427 qd = (qq_data *) gc->proto_data;
429 for (i = 0; i < 4; i++) 428 for (i = 0; i < 4; i++)
430 qq_send_cmd(gc, QQ_CMD_LOGOUT, FALSE, 0xffff, FALSE, qd->pwkey, QQ_KEY_LENGTH); 429 qq_send_cmd(gc, QQ_CMD_LOGOUT, FALSE, 0xffff, FALSE, qd->pwkey, QQ_KEY_LENGTH);
431 430
432 qd->logged_in = FALSE; // update login status AFTER sending logout packets 431 qd->logged_in = FALSE; /* update login status AFTER sending logout packets */
433 } // qq_send_packet_logout 432 }
434 433
435 // process the login reply packet 434 /* process the login reply packet */
436 void qq_process_login_reply(guint8 * buf, gint buf_len, GaimConnection * gc) 435 void qq_process_login_reply(guint8 *buf, gint buf_len, GaimConnection *gc)
437 { 436 {
438 gint len, ret, bytes; 437 gint len, ret, bytes;
439 guint8 *data; 438 guint8 *data;
440 qq_data *qd; 439 qq_data *qd;
441 440
442 g_return_if_fail(gc != NULL && gc->proto_data != NULL); 441 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
443 g_return_if_fail(buf != NULL && buf_len != 0); 442 g_return_if_fail(buf != NULL && buf_len != 0);
444 443
445 qd = (qq_data *) gc->proto_data; 444 qd = (qq_data *) gc->proto_data;
446 len = buf_len; 445 len = buf_len;
447 data = g_newa(guint8, len); // no need to be freed in the future 446 data = g_newa(guint8, len);
448 447
449 if (qq_crypt(DECRYPT, buf, buf_len, qd->pwkey, data, &len)) { 448 if (qq_crypt(DECRYPT, buf, buf_len, qd->pwkey, data, &len)) {
450 // should be able to decrypt with pwkey 449 /* should be able to decrypt with pwkey */
451 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Decrypt login reply packet with pwkey, %d bytes\n", len); 450 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Decrypt login reply packet with pwkey, %d bytes\n", len);
452 if (data[0] == QQ_LOGIN_REPLY_OK) { 451 if (data[0] == QQ_LOGIN_REPLY_OK) {
453 ret = _qq_process_login_ok(gc, data, len); 452 ret = _qq_process_login_ok(gc, data, len);
454 } else { 453 } else {
455 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Unknown login reply code : %d\n", data[0]); 454 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Unknown login reply code : %d\n", data[0]);
456 ret = QQ_LOGIN_REPLY_MISC_ERROR; 455 ret = QQ_LOGIN_REPLY_MISC_ERROR;
457 } // if QQ_LOGIN_REPLY_OK 456 }
458 } else { // decrypt with pwkey error 457 } else { /* decrypt with pwkey error */
459 len = buf_len; // reset len, decrypt will fail if len is too short 458 len = buf_len; /* reset len, decrypt will fail if len is too short */
460 if (qq_crypt(DECRYPT, buf, buf_len, qd->inikey, data, &len)) { 459 if (qq_crypt(DECRYPT, buf, buf_len, qd->inikey, data, &len)) {
461 // decrypt ok with inipwd, it might be password error 460 /* decrypt ok with inipwd, it might be password error */
462 gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Decrypt login reply packet with inikey, %d bytes\n", len); 461 gaim_debug(GAIM_DEBUG_WARNING, "QQ",
462 "Decrypt login reply packet with inikey, %d bytes\n", len);
463 bytes = 0; 463 bytes = 0;
464 switch (data[0]) { 464 switch (data[0]) {
465 case QQ_LOGIN_REPLY_REDIRECT: 465 case QQ_LOGIN_REPLY_REDIRECT:
466 ret = _qq_process_login_redirect(gc, data, len); 466 ret = _qq_process_login_redirect(gc, data, len);
467 break; 467 break;
474 ">>> %d bytes -> [default] decrypt and dump\n%s", 474 ">>> %d bytes -> [default] decrypt and dump\n%s",
475 buf_len, hex_dump_to_str(data, len)); 475 buf_len, hex_dump_to_str(data, len));
476 try_dump_as_gbk(data, len); 476 try_dump_as_gbk(data, len);
477 477
478 ret = QQ_LOGIN_REPLY_MISC_ERROR; 478 ret = QQ_LOGIN_REPLY_MISC_ERROR;
479 } // switch data[0] 479 }
480 } else { // no idea how to decrypt 480 } else { /* no idea how to decrypt */
481 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "No idea how to decrypt login reply\n"); 481 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "No idea how to decrypt login reply\n");
482 ret = QQ_LOGIN_REPLY_MISC_ERROR; 482 ret = QQ_LOGIN_REPLY_MISC_ERROR;
483 } // if qq_crypt with qd->inikey 483 }
484 } // if qq_crypt with qd->pwkey 484 }
485 485
486 switch (ret) { 486 switch (ret) {
487 case QQ_LOGIN_REPLY_PWD_ERROR: 487 case QQ_LOGIN_REPLY_PWD_ERROR:
488 gc->wants_to_die = TRUE; 488 gc->wants_to_die = TRUE;
489 gaim_connection_error(gc, _("Wrong password!")); 489 gaim_connection_error(gc, _("Wrong password!"));
493 break; 493 break;
494 case QQ_LOGIN_REPLY_OK: 494 case QQ_LOGIN_REPLY_OK:
495 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Login replys OK, everything is fine\n"); 495 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Login replys OK, everything is fine\n");
496 break; 496 break;
497 case QQ_LOGIN_REPLY_REDIRECT: 497 case QQ_LOGIN_REPLY_REDIRECT:
498 // the redirect has been done in _qq_process_login_reply 498 /* the redirect has been done in _qq_process_login_reply */
499 break; 499 break;
500 default:{; 500 default:{;
501 } 501 }
502 } 502 }
503 } 503 }