Mercurial > pidgin.yaz
annotate src/protocols/msn/cmdproc.c @ 10345:2e01c503aa4f
[gaim-migrate @ 11556]
Patch 1078151 from Felipe Contreras to fix some more MSN bugs:
"User Dislpay messages, and other less used, did not set
an slpcall, so the callback that should not be called,
was called (in some very special cases)."
...
"Here it goes the real real one, as far as I can tell.
Cleaning + organizing + documentation + hard bug fix = big
patch." -- Felipe Contreras
I also fixed drag-and-drop to conversation window file transfers (which
I had broken when I fixed some other dnd thing), made the debug output
of the autoreconnect plugin more useful, and stopped the message
notification plugin notifying you for messages sent by ignored users.
committer: Tailor Script <tailor@pidgin.im>
author | Stu Tomlinson <stu@nosnilmot.com> |
---|---|
date | Sat, 11 Dec 2004 20:01:58 +0000 |
parents | 926bd0e5f487 |
children | e5455f1dc9b6 |
rev | line source |
---|---|
8810 | 1 /** |
2 * @file cmdproc.c MSN command processor functions | |
3 * | |
4 * gaim | |
5 * | |
9198
ab6636c5a136
[gaim-migrate @ 9993]
Christian Hammond <chipx86@chipx86.com>
parents:
9193
diff
changeset
|
6 * Gaim is the legal property of its developers, whose names are too numerous |
ab6636c5a136
[gaim-migrate @ 9993]
Christian Hammond <chipx86@chipx86.com>
parents:
9193
diff
changeset
|
7 * to list here. Please refer to the COPYRIGHT file distributed with this |
ab6636c5a136
[gaim-migrate @ 9993]
Christian Hammond <chipx86@chipx86.com>
parents:
9193
diff
changeset
|
8 * source distribution. |
8810 | 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
23 */ | |
24 #include "msn.h" | |
25 #include "cmdproc.h" | |
26 | |
27 MsnCmdProc * | |
28 msn_cmdproc_new(MsnSession *session) | |
29 { | |
30 MsnCmdProc *cmdproc; | |
31 | |
32 cmdproc = g_new0(MsnCmdProc, 1); | |
33 | |
34 cmdproc->session = session; | |
35 cmdproc->txqueue = g_queue_new(); | |
36 cmdproc->history = msn_history_new(); | |
37 | |
38 return cmdproc; | |
39 } | |
40 | |
41 void | |
42 msn_cmdproc_destroy(MsnCmdProc *cmdproc) | |
43 { | |
44 MsnTransaction *trans; | |
45 | |
46 if (cmdproc->last_trans != NULL) | |
47 g_free(cmdproc->last_trans); | |
48 | |
49 while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL) | |
50 msn_transaction_destroy(trans); | |
51 | |
52 g_queue_free(cmdproc->txqueue); | |
53 | |
54 msn_history_destroy(cmdproc->history); | |
55 } | |
56 | |
57 void | |
58 msn_cmdproc_process_queue(MsnCmdProc *cmdproc) | |
59 { | |
60 MsnTransaction *trans; | |
61 | |
62 while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL && | |
63 cmdproc->error == 0) | |
64 { | |
65 msn_cmdproc_send_trans(cmdproc, trans); | |
66 } | |
67 } | |
68 | |
69 void | |
70 msn_cmdproc_queue_trans(MsnCmdProc *cmdproc, MsnTransaction *trans) | |
71 { | |
72 g_return_if_fail(cmdproc != NULL); | |
73 g_return_if_fail(trans != NULL); | |
74 | |
75 g_queue_push_tail(cmdproc->txqueue, trans); | |
76 } | |
77 | |
78 static void | |
79 show_debug_cmd(MsnCmdProc *cmdproc, gboolean incoming, const char *command) | |
80 { | |
81 MsnServConn *servconn; | |
82 const char *names[] = { "NS", "SB" }; | |
83 char *show; | |
84 char tmp; | |
85 size_t len; | |
86 | |
87 servconn = cmdproc->servconn; | |
88 len = strlen(command); | |
89 show = g_strdup(command); | |
90 | |
91 tmp = (incoming) ? 'S' : 'C'; | |
92 | |
93 if ((show[len - 1] == '\n') && (show[len - 2] == '\r')) | |
94 { | |
95 show[len - 2] = '\0'; | |
96 } | |
97 | |
98 gaim_debug_misc("msn", "%c: %s %03d: %s\n", tmp, | |
99 names[servconn->type], servconn->num, show); | |
100 | |
101 g_free(show); | |
102 } | |
103 | |
104 void | |
105 msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans) | |
106 { | |
107 MsnServConn *servconn; | |
108 char *data; | |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
109 size_t len; |
8810 | 110 |
111 g_return_if_fail(cmdproc != NULL); | |
112 g_return_if_fail(trans != NULL); | |
113 | |
114 servconn = cmdproc->servconn; | |
115 msn_history_add(cmdproc->history, trans); | |
116 | |
117 data = msn_transaction_to_string(trans); | |
9158
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
118 |
10284 | 119 if (cmdproc->last_trans != NULL) |
120 g_free(cmdproc->last_trans); | |
121 | |
8810 | 122 cmdproc->last_trans = g_strdup(data); |
123 | |
124 len = strlen(data); | |
125 | |
126 show_debug_cmd(cmdproc, FALSE, data); | |
127 | |
128 if (trans->callbacks == NULL) | |
129 trans->callbacks = g_hash_table_lookup(cmdproc->cbs_table->cmds, | |
130 trans->command); | |
131 | |
132 if (trans->payload != NULL) | |
133 { | |
134 data = g_realloc(data, len + trans->payload_len); | |
135 memcpy(data + len, trans->payload, trans->payload_len); | |
136 len += trans->payload_len; | |
137 } | |
138 | |
139 msn_servconn_write(servconn, data, len); | |
140 | |
141 g_free(data); | |
142 } | |
143 | |
144 void | |
145 msn_cmdproc_send_quick(MsnCmdProc *cmdproc, const char *command, | |
146 const char *format, ...) | |
147 { | |
148 MsnServConn *servconn; | |
149 char *data; | |
8830
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
150 char *params = NULL; |
8810 | 151 va_list arg; |
152 size_t len; | |
153 | |
154 g_return_if_fail(cmdproc != NULL); | |
155 g_return_if_fail(command != NULL); | |
156 | |
157 servconn = cmdproc->servconn; | |
158 | |
9158
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
159 if (format != NULL) |
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
160 { |
8830
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
161 va_start(arg, format); |
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
162 params = g_strdup_vprintf(format, arg); |
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
163 va_end(arg); |
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
164 } |
8810 | 165 |
166 if (params != NULL) | |
167 data = g_strdup_printf("%s %s\r\n", command, params); | |
168 else | |
169 data = g_strdup_printf("%s\r\n", command); | |
170 | |
171 g_free(params); | |
172 | |
173 len = strlen(data); | |
174 | |
175 show_debug_cmd(cmdproc, FALSE, data); | |
176 | |
177 msn_servconn_write(servconn, data, len); | |
178 | |
179 g_free(data); | |
180 } | |
181 | |
182 void | |
183 msn_cmdproc_send(MsnCmdProc *cmdproc, const char *command, | |
184 const char *format, ...) | |
185 { | |
186 MsnTransaction *trans; | |
187 va_list arg; | |
188 | |
189 g_return_if_fail(cmdproc != NULL); | |
190 g_return_if_fail(command != NULL); | |
191 | |
192 trans = g_new0(MsnTransaction, 1); | |
193 | |
194 trans->command = g_strdup(command); | |
195 | |
9158
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
196 if (format != NULL) |
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
197 { |
8830
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
198 va_start(arg, format); |
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
199 trans->params = g_strdup_vprintf(format, arg); |
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
200 va_end(arg); |
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
201 } |
8810 | 202 |
203 msn_cmdproc_send_trans(cmdproc, trans); | |
204 } | |
205 | |
206 void | |
9158
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
207 msn_cmdproc_process_payload(MsnCmdProc *cmdproc, char *payload, |
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
208 int payload_len) |
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
209 { |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
210 MsnCommand *last; |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
211 |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
212 g_return_if_fail(cmdproc != NULL); |
9158
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
213 |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
214 last = cmdproc->last_cmd; |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
215 last->payload = g_memdup(payload, payload_len); |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
216 last->payload_len = payload_len; |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
217 |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
218 if (last->payload_cb != NULL) |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
219 last->payload_cb(cmdproc, last, payload, payload_len); |
9158
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
220 } |
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
221 |
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
222 void |
8810 | 223 msn_cmdproc_process_msg(MsnCmdProc *cmdproc, MsnMessage *msg) |
224 { | |
10345 | 225 MsnMsgTypeCb cb; |
8810 | 226 |
9881 | 227 if (msn_message_get_content_type(msg) == NULL) |
228 { | |
229 gaim_debug_misc("msn", "failed to find message content\n"); | |
230 return; | |
231 } | |
232 | |
8810 | 233 cb = g_hash_table_lookup(cmdproc->cbs_table->msgs, |
234 msn_message_get_content_type(msg)); | |
235 | |
236 if (cb == NULL) | |
237 { | |
9158
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
238 gaim_debug_warning("msn", "Unhandled content-type '%s'\n", |
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
239 msn_message_get_content_type(msg)); |
8810 | 240 |
241 return; | |
242 } | |
243 | |
244 cb(cmdproc, msg); | |
245 } | |
246 | |
247 void | |
248 msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) | |
249 { | |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
250 MsnTransCb cb = NULL; |
8810 | 251 MsnTransaction *trans = NULL; |
252 | |
253 if (cmd->trId) | |
254 trans = msn_history_find(cmdproc->history, cmd->trId); | |
255 | |
10225 | 256 if (trans != NULL) |
257 if (trans->timer) | |
258 gaim_timeout_remove(trans->timer); | |
259 | |
8810 | 260 if (g_ascii_isdigit(cmd->command[0])) |
261 { | |
262 if (trans != NULL) | |
263 { | |
264 MsnErrorCb error_cb = NULL; | |
265 int error; | |
266 | |
267 error = atoi(cmd->command); | |
10225 | 268 |
269 if (trans->error_cb != NULL) | |
270 error_cb = trans->error_cb; | |
271 | |
272 if (error_cb == NULL && cmdproc->cbs_table->errors != NULL) | |
8810 | 273 error_cb = g_hash_table_lookup(cmdproc->cbs_table->errors, trans->command); |
274 | |
275 if (error_cb != NULL) | |
10225 | 276 { |
8810 | 277 error_cb(cmdproc, trans, error); |
10225 | 278 } |
8810 | 279 else |
280 { | |
281 #if 1 | |
282 msn_error_handle(cmdproc->session, error); | |
283 #else | |
284 gaim_debug_warning("msn", "Unhandled error '%s'\n", | |
285 cmd->command); | |
286 #endif | |
287 } | |
288 | |
289 return; | |
290 } | |
291 } | |
292 | |
293 if (cmdproc->cbs_table->async != NULL) | |
294 cb = g_hash_table_lookup(cmdproc->cbs_table->async, cmd->command); | |
295 | |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
296 if (cb == NULL && trans != NULL) |
8810 | 297 { |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
298 cmd->trans = trans; |
8810 | 299 |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
300 if (trans->callbacks != NULL) |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
301 cb = g_hash_table_lookup(trans->callbacks, cmd->command); |
8810 | 302 } |
303 | |
10043 | 304 if (cb == NULL && cmdproc->cbs_table->fallback != NULL) |
305 cb = g_hash_table_lookup(cmdproc->cbs_table->fallback, cmd->command); | |
306 | |
8810 | 307 if (cb != NULL) |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
308 { |
8810 | 309 cb(cmdproc, cmd); |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
310 } |
8810 | 311 else |
312 { | |
313 gaim_debug_warning("msn", "Unhandled command '%s'\n", | |
9158
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
314 cmd->command); |
8810 | 315 } |
316 | |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
317 #if 1 |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
318 /* TODO this is really ugly */ |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
319 /* Since commands have not stored payload and we need it for pendent |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
320 * commands at the time we process again the same command we will try |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
321 * to read again the payload of payload_len size but we will actually |
10310 | 322 * read sometime else, and reading from server synchronization goes to |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
323 * hell. */ |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
324 /* Now we store the payload in the command when we queue them :D */ |
8810 | 325 |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
326 if (trans != NULL && trans->pendent_cmd != NULL) |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
327 if (cmdproc->ready) |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
328 msn_transaction_unqueue_cmd(trans, cmdproc); |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
329 #endif |
8810 | 330 } |
331 | |
332 void | |
333 msn_cmdproc_process_cmd_text(MsnCmdProc *cmdproc, const char *command) | |
334 { | |
335 show_debug_cmd(cmdproc, TRUE, command); | |
336 | |
337 if (cmdproc->last_cmd != NULL) | |
338 msn_command_destroy(cmdproc->last_cmd); | |
339 | |
340 cmdproc->last_cmd = msn_command_from_string(command); | |
341 | |
342 msn_cmdproc_process_cmd(cmdproc, cmdproc->last_cmd); | |
343 } | |
344 | |
345 void | |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
346 msn_cmdproc_show_error(MsnCmdProc *cmdproc, int error) |
8810 | 347 { |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
348 GaimConnection *gc = |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
349 gaim_account_get_connection(cmdproc->session->account); |
8810 | 350 |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
351 char *tmp; |
8810 | 352 |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
353 tmp = NULL; |
8810 | 354 |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
355 switch (error) |
8810 | 356 { |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
357 case MSN_ERROR_MISC: |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
358 tmp = _("Miscellaneous error"); break; |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
359 case MSN_ERROR_SIGNOTHER: |
9641 | 360 gc->wants_to_die = TRUE; |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
361 tmp = _("You have signed on from another location."); break; |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
362 case MSN_ERROR_SERVDOWN: |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
363 tmp = _("The MSN servers are going down temporarily."); break; |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
364 default: |
8810 | 365 break; |
366 } | |
367 | |
9193
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
368 if (tmp != NULL) |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
369 { |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
370 gaim_connection_error(gc, tmp); |
502707ca1836
[gaim-migrate @ 9988]
Christian Hammond <chipx86@chipx86.com>
parents:
9158
diff
changeset
|
371 } |
8810 | 372 } |