libpurple/protocols/qq/buddy_status.c

branch
release-2.4.3
changeset 23190
ce258cadbd9e
parent 22685
f3a524370c38
child 23192
2f00b04db5cb
equal deleted inserted replaced
23188:eab7aad90c95 23190:ce258cadbd9e
1 /** 1 /**
2 * @file buddy_status.c 2 * @file buddy_status.c
3 * 3 *
4 * purple 4 * purple
5 * 5 *
6 * Purple is the legal property of its developers, whose names are too numerous 6 * Purple is the legal property ofr its developers, whose names are too numerous
7 * to list here. Please refer to the COPYRIGHT file distributed with this 7 * to list here. Please refer to the COPYRIGHT file distributed with this
8 * source distribution. 8 * source distribution.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 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 11 * it under the terms of the GNU General Public License as published by
64 /* TODO: figure out what's going on with the IP region. Sometimes I get valid IP addresses, 64 /* TODO: figure out what's going on with the IP region. Sometimes I get valid IP addresses,
65 * but the port number's weird, other times I get 0s. I get these simultaneously on the same buddy, 65 * but the port number's weird, other times I get 0s. I get these simultaneously on the same buddy,
66 * using different accounts to get info. */ 66 * using different accounts to get info. */
67 67
68 /* parse the data into qq_buddy_status */ 68 /* parse the data into qq_buddy_status */
69 gint qq_buddy_status_read(guint8 *data, guint8 **cursor, gint len, qq_buddy_status *s) 69 gint qq_buddy_status_read(qq_buddy_status *s, guint8 *data)
70 { 70 {
71 gint bytes; 71 gint bytes = 0;
72 72
73 g_return_val_if_fail(data != NULL && *cursor != NULL && s != NULL, -1); 73 g_return_val_if_fail(data != NULL && s != NULL, -1);
74
75 bytes = 0;
76 74
77 /* 000-003: uid */ 75 /* 000-003: uid */
78 bytes += read_packet_dw(data, cursor, len, &s->uid); 76 bytes += qq_get32(&s->uid, data + bytes);
79 /* 004-004: 0x01 */ 77 /* 004-004: 0x01 */
80 bytes += read_packet_b(data, cursor, len, &s->unknown1); 78 bytes += qq_get8(&s->unknown1, data + bytes);
81 /* this is no longer the IP, it seems QQ (as of 2006) no longer sends 79 /* this is no longer the IP, it seems QQ (as of 2006) no longer sends
82 * the buddy's IP in this packet. all 0s */ 80 * the buddy's IP in this packet. all 0s */
83 /* 005-008: ip */ 81 /* 005-008: ip */
84 s->ip = g_new0(guint8, 4); 82 s->ip = g_new0(guint8, 4);
85 bytes += read_packet_data(data, cursor, len, s->ip, 4); 83 bytes += qq_getdata(s->ip, 4, data + bytes);
86 /* port info is no longer here either */ 84 /* port info is no longer here either */
87 /* 009-010: port */ 85 /* 009-010: port */
88 bytes += read_packet_w(data, cursor, len, &s->port); 86 bytes += qq_get16(&s->port, data + bytes);
89 /* 011-011: 0x00 */ 87 /* 011-011: 0x00 */
90 bytes += read_packet_b(data, cursor, len, &s->unknown2); 88 bytes += qq_get8(&s->unknown2, data + bytes);
91 /* 012-012: status */ 89 /* 012-012: status */
92 bytes += read_packet_b(data, cursor, len, &s->status); 90 bytes += qq_get8(&s->status, data + bytes);
93 /* 013-014: client_version */ 91 /* 013-014: client_version */
94 bytes += read_packet_w(data, cursor, len, &s->client_version); 92 bytes += qq_get16(&s->client_version, data + bytes);
95 /* 015-030: unknown key */ 93 /* 015-030: unknown key */
96 s->unknown_key = g_new0(guint8, QQ_KEY_LENGTH); 94 s->unknown_key = g_new0(guint8, QQ_KEY_LENGTH);
97 bytes += read_packet_data(data, cursor, len, s->unknown_key, QQ_KEY_LENGTH); 95 bytes += qq_getdata(s->unknown_key, QQ_KEY_LENGTH, data + bytes);
98 96
99 if (s->uid == 0 || bytes != 31) 97 if (s->uid == 0 || bytes != 31)
100 return -1; 98 return -1;
101 99
102 return bytes; 100 return bytes;
104 102
105 /* check if status means online or offline */ 103 /* check if status means online or offline */
106 gboolean is_online(guint8 status) 104 gboolean is_online(guint8 status)
107 { 105 {
108 switch(status) { 106 switch(status) {
109 case QQ_BUDDY_ONLINE_NORMAL: 107 case QQ_BUDDY_ONLINE_NORMAL:
110 case QQ_BUDDY_ONLINE_AWAY: 108 case QQ_BUDDY_ONLINE_AWAY:
111 case QQ_BUDDY_ONLINE_INVISIBLE: 109 case QQ_BUDDY_ONLINE_INVISIBLE:
112 return TRUE; 110 return TRUE;
113 case QQ_BUDDY_ONLINE_OFFLINE: 111 case QQ_BUDDY_ONLINE_OFFLINE:
114 return FALSE; 112 return FALSE;
115 } 113 }
116 return FALSE; 114 return FALSE;
117 } 115 }
118 116
119 /* Help calculate the correct icon index to tell the server. */ 117 /* Help calculate the correct icon index to tell the server. */
120 gint get_icon_offset(PurpleConnection *gc) 118 gint get_icon_offset(PurpleConnection *gc)
121 { 119 {
122 PurpleAccount *account; 120 PurpleAccount *account;
123 PurplePresence *presence; 121 PurplePresence *presence;
124 122
129 return 2; 127 return 2;
130 } else if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_AWAY) 128 } else if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_AWAY)
131 || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_EXTENDED_AWAY) 129 || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_EXTENDED_AWAY)
132 || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_UNAVAILABLE)) { 130 || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_UNAVAILABLE)) {
133 return 1; 131 return 1;
134 } else { 132 } else {
135 return 0; 133 return 0;
136 } 134 }
137 } 135 }
138 136
139 /* send a packet to change my online status */ 137 /* send a packet to change my online status */
140 void qq_send_packet_change_status(PurpleConnection *gc) 138 void qq_send_packet_change_status(PurpleConnection *gc)
141 { 139 {
142 qq_data *qd; 140 qq_data *qd;
143 guint8 *raw_data, *cursor, away_cmd; 141 guint8 raw_data[16] = {0};
142 gint bytes = 0;
143 guint8 away_cmd;
144 guint32 misc_status; 144 guint32 misc_status;
145 gboolean fake_video; 145 gboolean fake_video;
146 PurpleAccount *account; 146 PurpleAccount *account;
147 PurplePresence *presence; 147 PurplePresence *presence;
148 148
161 away_cmd = QQ_BUDDY_ONLINE_AWAY; 161 away_cmd = QQ_BUDDY_ONLINE_AWAY;
162 } else { 162 } else {
163 away_cmd = QQ_BUDDY_ONLINE_NORMAL; 163 away_cmd = QQ_BUDDY_ONLINE_NORMAL;
164 } 164 }
165 165
166 raw_data = g_new0(guint8, 5);
167 cursor = raw_data;
168 misc_status = 0x00000000; 166 misc_status = 0x00000000;
169
170 fake_video = purple_prefs_get_bool("/plugins/prpl/qq/show_fake_video"); 167 fake_video = purple_prefs_get_bool("/plugins/prpl/qq/show_fake_video");
171 if (fake_video) 168 if (fake_video)
172 misc_status |= QQ_MISC_STATUS_HAVING_VIIDEO; 169 misc_status |= QQ_MISC_STATUS_HAVING_VIIDEO;
173 170
174 create_packet_b(raw_data, &cursor, away_cmd); 171 bytes = 0;
175 create_packet_dw(raw_data, &cursor, misc_status); 172 bytes += qq_put8(raw_data + bytes, away_cmd);
176 173 bytes += qq_put32(raw_data + bytes, misc_status);
177 qq_send_cmd(gc, QQ_CMD_CHANGE_ONLINE_STATUS, TRUE, 0, TRUE, raw_data, 5); 174
178 175 qq_send_cmd(gc, QQ_CMD_CHANGE_ONLINE_STATUS, TRUE, 0, TRUE, raw_data, bytes);
179 g_free(raw_data);
180 } 176 }
181 177
182 /* parse the reply packet for change_status */ 178 /* parse the reply packet for change_status */
183 void qq_process_change_status_reply(guint8 *buf, gint buf_len, PurpleConnection *gc) 179 void qq_process_change_status_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
184 { 180 {
185 qq_data *qd; 181 qq_data *qd;
186 gint len; 182 gint len, bytes;
187 guint8 *data, *cursor, reply; 183 guint8 *data, reply;
188 PurpleBuddy *b; 184 PurpleBuddy *b;
189 qq_buddy *q_bud; 185 qq_buddy *q_bud;
190 gchar *name; 186 gchar *name;
191 187
192 g_return_if_fail(buf != NULL && buf_len != 0); 188 g_return_if_fail(buf != NULL && buf_len != 0);
193 189
194 qd = (qq_data *) gc->proto_data; 190 qd = (qq_data *) gc->proto_data;
195 len = buf_len; 191 len = buf_len;
196 data = g_newa(guint8, len); 192 data = g_newa(guint8, len);
197 193
198 if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) { 194 if ( !qq_decrypt(buf, buf_len, qd->session_key, data, &len) ) {
199 cursor = data;
200 read_packet_b(data, &cursor, len, &reply);
201 if (reply != QQ_CHANGE_ONLINE_STATUS_REPLY_OK) {
202 purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Change status fail\n");
203 } else {
204 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Change status OK\n");
205 name = uid_to_purple_name(qd->uid);
206 b = purple_find_buddy(gc->account, name);
207 g_free(name);
208 q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
209 qq_update_buddy_contact(gc, q_bud);
210 }
211 } else {
212 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt chg status reply\n"); 195 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt chg status reply\n");
196 return;
197 }
198
199 bytes = 0;
200 bytes = qq_get8(&reply, data + bytes);
201 if (reply != QQ_CHANGE_ONLINE_STATUS_REPLY_OK) {
202 purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Change status fail\n");
203 } else {
204 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Change status OK\n");
205 name = uid_to_purple_name(qd->uid);
206 b = purple_find_buddy(gc->account, name);
207 g_free(name);
208 q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
209 qq_update_buddy_contact(gc, q_bud);
213 } 210 }
214 } 211 }
215 212
216 /* it is a server message indicating that one of my buddies has changed its status */ 213 /* it is a server message indicating that one of my buddies has changed its status */
217 void qq_process_friend_change_status(guint8 *buf, gint buf_len, PurpleConnection *gc) 214 void qq_process_friend_change_status(guint8 *buf, gint buf_len, PurpleConnection *gc)
218 { 215 {
219 qq_data *qd; 216 qq_data *qd;
220 gint len, bytes; 217 gint len, bytes;
221 guint32 my_uid; 218 guint32 my_uid;
222 guint8 *data, *cursor; 219 guint8 *data;
223 PurpleBuddy *b; 220 PurpleBuddy *b;
224 qq_buddy *q_bud; 221 qq_buddy *q_bud;
225 qq_buddy_status *s; 222 qq_buddy_status *s;
226 gchar *name; 223 gchar *name;
227 224
228 g_return_if_fail(buf != NULL && buf_len != 0); 225 g_return_if_fail(buf != NULL && buf_len != 0);
229 226
230 qd = (qq_data *) gc->proto_data; 227 qd = (qq_data *) gc->proto_data;
231 len = buf_len; 228 len = buf_len;
232 data = g_newa(guint8, len); 229 data = g_newa(guint8, len);
233 cursor = data; 230
234 231 if ( !qq_decrypt(buf, buf_len, qd->session_key, data, &len) ) {
235 if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) { 232 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt buddy status change packet\n");
236 s = g_new0(qq_buddy_status, 1); 233 return;
237 bytes = 0; 234 }
238 /* 000-030: qq_buddy_status */ 235
239 bytes += qq_buddy_status_read(data, &cursor, len, s); 236 s = g_new0(qq_buddy_status, 1);
240 /* 031-034: my uid */ 237 bytes = 0;
241 /* This has a value of 0 when we've changed our status to 238 /* 000-030: qq_buddy_status */
242 * QQ_BUDDY_ONLINE_INVISIBLE */ 239 bytes += qq_buddy_status_read(s, data + bytes);
243 bytes += read_packet_dw(data, &cursor, len, &my_uid); 240 /* 031-034: my uid */
244 241 /* This has a value of 0 when we've changed our status to
245 if (bytes != 35) { 242 * QQ_BUDDY_ONLINE_INVISIBLE */
246 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "bytes(%d) != 35\n", bytes); 243 bytes += qq_get32(&my_uid, data + bytes);
247 g_free(s->ip); 244
248 g_free(s->unknown_key); 245 if (bytes != 35) {
249 g_free(s); 246 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "bytes(%d) != 35\n", bytes);
250 return;
251 }
252
253 name = uid_to_purple_name(s->uid);
254 b = purple_find_buddy(gc->account, name);
255 g_free(name);
256 q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
257 if (q_bud) {
258 purple_debug(PURPLE_DEBUG_INFO, "QQ", "s->uid = %d, q_bud->uid = %d\n", s->uid , q_bud->uid);
259 if(0 != *((guint32 *)s->ip)) {
260 g_memmove(q_bud->ip, s->ip, 4);
261 q_bud->port = s->port;
262 }
263 q_bud->status = s->status;
264 if(0 != s->client_version)
265 q_bud->client_version = s->client_version;
266 if (q_bud->status == QQ_BUDDY_ONLINE_NORMAL)
267 qq_send_packet_get_level(gc, q_bud->uid);
268 qq_update_buddy_contact(gc, q_bud);
269 } else {
270 purple_debug(PURPLE_DEBUG_ERROR, "QQ",
271 "got information of unknown buddy %d\n", s->uid);
272 }
273
274 g_free(s->ip); 247 g_free(s->ip);
275 g_free(s->unknown_key); 248 g_free(s->unknown_key);
276 g_free(s); 249 g_free(s);
277 } else { 250 return;
278 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt buddy status change packet\n"); 251 }
279 } 252
280 } 253 name = uid_to_purple_name(s->uid);
254 b = purple_find_buddy(gc->account, name);
255 g_free(name);
256 q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
257 if (q_bud) {
258 purple_debug(PURPLE_DEBUG_INFO, "QQ", "s->uid = %d, q_bud->uid = %d\n", s->uid , q_bud->uid);
259 if(0 != *((guint32 *)s->ip)) {
260 g_memmove(q_bud->ip, s->ip, 4);
261 q_bud->port = s->port;
262 }
263 q_bud->status = s->status;
264 if(0 != s->client_version) {
265 q_bud->client_version = s->client_version;
266 }
267 if (q_bud->status == QQ_BUDDY_ONLINE_NORMAL) {
268 qq_send_packet_get_level(gc, q_bud->uid);
269 }
270 qq_update_buddy_contact(gc, q_bud);
271 } else {
272 purple_debug(PURPLE_DEBUG_ERROR, "QQ",
273 "got information of unknown buddy %d\n", s->uid);
274 }
275
276 g_free(s->ip);
277 g_free(s->unknown_key);
278 g_free(s);
279 }

mercurial