Mercurial > pidgin
comparison libgaim/protocols/qq/sys_msg.c @ 14192:60b1bc8dbf37
[gaim-migrate @ 16863]
Renamed 'core' to 'libgaim'
committer: Tailor Script <tailor@pidgin.im>
author | Evan Schoenberg <evan.s@dreskin.net> |
---|---|
date | Sat, 19 Aug 2006 01:50:10 +0000 |
parents | |
children | 3c58357772a2 |
comparison
equal
deleted
inserted
replaced
14191:009db0b357b5 | 14192:60b1bc8dbf37 |
---|---|
1 /** | |
2 * The QQ2003C protocol plugin | |
3 * | |
4 * for gaim | |
5 * | |
6 * Copyright (C) 2004 Puzzlebird | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
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 | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 */ | |
22 | |
23 #include "debug.h" | |
24 #include "internal.h" | |
25 #include "notify.h" | |
26 #include "request.h" | |
27 | |
28 #include "buddy_info.h" | |
29 #include "buddy_list.h" | |
30 #include "buddy_opt.h" | |
31 #include "char_conv.h" | |
32 #include "crypt.h" | |
33 #include "header_info.h" | |
34 #include "packet_parse.h" | |
35 #include "qq.h" | |
36 #include "send_core.h" | |
37 #include "sys_msg.h" | |
38 #include "utils.h" | |
39 | |
40 enum { | |
41 QQ_MSG_SYS_BEING_ADDED = 0x01, | |
42 QQ_MSG_SYS_ADD_CONTACT_REQUEST = 0x02, | |
43 QQ_MSG_SYS_ADD_CONTACT_APPROVED = 0x03, | |
44 QQ_MSG_SYS_ADD_CONTACT_REJECTED = 0x04, | |
45 QQ_MSG_SYS_NEW_VERSION = 0x09 | |
46 }; | |
47 | |
48 /* Henry: private function for reading/writing of system log */ | |
49 static void _qq_sys_msg_log_write(GaimConnection *gc, gchar *msg, gchar *from) | |
50 { | |
51 GaimLog *log; | |
52 GaimAccount *account; | |
53 | |
54 account = gaim_connection_get_account(gc); | |
55 g_return_if_fail(gc != NULL && gc->proto_data != NULL); | |
56 | |
57 log = gaim_log_new(GAIM_LOG_IM, | |
58 "systemim", | |
59 account, | |
60 NULL, | |
61 time(NULL), | |
62 NULL | |
63 ); | |
64 gaim_log_write(log, GAIM_MESSAGE_SYSTEM, from, | |
65 time(NULL), msg); | |
66 gaim_log_free(log); | |
67 } | |
68 | |
69 /* suggested by rakescar@linuxsir, can still approve after search */ | |
70 static void _qq_search_before_auth_with_gc_and_uid(gc_and_uid *g) | |
71 { | |
72 GaimConnection *gc; | |
73 guint32 uid; | |
74 | |
75 g_return_if_fail(g != NULL); | |
76 | |
77 gc = g->gc; | |
78 uid = g->uid; | |
79 g_return_if_fail(gc != 0 && uid != 0); | |
80 | |
81 qq_send_packet_get_info(gc, uid, TRUE); /* we wanna see window */ | |
82 gaim_request_action | |
83 (gc, NULL, _("Do you wanna approve the request?"), "", 2, g, 2, | |
84 _("Reject"), | |
85 G_CALLBACK(qq_reject_add_request_with_gc_and_uid), | |
86 _("Approve"), G_CALLBACK(qq_approve_add_request_with_gc_and_uid)); | |
87 } | |
88 | |
89 static void _qq_search_before_add_with_gc_and_uid(gc_and_uid *g) | |
90 { | |
91 GaimConnection *gc; | |
92 guint32 uid; | |
93 | |
94 g_return_if_fail(g != NULL); | |
95 | |
96 gc = g->gc; | |
97 uid = g->uid; | |
98 g_return_if_fail(gc != 0 && uid != 0); | |
99 | |
100 qq_send_packet_get_info(gc, uid, TRUE); /* we wanna see window */ | |
101 gaim_request_action | |
102 (gc, NULL, _("Do you wanna add this buddy?"), "", 2, g, 2, | |
103 _("Cancel"), NULL, _("Add"), G_CALLBACK(qq_add_buddy_with_gc_and_uid)); | |
104 } | |
105 | |
106 /* Send ACK if the sys message needs an ACK */ | |
107 static void _qq_send_packet_ack_msg_sys(GaimConnection *gc, guint8 code, guint32 from, guint16 seq) | |
108 { | |
109 guint8 bar, *ack, *cursor; | |
110 gchar *str; | |
111 gint ack_len, bytes; | |
112 | |
113 str = g_strdup_printf("%d", from); | |
114 bar = 0x1e; | |
115 ack_len = 1 + 1 + strlen(str) + 1 + 2; | |
116 ack = g_newa(guint8, ack_len); | |
117 cursor = ack; | |
118 bytes = 0; | |
119 | |
120 bytes += create_packet_b(ack, &cursor, code); | |
121 bytes += create_packet_b(ack, &cursor, bar); | |
122 bytes += create_packet_data(ack, &cursor, (guint8 *) str, strlen(str)); | |
123 bytes += create_packet_b(ack, &cursor, bar); | |
124 bytes += create_packet_w(ack, &cursor, seq); | |
125 | |
126 g_free(str); | |
127 | |
128 if (bytes == ack_len) /* creation OK */ | |
129 qq_send_cmd(gc, QQ_CMD_ACK_SYS_MSG, TRUE, 0, FALSE, ack, ack_len); | |
130 else | |
131 gaim_debug(GAIM_DEBUG_ERROR, "QQ", | |
132 "Fail creating sys msg ACK, expect %d bytes, build %d bytes\n", ack_len, bytes); | |
133 } | |
134 | |
135 /* when you are added by a person, QQ server will send sys message */ | |
136 static void _qq_process_msg_sys_being_added(GaimConnection *gc, gchar *from, gchar *to, gchar *msg_utf8) | |
137 { | |
138 gchar *message; | |
139 GaimBuddy *b; | |
140 guint32 uid; | |
141 gc_and_uid *g; | |
142 gchar *name; | |
143 | |
144 g_return_if_fail(gc != NULL && from != NULL && to != NULL); | |
145 | |
146 uid = strtol(from, NULL, 10); | |
147 name = uid_to_gaim_name(uid); | |
148 b = gaim_find_buddy(gc->account, name); | |
149 g_free(name); | |
150 if (b == NULL) { /* the person is not in my list */ | |
151 g = g_new0(gc_and_uid, 1); | |
152 g->gc = gc; | |
153 g->uid = uid; /* only need to get value */ | |
154 message = g_strdup_printf(_("You have been added by %s"), from); | |
155 _qq_sys_msg_log_write(gc, message, from); | |
156 gaim_request_action(gc, NULL, message, | |
157 _("Would like to add him?"), 2, g, 3, | |
158 _("Cancel"), NULL, _("Add"), | |
159 G_CALLBACK | |
160 (qq_add_buddy_with_gc_and_uid), | |
161 _("Search"), G_CALLBACK(_qq_search_before_add_with_gc_and_uid)); | |
162 } else { | |
163 message = g_strdup_printf(_("%s has added you [%s]"), from, to); | |
164 _qq_sys_msg_log_write(gc, message, from); | |
165 gaim_notify_info(gc, NULL, message, NULL); | |
166 } | |
167 | |
168 g_free(message); | |
169 } | |
170 | |
171 /* you are rejected by the person */ | |
172 static void _qq_process_msg_sys_add_contact_rejected(GaimConnection *gc, gchar *from, gchar *to, gchar *msg_utf8) | |
173 { | |
174 gchar *message, *reason; | |
175 | |
176 g_return_if_fail(gc != NULL && from != NULL && to != NULL); | |
177 | |
178 message = g_strdup_printf(_("User %s rejected your request"), from); | |
179 reason = g_strdup_printf(_("Reason: %s"), msg_utf8); | |
180 _qq_sys_msg_log_write(gc, message, from); | |
181 | |
182 gaim_notify_info(gc, NULL, message, reason); | |
183 g_free(message); | |
184 g_free(reason); | |
185 } | |
186 | |
187 /* the buddy approves your request of adding him/her as your friend */ | |
188 static void _qq_process_msg_sys_add_contact_approved(GaimConnection *gc, gchar *from, gchar *to, gchar *msg_utf8) | |
189 { | |
190 gchar *message; | |
191 qq_data *qd; | |
192 | |
193 g_return_if_fail(gc != NULL && from != NULL && to != NULL); | |
194 | |
195 qd = (qq_data *) gc->proto_data; | |
196 qq_add_buddy_by_recv_packet(gc, strtol(from, NULL, 10), TRUE, TRUE); | |
197 | |
198 message = g_strdup_printf(_("Use %s has approved your request"), from); | |
199 _qq_sys_msg_log_write(gc, message, from); | |
200 gaim_notify_info(gc, NULL, message, NULL); | |
201 | |
202 g_free(message); | |
203 } | |
204 | |
205 /* someone wants to add you to his buddy list */ | |
206 static void _qq_process_msg_sys_add_contact_request(GaimConnection *gc, gchar *from, gchar *to, gchar *msg_utf8) | |
207 { | |
208 gchar *message, *reason; | |
209 guint32 uid; | |
210 gc_and_uid *g, *g2; | |
211 GaimBuddy *b; | |
212 gchar *name; | |
213 | |
214 g_return_if_fail(gc != NULL && from != NULL && to != NULL); | |
215 | |
216 uid = strtol(from, NULL, 10); | |
217 g = g_new0(gc_and_uid, 1); | |
218 g->gc = gc; | |
219 g->uid = uid; | |
220 | |
221 message = g_strdup_printf(_("%s wanna add you [%s] as friends"), from, to); | |
222 reason = g_strdup_printf(_("Message: %s"), msg_utf8); | |
223 _qq_sys_msg_log_write(gc, message, from); | |
224 | |
225 gaim_request_action | |
226 (gc, NULL, message, reason, 2, g, 3, | |
227 _("Reject"), | |
228 G_CALLBACK(qq_reject_add_request_with_gc_and_uid), | |
229 _("Approve"), | |
230 G_CALLBACK(qq_approve_add_request_with_gc_and_uid), | |
231 _("Search"), G_CALLBACK(_qq_search_before_auth_with_gc_and_uid)); | |
232 | |
233 g_free(message); | |
234 g_free(reason); | |
235 | |
236 name = uid_to_gaim_name(uid); | |
237 b = gaim_find_buddy(gc->account, name); | |
238 g_free(name); | |
239 if (b == NULL) { /* the person is not in my list */ | |
240 g2 = g_new0(gc_and_uid, 1); | |
241 g2->gc = gc; | |
242 g2->uid = strtol(from, NULL, 10); | |
243 message = g_strdup_printf(_("%s is not in your buddy list"), from); | |
244 gaim_request_action(gc, NULL, message, | |
245 _("Would you like to add him?"), 2, g2, | |
246 3, _("Cancel"), NULL, _("Add"), | |
247 G_CALLBACK | |
248 (qq_add_buddy_with_gc_and_uid), | |
249 _("Search"), G_CALLBACK(_qq_search_before_add_with_gc_and_uid)); | |
250 g_free(message); | |
251 } | |
252 } | |
253 | |
254 void qq_process_msg_sys(guint8 *buf, gint buf_len, guint16 seq, GaimConnection *gc) | |
255 { | |
256 qq_data *qd; | |
257 gint len; | |
258 guint8 *data; | |
259 gchar **segments, *code, *from, *to, *msg, *msg_utf8; | |
260 | |
261 g_return_if_fail(gc != NULL && gc->proto_data != NULL); | |
262 g_return_if_fail(buf != NULL && buf_len != 0); | |
263 | |
264 qd = (qq_data *) gc->proto_data; | |
265 len = buf_len; | |
266 data = g_newa(guint8, len); | |
267 | |
268 if (qq_crypt(DECRYPT, buf, buf_len, qd->session_key, data, &len)) { | |
269 if (NULL == (segments = split_data(data, len, "\x1f", 4))) | |
270 return; | |
271 code = segments[0]; | |
272 from = segments[1]; | |
273 to = segments[2]; | |
274 msg = segments[3]; | |
275 | |
276 _qq_send_packet_ack_msg_sys(gc, code[0], strtol(from, NULL, 10), seq); | |
277 | |
278 if (strtol(to, NULL, 10) != qd->uid) { /* not to me */ | |
279 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Recv sys msg to [%s], not me!, discard\n", to); | |
280 g_strfreev(segments); | |
281 return; | |
282 } | |
283 | |
284 msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); | |
285 switch (strtol(code, NULL, 10)) { | |
286 case QQ_MSG_SYS_BEING_ADDED: | |
287 _qq_process_msg_sys_being_added(gc, from, to, msg_utf8); | |
288 break; | |
289 case QQ_MSG_SYS_ADD_CONTACT_REQUEST: | |
290 _qq_process_msg_sys_add_contact_request(gc, from, to, msg_utf8); | |
291 break; | |
292 case QQ_MSG_SYS_ADD_CONTACT_APPROVED: | |
293 _qq_process_msg_sys_add_contact_approved(gc, from, to, msg_utf8); | |
294 break; | |
295 case QQ_MSG_SYS_ADD_CONTACT_REJECTED: | |
296 _qq_process_msg_sys_add_contact_rejected(gc, from, to, msg_utf8); | |
297 break; | |
298 case QQ_MSG_SYS_NEW_VERSION: | |
299 gaim_debug(GAIM_DEBUG_WARNING, "QQ", | |
300 "QQ server says there is newer version than %s\n", qq_get_source_str(QQ_CLIENT)); | |
301 break; | |
302 default: | |
303 gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Recv unknown sys msg code: %s\n", code); | |
304 gaim_debug(GAIM_DEBUG_WARNING, "QQ", "the msg is : %s\n", msg_utf8); | |
305 } | |
306 g_free(msg_utf8); | |
307 g_strfreev(segments); | |
308 | |
309 } else { | |
310 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Error decrypt recv msg sys\n"); | |
311 } | |
312 } |