Mercurial > pidgin.yaz
annotate src/protocols/silc/ops.c @ 12167:5851a9219bc7
[gaim-migrate @ 14468]
Some SILC fixes from Pekka for whiteboard support, preferences, and
documentation. Let's hear a big thanks to Pekka for keeping up with
this stuff!
Enclosed patch fixes couple crashbugs from the SILC whiteboard code,
fixes the preferences (which are not used anymore in Gaim) by
eliminating some of the old preferences and moving some of the
preferences to account options, and introduces Create SILC Key Pair
protocol action which can be used to generate new SILC key pair from
Gaim.
committer: Tailor Script <tailor@pidgin.im>
author | Ethan Blanton <elb@pidgin.im> |
---|---|
date | Sun, 20 Nov 2005 00:59:36 +0000 |
parents | d5daff460913 |
children | 029802981b81 |
rev | line source |
---|---|
8849 | 1 /* |
2 | |
3 silcgaim_ops.c | |
4 | |
5 Author: Pekka Riikonen <priikone@silcnet.org> | |
6 | |
7 Copyright (C) 2004 Pekka Riikonen | |
8 | |
9 This program is free software; you can redistribute it and/or modify | |
10 it under the terms of the GNU General Public License as published by | |
11 the Free Software Foundation; version 2 of the License. | |
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 */ | |
19 | |
20 #include "silcincludes.h" | |
21 #include "silcclient.h" | |
22 #include "silcgaim.h" | |
12058 | 23 #include "wb.h" |
8849 | 24 |
25 /* Message sent to the application by library. `conn' associates the | |
26 message to a specific connection. `conn', however, may be NULL. | |
27 The `type' indicates the type of the message sent by the library. | |
28 The application can for example filter the message according the | |
29 type. */ | |
30 | |
31 static void | |
32 silc_say(SilcClient client, SilcClientConnection conn, | |
33 SilcClientMessageType type, char *msg, ...) | |
34 { | |
35 /* Nothing */ | |
36 } | |
37 | |
38 | |
39 /* Message for a channel. The `sender' is the sender of the message | |
40 The `channel' is the channel. The `message' is the message. Note | |
41 that `message' maybe NULL. The `flags' indicates message flags | |
42 and it is used to determine how the message can be interpreted | |
43 (like it may tell the message is multimedia message). */ | |
44 | |
45 static void | |
46 silc_channel_message(SilcClient client, SilcClientConnection conn, | |
47 SilcClientEntry sender, SilcChannelEntry channel, | |
48 SilcMessagePayload payload, SilcChannelPrivateKey key, | |
49 SilcMessageFlags flags, const unsigned char *message, | |
50 SilcUInt32 message_len) | |
51 { | |
52 GaimConnection *gc = client->application; | |
53 SilcGaim sg = gc->proto_data; | |
54 GaimConversation *convo = NULL; | |
9359 | 55 char *msg, *tmp; |
8849 | 56 |
57 if (!message) | |
58 return; | |
59 | |
60 if (key) { | |
61 GList *l; | |
62 SilcGaimPrvgrp prv; | |
63 | |
64 for (l = sg->grps; l; l = l->next) | |
65 if (((SilcGaimPrvgrp)l->data)->key == key) { | |
66 prv = l->data; | |
11338 | 67 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 68 prv->channel, sg->account); |
8849 | 69 break; |
70 } | |
71 } | |
72 if (!convo) | |
11338 | 73 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 74 channel->channel_name, sg->account); |
8849 | 75 if (!convo) |
76 return; | |
77 | |
78 if (flags & SILC_MESSAGE_FLAG_SIGNED && | |
12167 | 79 gaim_account_get_bool(sg->account, "sign-verify", FALSE)) { |
8849 | 80 /* XXX */ |
81 } | |
82 | |
83 if (flags & SILC_MESSAGE_FLAG_DATA) { | |
12058 | 84 char type[128], enc[128]; |
85 unsigned char *data; | |
86 SilcUInt32 data_len; | |
87 | |
88 memset(type, 0, sizeof(type)); | |
89 memset(enc, 0, sizeof(enc)); | |
90 | |
91 if (!silc_mime_parse(message, message_len, NULL, 0, | |
92 type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data, | |
93 &data_len)) | |
94 return; | |
95 | |
96 if (!strcmp(type, "application/x-wb") && | |
12167 | 97 !strcmp(enc, "binary") && |
98 !gaim_account_get_bool(sg->account, "block-wb", FALSE)) | |
12058 | 99 silcgaim_wb_receive_ch(client, conn, sender, channel, |
100 payload, flags, data, data_len); | |
101 | |
8849 | 102 return; |
103 } | |
104 | |
105 if (flags & SILC_MESSAGE_FLAG_ACTION) { | |
9353 | 106 msg = g_strdup_printf("/me %s", |
8849 | 107 (const char *)message); |
108 if (!msg) | |
109 return; | |
110 | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10589
diff
changeset
|
111 tmp = g_markup_escape_text(msg, -1); |
8849 | 112 /* Send to Gaim */ |
9353 | 113 serv_got_chat_in(gc, gaim_conv_chat_get_id(GAIM_CONV_CHAT(convo)), |
114 sender->nickname ? | |
115 sender->nickname : "<unknown>", 0, | |
9359 | 116 tmp, time(NULL)); |
117 g_free(tmp); | |
8849 | 118 g_free(msg); |
119 return; | |
120 } | |
121 | |
122 if (flags & SILC_MESSAGE_FLAG_NOTICE) { | |
123 msg = g_strdup_printf("(notice) <I>%s</I> %s", | |
124 sender->nickname ? | |
125 sender->nickname : "<unknown>", | |
126 (const char *)message); | |
127 if (!msg) | |
128 return; | |
129 | |
130 /* Send to Gaim */ | |
131 gaim_conversation_write(convo, NULL, (const char *)msg, | |
132 GAIM_MESSAGE_SYSTEM, time(NULL)); | |
133 g_free(msg); | |
134 return; | |
135 } | |
136 | |
9359 | 137 if (flags & SILC_MESSAGE_FLAG_UTF8) { |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10589
diff
changeset
|
138 tmp = g_markup_escape_text((const char *)message, -1); |
8849 | 139 /* Send to Gaim */ |
140 serv_got_chat_in(gc, gaim_conv_chat_get_id(GAIM_CONV_CHAT(convo)), | |
141 sender->nickname ? | |
142 sender->nickname : "<unknown>", 0, | |
9359 | 143 tmp, time(NULL)); |
144 g_free(tmp); | |
145 } | |
8849 | 146 } |
147 | |
148 | |
149 /* Private message to the client. The `sender' is the sender of the | |
150 message. The message is `message'and maybe NULL. The `flags' | |
151 indicates message flags and it is used to determine how the message | |
152 can be interpreted (like it may tell the message is multimedia | |
153 message). */ | |
154 | |
155 static void | |
156 silc_private_message(SilcClient client, SilcClientConnection conn, | |
157 SilcClientEntry sender, SilcMessagePayload payload, | |
158 SilcMessageFlags flags, const unsigned char *message, | |
159 SilcUInt32 message_len) | |
160 { | |
161 GaimConnection *gc = client->application; | |
162 SilcGaim sg = gc->proto_data; | |
163 GaimConversation *convo = NULL; | |
9359 | 164 char *msg, *tmp; |
8849 | 165 |
166 if (!message) | |
167 return; | |
168 | |
169 if (sender->nickname) | |
11338 | 170 /* XXX - Should this be GAIM_CONV_TYPE_IM? */ |
171 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_ANY, | |
10246 | 172 sender->nickname, sg->account); |
8849 | 173 |
174 if (flags & SILC_MESSAGE_FLAG_SIGNED && | |
12167 | 175 gaim_account_get_bool(sg->account, "sign-verify", FALSE)) { |
8849 | 176 /* XXX */ |
177 } | |
178 | |
179 if (flags & SILC_MESSAGE_FLAG_DATA) { | |
12058 | 180 char type[128], enc[128]; |
181 unsigned char *data; | |
182 SilcUInt32 data_len; | |
183 | |
184 memset(type, 0, sizeof(type)); | |
185 memset(enc, 0, sizeof(enc)); | |
186 | |
187 if (!silc_mime_parse(message, message_len, NULL, 0, | |
188 type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data, | |
189 &data_len)) | |
190 return; | |
191 | |
192 if (!strcmp(type, "application/x-wb") && | |
12167 | 193 !strcmp(enc, "binary") && |
194 !gaim_account_get_bool(sg->account, "block-wb", FALSE)) | |
12058 | 195 silcgaim_wb_receive(client, conn, sender, payload, |
196 flags, data, data_len); | |
197 | |
8849 | 198 return; |
199 } | |
200 | |
201 if (flags & SILC_MESSAGE_FLAG_ACTION && convo) { | |
9353 | 202 msg = g_strdup_printf("/me %s", |
8849 | 203 (const char *)message); |
204 if (!msg) | |
205 return; | |
206 | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10589
diff
changeset
|
207 tmp = g_markup_escape_text(msg, -1); |
8849 | 208 /* Send to Gaim */ |
9353 | 209 serv_got_im(gc, sender->nickname ? |
210 sender->nickname : "<unknown>", | |
9359 | 211 tmp, 0, time(NULL)); |
8849 | 212 g_free(msg); |
9359 | 213 g_free(tmp); |
8849 | 214 return; |
215 } | |
216 | |
217 if (flags & SILC_MESSAGE_FLAG_NOTICE && convo) { | |
218 msg = g_strdup_printf("(notice) <I>%s</I> %s", | |
219 sender->nickname ? | |
220 sender->nickname : "<unknown>", | |
221 (const char *)message); | |
222 if (!msg) | |
223 return; | |
224 | |
225 /* Send to Gaim */ | |
226 gaim_conversation_write(convo, NULL, (const char *)msg, | |
227 GAIM_MESSAGE_SYSTEM, time(NULL)); | |
228 g_free(msg); | |
229 return; | |
230 } | |
231 | |
9359 | 232 if (flags & SILC_MESSAGE_FLAG_UTF8) { |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10589
diff
changeset
|
233 tmp = g_markup_escape_text((const char *)message, -1); |
8849 | 234 /* Send to Gaim */ |
235 serv_got_im(gc, sender->nickname ? | |
236 sender->nickname : "<unknown>", | |
9359 | 237 tmp, 0, time(NULL)); |
238 g_free(tmp); | |
239 } | |
8849 | 240 } |
241 | |
242 | |
243 /* Notify message to the client. The notify arguments are sent in the | |
244 same order as servers sends them. The arguments are same as received | |
245 from the server except for ID's. If ID is received application receives | |
246 the corresponding entry to the ID. For example, if Client ID is received | |
247 application receives SilcClientEntry. Also, if the notify type is | |
248 for channel the channel entry is sent to application (even if server | |
249 does not send it because client library gets the channel entry from | |
250 the Channel ID in the packet's header). */ | |
251 | |
252 static void | |
253 silc_notify(SilcClient client, SilcClientConnection conn, | |
254 SilcNotifyType type, ...) | |
255 { | |
256 va_list va; | |
257 GaimConnection *gc = client->application; | |
258 SilcGaim sg = gc->proto_data; | |
259 GaimConversation *convo; | |
260 SilcClientEntry client_entry, client_entry2; | |
261 SilcChannelEntry channel; | |
262 SilcServerEntry server_entry; | |
263 SilcIdType idtype; | |
264 void *entry; | |
265 SilcUInt32 mode; | |
266 SilcHashTableList htl; | |
267 SilcChannelUser chu; | |
268 char buf[512], buf2[512], *tmp, *name; | |
269 SilcBuffer buffer; | |
270 SilcNotifyType notify; | |
271 GaimBuddy *b; | |
272 int i; | |
273 | |
274 va_start(va, type); | |
275 memset(buf, 0, sizeof(buf)); | |
276 | |
277 switch (type) { | |
278 | |
279 case SILC_NOTIFY_TYPE_NONE: | |
280 break; | |
281 | |
282 case SILC_NOTIFY_TYPE_INVITE: | |
283 { | |
284 GHashTable *components; | |
285 channel = va_arg(va, SilcChannelEntry); | |
286 name = va_arg(va, char *); | |
287 client_entry = va_arg(va, SilcClientEntry); | |
288 | |
289 components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | |
9353 | 290 g_hash_table_insert(components, strdup("channel"), strdup(name)); |
291 serv_got_chat_invite(gc, name, client_entry->nickname, NULL, components); | |
8849 | 292 } |
293 break; | |
294 | |
295 case SILC_NOTIFY_TYPE_JOIN: | |
296 client_entry = va_arg(va, SilcClientEntry); | |
297 channel = va_arg(va, SilcChannelEntry); | |
298 | |
299 /* If we joined channel, do nothing */ | |
300 if (client_entry == conn->local_entry) | |
301 break; | |
302 | |
11338 | 303 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 304 channel->channel_name, sg->account); |
8849 | 305 if (!convo) |
306 break; | |
307 | |
308 /* Join user to channel */ | |
8891 | 309 g_snprintf(buf, sizeof(buf), "%s@%s", |
8849 | 310 client_entry->username, client_entry->hostname); |
311 gaim_conv_chat_add_user(GAIM_CONV_CHAT(convo), | |
9846 | 312 g_strdup(client_entry->nickname), buf, GAIM_CBFLAGS_NONE, TRUE); |
8849 | 313 |
314 break; | |
315 | |
316 case SILC_NOTIFY_TYPE_LEAVE: | |
317 client_entry = va_arg(va, SilcClientEntry); | |
318 channel = va_arg(va, SilcChannelEntry); | |
319 | |
11338 | 320 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 321 channel->channel_name, sg->account); |
8849 | 322 if (!convo) |
323 break; | |
324 | |
325 /* Remove user from channel */ | |
326 gaim_conv_chat_remove_user(GAIM_CONV_CHAT(convo), | |
327 client_entry->nickname, NULL); | |
328 | |
329 break; | |
330 | |
331 case SILC_NOTIFY_TYPE_SIGNOFF: | |
332 client_entry = va_arg(va, SilcClientEntry); | |
333 tmp = va_arg(va, char *); | |
334 | |
335 if (!client_entry->nickname) | |
336 break; | |
337 | |
338 /* Remove from all channels */ | |
339 silc_hash_table_list(client_entry->channels, &htl); | |
340 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
11338 | 341 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 342 chu->channel->channel_name, sg->account); |
8849 | 343 if (!convo) |
344 continue; | |
345 gaim_conv_chat_remove_user(GAIM_CONV_CHAT(convo), | |
346 client_entry->nickname, | |
347 tmp); | |
348 } | |
349 silc_hash_table_list_reset(&htl); | |
350 | |
351 break; | |
352 | |
353 case SILC_NOTIFY_TYPE_TOPIC_SET: | |
9762 | 354 { |
355 char *esc, *tmp2; | |
356 idtype = va_arg(va, int); | |
357 entry = va_arg(va, void *); | |
358 tmp = va_arg(va, char *); | |
359 channel = va_arg(va, SilcChannelEntry); | |
360 | |
11338 | 361 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 362 channel->channel_name, sg->account); |
9762 | 363 if (!convo) |
364 break; | |
365 | |
366 if (!tmp) | |
367 break; | |
368 | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10589
diff
changeset
|
369 esc = g_markup_escape_text(tmp, -1); |
9762 | 370 tmp2 = gaim_markup_linkify(esc); |
371 g_free(esc); | |
8849 | 372 |
9762 | 373 if (idtype == SILC_ID_CLIENT) { |
374 client_entry = (SilcClientEntry)entry; | |
375 g_snprintf(buf, sizeof(buf), | |
376 _("%s has changed the topic of <I>%s</I> to: %s"), | |
377 client_entry->nickname, channel->channel_name, tmp2); | |
378 gaim_conv_chat_write(GAIM_CONV_CHAT(convo), client_entry->nickname, | |
379 buf, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
380 gaim_conv_chat_set_topic(GAIM_CONV_CHAT(convo), | |
381 client_entry->nickname, tmp); | |
382 } else if (idtype == SILC_ID_SERVER) { | |
383 server_entry = (SilcServerEntry)entry; | |
384 g_snprintf(buf, sizeof(buf), | |
385 _("%s has changed the topic of <I>%s</I> to: %s"), | |
386 server_entry->server_name, channel->channel_name, tmp2); | |
387 gaim_conv_chat_write(GAIM_CONV_CHAT(convo), server_entry->server_name, | |
388 buf, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
389 gaim_conv_chat_set_topic(GAIM_CONV_CHAT(convo), | |
390 server_entry->server_name, tmp); | |
391 } else if (idtype == SILC_ID_CHANNEL) { | |
392 channel = (SilcChannelEntry)entry; | |
393 g_snprintf(buf, sizeof(buf), | |
394 _("%s has changed the topic of <I>%s</I> to: %s"), | |
395 channel->channel_name, channel->channel_name, tmp2); | |
396 gaim_conv_chat_write(GAIM_CONV_CHAT(convo), channel->channel_name, | |
397 buf, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
398 gaim_conv_chat_set_topic(GAIM_CONV_CHAT(convo), | |
399 channel->channel_name, tmp); | |
400 } else { | |
401 gaim_conv_chat_set_topic(GAIM_CONV_CHAT(convo), NULL, tmp); | |
402 } | |
8849 | 403 |
9762 | 404 g_free(tmp2); |
405 | |
8849 | 406 break; |
407 | |
408 } | |
409 case SILC_NOTIFY_TYPE_NICK_CHANGE: | |
410 client_entry = va_arg(va, SilcClientEntry); | |
411 client_entry2 = va_arg(va, SilcClientEntry); | |
412 | |
413 if (!strcmp(client_entry->nickname, client_entry2->nickname)) | |
414 break; | |
415 | |
416 /* Change nick on all channels */ | |
417 silc_hash_table_list(client_entry2->channels, &htl); | |
418 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
11338 | 419 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 420 chu->channel->channel_name, sg->account); |
8849 | 421 if (!convo) |
422 continue; | |
9628 | 423 if (gaim_conv_chat_find_user(GAIM_CONV_CHAT(convo), client_entry->nickname)) |
424 gaim_conv_chat_rename_user(GAIM_CONV_CHAT(convo), | |
425 client_entry->nickname, | |
426 client_entry2->nickname); | |
8849 | 427 } |
428 silc_hash_table_list_reset(&htl); | |
429 | |
430 break; | |
431 | |
432 case SILC_NOTIFY_TYPE_CMODE_CHANGE: | |
433 idtype = va_arg(va, int); | |
434 entry = va_arg(va, void *); | |
435 mode = va_arg(va, SilcUInt32); | |
436 (void)va_arg(va, char *); | |
437 (void)va_arg(va, char *); | |
438 (void)va_arg(va, char *); | |
439 (void)va_arg(va, SilcPublicKey); | |
440 buffer = va_arg(va, SilcBuffer); | |
441 channel = va_arg(va, SilcChannelEntry); | |
442 | |
11338 | 443 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 444 channel->channel_name, sg->account); |
8849 | 445 if (!convo) |
446 break; | |
447 | |
448 if (idtype == SILC_ID_CLIENT) | |
449 name = ((SilcClientEntry)entry)->nickname; | |
450 else if (idtype == SILC_ID_SERVER) | |
451 name = ((SilcServerEntry)entry)->server_name; | |
452 else | |
453 name = ((SilcChannelEntry)entry)->channel_name; | |
454 if (!name) | |
455 break; | |
456 | |
457 if (mode) { | |
458 silcgaim_get_chmode_string(mode, buf2, sizeof(buf2)); | |
459 g_snprintf(buf, sizeof(buf), | |
460 _("<I>%s</I> set channel <I>%s</I> modes to: %s"), name, | |
461 channel->channel_name, buf2); | |
462 } else { | |
463 g_snprintf(buf, sizeof(buf), | |
464 _("<I>%s</I> removed all channel <I>%s</I> modes"), name, | |
465 channel->channel_name); | |
466 } | |
467 gaim_conv_chat_write(GAIM_CONV_CHAT(convo), channel->channel_name, | |
468 buf, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
469 break; | |
470 | |
471 case SILC_NOTIFY_TYPE_CUMODE_CHANGE: | |
9554 | 472 { |
473 GaimConvChatBuddyFlags flags = GAIM_CBFLAGS_NONE; | |
474 idtype = va_arg(va, int); | |
475 entry = va_arg(va, void *); | |
476 mode = va_arg(va, SilcUInt32); | |
477 client_entry2 = va_arg(va, SilcClientEntry); | |
478 channel = va_arg(va, SilcChannelEntry); | |
8849 | 479 |
11338 | 480 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 481 channel->channel_name, sg->account); |
9554 | 482 if (!convo) |
483 break; | |
8849 | 484 |
9554 | 485 if (idtype == SILC_ID_CLIENT) |
486 name = ((SilcClientEntry)entry)->nickname; | |
487 else if (idtype == SILC_ID_SERVER) | |
488 name = ((SilcServerEntry)entry)->server_name; | |
489 else | |
490 name = ((SilcChannelEntry)entry)->channel_name; | |
491 if (!name) | |
492 break; | |
8849 | 493 |
9554 | 494 if (mode) { |
495 silcgaim_get_chumode_string(mode, buf2, sizeof(buf2)); | |
496 g_snprintf(buf, sizeof(buf), | |
497 _("<I>%s</I> set <I>%s's</I> modes to: %s"), name, | |
498 client_entry2->nickname, buf2); | |
499 if (mode & SILC_CHANNEL_UMODE_CHANFO) | |
500 flags |= GAIM_CBFLAGS_FOUNDER; | |
501 if (mode & SILC_CHANNEL_UMODE_CHANOP) | |
502 flags |= GAIM_CBFLAGS_OP; | |
503 } else { | |
504 g_snprintf(buf, sizeof(buf), | |
505 _("<I>%s</I> removed all <I>%s's</I> modes"), name, | |
506 client_entry2->nickname); | |
507 } | |
508 gaim_conv_chat_write(GAIM_CONV_CHAT(convo), channel->channel_name, | |
509 buf, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
510 gaim_conv_chat_user_set_flags(GAIM_CONV_CHAT(convo), client_entry2->nickname, flags); | |
511 break; | |
8849 | 512 } |
513 | |
514 case SILC_NOTIFY_TYPE_MOTD: | |
515 tmp = va_arg(va, char *); | |
516 silc_free(sg->motd); | |
517 sg->motd = silc_memdup(tmp, strlen(tmp)); | |
518 break; | |
519 | |
520 case SILC_NOTIFY_TYPE_KICKED: | |
521 client_entry = va_arg(va, SilcClientEntry); | |
522 tmp = va_arg(va, char *); | |
523 client_entry2 = va_arg(va, SilcClientEntry); | |
524 channel = va_arg(va, SilcChannelEntry); | |
525 | |
11338 | 526 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 527 channel->channel_name, sg->account); |
8849 | 528 if (!convo) |
529 break; | |
530 | |
531 if (client_entry == conn->local_entry) { | |
532 /* Remove us from channel */ | |
533 g_snprintf(buf, sizeof(buf), | |
534 _("You have been kicked off <I>%s</I> by <I>%s</I> (%s)"), | |
535 channel->channel_name, client_entry2->nickname, | |
536 tmp ? tmp : ""); | |
537 gaim_conv_chat_write(GAIM_CONV_CHAT(convo), client_entry->nickname, | |
538 buf, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
539 serv_got_chat_left(gc, gaim_conv_chat_get_id(GAIM_CONV_CHAT(convo))); | |
540 } else { | |
541 /* Remove user from channel */ | |
542 g_snprintf(buf, sizeof(buf), ("Kicked by %s (%s)"), | |
543 client_entry2->nickname, tmp ? tmp : ""); | |
9353 | 544 gaim_conv_chat_remove_user(GAIM_CONV_CHAT(convo), |
8849 | 545 client_entry->nickname, |
546 buf); | |
547 } | |
548 | |
549 break; | |
550 | |
551 case SILC_NOTIFY_TYPE_KILLED: | |
552 client_entry = va_arg(va, SilcClientEntry); | |
553 tmp = va_arg(va, char *); | |
554 idtype = va_arg(va, int); | |
555 entry = va_arg(va, SilcClientEntry); | |
556 | |
557 if (!client_entry->nickname) | |
558 break; | |
559 | |
560 if (client_entry == conn->local_entry) { | |
561 if (idtype == SILC_ID_CLIENT) { | |
562 client_entry2 = (SilcClientEntry)entry; | |
563 g_snprintf(buf, sizeof(buf), | |
564 _("You have been killed by %s (%s)"), | |
565 client_entry2->nickname, tmp ? tmp : ""); | |
566 } else if (idtype == SILC_ID_SERVER) { | |
567 server_entry = (SilcServerEntry)entry; | |
568 g_snprintf(buf, sizeof(buf), | |
569 _("You have been killed by %s (%s)"), | |
570 server_entry->server_name, tmp ? tmp : ""); | |
571 } else if (idtype == SILC_ID_CHANNEL) { | |
572 channel = (SilcChannelEntry)entry; | |
573 g_snprintf(buf, sizeof(buf), | |
574 _("You have been killed by %s (%s)"), | |
575 channel->channel_name, tmp ? tmp : ""); | |
576 } | |
577 | |
578 /* Remove us from all channels */ | |
579 silc_hash_table_list(client_entry->channels, &htl); | |
580 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
11338 | 581 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 582 chu->channel->channel_name, sg->account); |
8849 | 583 if (!convo) |
584 continue; | |
585 gaim_conv_chat_write(GAIM_CONV_CHAT(convo), client_entry->nickname, | |
586 buf, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
587 serv_got_chat_left(gc, gaim_conv_chat_get_id(GAIM_CONV_CHAT(convo))); | |
588 } | |
589 silc_hash_table_list_reset(&htl); | |
590 | |
591 } else { | |
592 if (idtype == SILC_ID_CLIENT) { | |
593 client_entry2 = (SilcClientEntry)entry; | |
594 g_snprintf(buf, sizeof(buf), | |
595 _("Killed by %s (%s)"), | |
596 client_entry2->nickname, tmp ? tmp : ""); | |
597 } else if (idtype == SILC_ID_SERVER) { | |
598 server_entry = (SilcServerEntry)entry; | |
599 g_snprintf(buf, sizeof(buf), | |
600 _("Killed by %s (%s)"), | |
601 server_entry->server_name, tmp ? tmp : ""); | |
602 } else if (idtype == SILC_ID_CHANNEL) { | |
603 channel = (SilcChannelEntry)entry; | |
604 g_snprintf(buf, sizeof(buf), | |
605 _("Killed by %s (%s)"), | |
606 channel->channel_name, tmp ? tmp : ""); | |
607 } | |
608 | |
609 /* Remove user from all channels */ | |
610 silc_hash_table_list(client_entry->channels, &htl); | |
611 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
11338 | 612 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 613 chu->channel->channel_name, sg->account); |
8849 | 614 if (!convo) |
615 continue; | |
616 gaim_conv_chat_remove_user(GAIM_CONV_CHAT(convo), | |
617 client_entry->nickname, tmp); | |
618 } | |
619 silc_hash_table_list_reset(&htl); | |
620 } | |
621 | |
622 break; | |
623 | |
624 case SILC_NOTIFY_TYPE_CHANNEL_CHANGE: | |
625 break; | |
626 | |
627 case SILC_NOTIFY_TYPE_SERVER_SIGNOFF: | |
628 { | |
629 int i; | |
630 SilcClientEntry *clients; | |
631 SilcUInt32 clients_count; | |
632 | |
633 (void)va_arg(va, void *); | |
634 clients = va_arg(va, SilcClientEntry *); | |
635 clients_count = va_arg(va, SilcUInt32); | |
636 | |
637 for (i = 0; i < clients_count; i++) { | |
638 if (!clients[i]->nickname) | |
639 break; | |
640 | |
641 /* Remove from all channels */ | |
642 silc_hash_table_list(clients[i]->channels, &htl); | |
643 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
644 convo = | |
11338 | 645 gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 646 chu->channel->channel_name, sg->account); |
8849 | 647 if (!convo) |
648 continue; | |
649 gaim_conv_chat_remove_user(GAIM_CONV_CHAT(convo), | |
650 clients[i]->nickname, | |
651 _("Server signoff")); | |
652 } | |
653 silc_hash_table_list_reset(&htl); | |
654 } | |
655 } | |
656 break; | |
657 | |
658 case SILC_NOTIFY_TYPE_ERROR: | |
659 { | |
660 SilcStatus error = va_arg(va, int); | |
661 gaim_notify_error(gc, "Error Notify", | |
662 silc_get_status_message(error), | |
663 NULL); | |
664 } | |
665 break; | |
666 | |
667 case SILC_NOTIFY_TYPE_WATCH: | |
668 { | |
669 SilcPublicKey public_key; | |
670 unsigned char *pk; | |
671 SilcUInt32 pk_len; | |
672 char *fingerprint; | |
673 | |
674 client_entry = va_arg(va, SilcClientEntry); | |
675 (void)va_arg(va, char *); | |
676 mode = va_arg(va, SilcUInt32); | |
677 notify = va_arg(va, int); | |
678 public_key = va_arg(va, SilcPublicKey); | |
679 | |
680 b = NULL; | |
681 if (public_key) { | |
682 GaimBlistNode *gnode, *cnode, *bnode; | |
683 const char *f; | |
684 | |
685 pk = silc_pkcs_public_key_encode(public_key, &pk_len); | |
686 if (!pk) | |
687 break; | |
688 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); | |
689 for (i = 0; i < strlen(fingerprint); i++) | |
690 if (fingerprint[i] == ' ') | |
691 fingerprint[i] = '_'; | |
692 g_snprintf(buf, sizeof(buf) - 1, | |
693 "%s" G_DIR_SEPARATOR_S "clientkeys" | |
694 G_DIR_SEPARATOR_S "clientkey_%s.pub", | |
695 silcgaim_silcdir(), fingerprint); | |
696 silc_free(fingerprint); | |
697 silc_free(pk); | |
698 | |
699 /* Find buddy by associated public key */ | |
700 for (gnode = gaim_get_blist()->root; gnode; | |
701 gnode = gnode->next) { | |
702 if (!GAIM_BLIST_NODE_IS_GROUP(gnode)) | |
703 continue; | |
704 for (cnode = gnode->child; cnode; cnode = cnode->next) { | |
705 if( !GAIM_BLIST_NODE_IS_CONTACT(cnode)) | |
706 continue; | |
707 for (bnode = cnode->child; bnode; | |
708 bnode = bnode->next) { | |
709 if (!GAIM_BLIST_NODE_IS_BUDDY(bnode)) | |
710 continue; | |
711 b = (GaimBuddy *)bnode; | |
712 if (b->account != gc->account) | |
713 continue; | |
714 f = gaim_blist_node_get_string(bnode, "public-key"); | |
715 if (!strcmp(f, buf)) | |
716 goto cont; | |
717 } | |
718 } | |
719 } | |
720 } | |
721 cont: | |
722 if (!b) { | |
723 /* Find buddy by nickname */ | |
724 b = gaim_find_buddy(sg->account, client_entry->nickname); | |
725 if (!b) { | |
9272 | 726 gaim_debug_warning("silc", "WATCH for %s, unknown buddy", |
8849 | 727 client_entry->nickname); |
728 break; | |
729 } | |
730 } | |
731 | |
732 silc_free(b->proto_data); | |
733 b->proto_data = silc_memdup(client_entry->id, | |
734 sizeof(*client_entry->id)); | |
735 if (notify == SILC_NOTIFY_TYPE_NICK_CHANGE) { | |
736 break; | |
737 } else if (notify == SILC_NOTIFY_TYPE_UMODE_CHANGE) { | |
738 /* See if client was away and is now present */ | |
739 if (!(mode & (SILC_UMODE_GONE | SILC_UMODE_INDISPOSED | | |
740 SILC_UMODE_BUSY | SILC_UMODE_PAGE | | |
741 SILC_UMODE_DETACHED)) && | |
742 (client_entry->mode & SILC_UMODE_GONE || | |
743 client_entry->mode & SILC_UMODE_INDISPOSED || | |
744 client_entry->mode & SILC_UMODE_BUSY || | |
745 client_entry->mode & SILC_UMODE_PAGE || | |
746 client_entry->mode & SILC_UMODE_DETACHED)) { | |
747 client_entry->mode = mode; | |
11522 | 748 gaim_prpl_got_user_status(gaim_buddy_get_account(b), gaim_buddy_get_name(b), SILCGAIM_STATUS_ID_AVAILABLE, NULL); |
8849 | 749 } |
750 else if ((mode & SILC_UMODE_GONE) || | |
751 (mode & SILC_UMODE_INDISPOSED) || | |
752 (mode & SILC_UMODE_BUSY) || | |
753 (mode & SILC_UMODE_PAGE) || | |
754 (mode & SILC_UMODE_DETACHED)) { | |
755 client_entry->mode = mode; | |
10050 | 756 gaim_prpl_got_user_status(gaim_buddy_get_account(b), gaim_buddy_get_name(b), SILCGAIM_STATUS_ID_OFFLINE, NULL); |
8849 | 757 } |
758 } else if (notify == SILC_NOTIFY_TYPE_SIGNOFF || | |
759 notify == SILC_NOTIFY_TYPE_SERVER_SIGNOFF || | |
760 notify == SILC_NOTIFY_TYPE_KILLED) { | |
761 client_entry->mode = mode; | |
10050 | 762 gaim_prpl_got_user_status(gaim_buddy_get_account(b), gaim_buddy_get_name(b), SILCGAIM_STATUS_ID_OFFLINE, NULL); |
8849 | 763 } else if (notify == SILC_NOTIFY_TYPE_NONE) { |
764 client_entry->mode = mode; | |
11522 | 765 gaim_prpl_got_user_status(gaim_buddy_get_account(b), gaim_buddy_get_name(b), SILCGAIM_STATUS_ID_AVAILABLE, NULL); |
8849 | 766 } |
767 } | |
768 break; | |
769 | |
770 default: | |
9353 | 771 gaim_debug_info("silc", "Unhandled notification: %d\n", type); |
8849 | 772 break; |
773 } | |
774 | |
775 va_end(va); | |
776 } | |
777 | |
778 | |
779 /* Command handler. This function is called always in the command function. | |
780 If error occurs it will be called as well. `conn' is the associated | |
781 client connection. `cmd_context' is the command context that was | |
782 originally sent to the command. `success' is FALSE if error occurred | |
783 during command. `command' is the command being processed. It must be | |
784 noted that this is not reply from server. This is merely called just | |
785 after application has called the command. Just to tell application | |
786 that the command really was processed. */ | |
787 | |
788 static void | |
789 silc_command(SilcClient client, SilcClientConnection conn, | |
790 SilcClientCommandContext cmd_context, bool success, | |
791 SilcCommand command, SilcStatus status) | |
792 { | |
793 GaimConnection *gc = client->application; | |
794 SilcGaim sg = gc->proto_data; | |
795 | |
796 switch (command) { | |
797 | |
798 case SILC_COMMAND_CMODE: | |
799 if (cmd_context->argc == 3 && | |
11488 | 800 !strcmp((char *)cmd_context->argv[2], "+C")) |
8849 | 801 sg->chpk = TRUE; |
802 else | |
803 sg->chpk = FALSE; | |
804 break; | |
805 | |
806 default: | |
807 break; | |
808 } | |
809 } | |
810 | |
9024 | 811 #if 0 |
8849 | 812 static void |
813 silcgaim_whois_more(SilcClientEntry client_entry, gint id) | |
814 { | |
815 SilcAttributePayload attr; | |
816 SilcAttribute attribute; | |
817 char *buf; | |
818 GString *s; | |
819 SilcVCardStruct vcard; | |
820 int i; | |
821 | |
822 if (id != 0) | |
823 return; | |
824 | |
825 memset(&vcard, 0, sizeof(vcard)); | |
826 | |
827 s = g_string_new(""); | |
828 | |
829 silc_dlist_start(client_entry->attrs); | |
830 while ((attr = silc_dlist_get(client_entry->attrs)) != SILC_LIST_END) { | |
831 attribute = silc_attribute_get_attribute(attr); | |
832 switch (attribute) { | |
833 | |
834 case SILC_ATTRIBUTE_USER_INFO: | |
835 if (!silc_attribute_get_object(attr, (void *)&vcard, | |
836 sizeof(vcard))) | |
837 continue; | |
9039 | 838 g_string_append_printf(s, "%s:\n\n", _("Personal Information")); |
8849 | 839 if (vcard.full_name) |
9039 | 840 g_string_append_printf(s, "%s:\t\t%s\n", |
841 _("Full Name"), | |
8849 | 842 vcard.full_name); |
843 if (vcard.first_name) | |
9039 | 844 g_string_append_printf(s, "%s:\t%s\n", |
845 _("First Name"), | |
8849 | 846 vcard.first_name); |
847 if (vcard.middle_names) | |
9039 | 848 g_string_append_printf(s, "%s:\t%s\n", |
849 _("Middle Name"), | |
8849 | 850 vcard.middle_names); |
851 if (vcard.family_name) | |
9039 | 852 g_string_append_printf(s, "%s:\t%s\n", |
853 _("Family Name"), | |
8849 | 854 vcard.family_name); |
855 if (vcard.nickname) | |
9039 | 856 g_string_append_printf(s, "%s:\t\t%s\n", |
857 _("Nickname"), | |
8849 | 858 vcard.nickname); |
859 if (vcard.bday) | |
9039 | 860 g_string_append_printf(s, "%s:\t\t%s\n", |
861 _("Birth Day"), | |
8849 | 862 vcard.bday); |
863 if (vcard.title) | |
9039 | 864 g_string_append_printf(s, "%s:\t\t%s\n", |
865 _("Job Title"), | |
8849 | 866 vcard.title); |
867 if (vcard.role) | |
9039 | 868 g_string_append_printf(s, "%s:\t\t%s\n", |
869 _("Job Role"), | |
8849 | 870 vcard.role); |
871 if (vcard.org_name) | |
9039 | 872 g_string_append_printf(s, "%s:\t%s\n", |
873 _("Organization"), | |
8849 | 874 vcard.org_name); |
875 if (vcard.org_unit) | |
9039 | 876 g_string_append_printf(s, "%s:\t\t%s\n", |
877 _("Unit"), | |
8849 | 878 vcard.org_unit); |
879 if (vcard.url) | |
9039 | 880 g_string_append_printf(s, "%s:\t%s\n", |
881 _("Homepage"), | |
8849 | 882 vcard.url); |
883 if (vcard.label) | |
9039 | 884 g_string_append_printf(s, "%s:\t%s\n", |
885 _("Address"), | |
8849 | 886 vcard.label); |
887 for (i = 0; i < vcard.num_tels; i++) { | |
888 if (vcard.tels[i].telnum) | |
9039 | 889 g_string_append_printf(s, "%s:\t\t\t%s\n", |
890 _("Phone"), | |
8849 | 891 vcard.tels[i].telnum); |
892 } | |
893 for (i = 0; i < vcard.num_emails; i++) { | |
894 if (vcard.emails[i].address) | |
9039 | 895 g_string_append_printf(s, "%s:\t\t%s\n", |
896 _("EMail"), | |
8849 | 897 vcard.emails[i].address); |
898 } | |
899 if (vcard.note) | |
9039 | 900 g_string_append_printf(s, "\n%s:\t\t%s\n", |
901 _("Note"), | |
8849 | 902 vcard.note); |
903 break; | |
904 } | |
905 } | |
906 | |
907 buf = g_string_free(s, FALSE); | |
908 gaim_notify_info(NULL, _("User Information"), _("User Information"), | |
909 buf); | |
910 g_free(buf); | |
911 } | |
9024 | 912 #endif |
8849 | 913 |
914 /* Command reply handler. This function is called always in the command reply | |
915 function. If error occurs it will be called as well. Normal scenario | |
916 is that it will be called after the received command data has been parsed | |
917 and processed. The function is used to pass the received command data to | |
918 the application. | |
919 | |
920 `conn' is the associated client connection. `cmd_payload' is the command | |
921 payload data received from server and it can be ignored. It is provided | |
922 if the application would like to re-parse the received command data, | |
923 however, it must be noted that the data is parsed already by the library | |
924 thus the payload can be ignored. `success' is FALSE if error occurred. | |
925 In this case arguments are not sent to the application. The `status' is | |
926 the command reply status server returned. The `command' is the command | |
927 reply being processed. The function has variable argument list and each | |
928 command defines the number and type of arguments it passes to the | |
929 application (on error they are not sent). */ | |
930 | |
931 static void | |
932 silc_command_reply(SilcClient client, SilcClientConnection conn, | |
933 SilcCommandPayload cmd_payload, bool success, | |
934 SilcCommand command, SilcStatus status, ...) | |
935 { | |
936 GaimConnection *gc = client->application; | |
937 SilcGaim sg = gc->proto_data; | |
938 GaimConversation *convo; | |
939 va_list vp; | |
940 | |
941 va_start(vp, status); | |
942 | |
943 switch (command) { | |
944 case SILC_COMMAND_JOIN: | |
945 { | |
946 SilcChannelEntry channel_entry; | |
947 | |
948 if (!success) { | |
949 gaim_notify_error(gc, _("Join Chat"), _("Cannot join channel"), | |
950 silc_get_status_message(status)); | |
951 return; | |
952 } | |
953 | |
954 (void)va_arg(vp, char *); | |
955 channel_entry = va_arg(vp, SilcChannelEntry); | |
956 | |
957 /* Resolve users on channel */ | |
958 silc_client_get_clients_by_channel(client, conn, channel_entry, | |
959 silcgaim_chat_join_done, | |
960 channel_entry); | |
961 } | |
962 break; | |
963 | |
964 case SILC_COMMAND_LEAVE: | |
965 break; | |
966 | |
967 case SILC_COMMAND_USERS: | |
968 break; | |
969 | |
970 case SILC_COMMAND_WHOIS: | |
971 { | |
972 SilcUInt32 idle, mode; | |
973 SilcBuffer channels, user_modes; | |
974 SilcClientEntry client_entry; | |
11531
bf763a1b2454
[gaim-migrate @ 13780]
Luke Schierer <lschiere@pidgin.im>
parents:
11522
diff
changeset
|
975 char *buf, tmp[1024], *tmp2; |
9488 | 976 char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr; |
8849 | 977 GString *s; |
978 | |
979 if (!success) { | |
980 gaim_notify_error(gc, _("User Information"), | |
9488 | 981 _("Cannot get user information"), |
982 silc_get_status_message(status)); | |
8849 | 983 break; |
984 } | |
985 | |
986 client_entry = va_arg(vp, SilcClientEntry); | |
987 if (!client_entry->nickname) | |
988 break; | |
989 (void)va_arg(vp, char *); | |
990 (void)va_arg(vp, char *); | |
991 (void)va_arg(vp, char *); | |
992 channels = va_arg(vp, SilcBuffer); | |
993 mode = va_arg(vp, SilcUInt32); | |
994 idle = va_arg(vp, SilcUInt32); | |
995 (void)va_arg(vp, unsigned char *); | |
996 user_modes = va_arg(vp, SilcBuffer); | |
997 | |
998 s = g_string_new(""); | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10589
diff
changeset
|
999 tmp2 = g_markup_escape_text(client_entry->nickname, -1); |
9488 | 1000 g_string_append_printf(s, "<b>%s:</b> %s", _("Nickname"), tmp2); |
1001 g_free(tmp2); | |
1002 if (client_entry->realname) { | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10589
diff
changeset
|
1003 tmp2 = g_markup_escape_text(client_entry->realname, -1); |
9488 | 1004 g_string_append_printf(s, "<br><b>%s:</b> %s", _("Realname"), tmp2); |
1005 g_free(tmp2); | |
1006 } | |
1007 if (client_entry->username) { | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10589
diff
changeset
|
1008 tmp2 = g_markup_escape_text(client_entry->username, -1); |
9488 | 1009 if (client_entry->hostname) |
1010 g_string_append_printf(s, "<br><b>%s:</b> %s@%s", _("Username"), tmp2, client_entry->hostname); | |
1011 else | |
1012 g_string_append_printf(s, "<br><b>%s:</b> %s", _("Username"), tmp2); | |
1013 g_free(tmp2); | |
1014 } | |
1015 | |
1016 if (client_entry->mode) { | |
1017 g_string_append_printf(s, "<br><b>%s:</b> ", _("User Modes")); | |
1018 memset(tmp, 0, sizeof(tmp)); | |
1019 silcgaim_get_umode_string(client_entry->mode, | |
1020 tmp, sizeof(tmp) - strlen(tmp)); | |
1021 g_string_append_printf(s, "%s", tmp); | |
1022 } | |
1023 | |
1024 silcgaim_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr); | |
1025 if (moodstr) { | |
1026 g_string_append_printf(s, "<br><b>%s:</b> %s", _("Mood"), moodstr); | |
1027 g_free(moodstr); | |
1028 } | |
1029 | |
1030 if (statusstr) { | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10589
diff
changeset
|
1031 tmp2 = g_markup_escape_text(statusstr, -1); |
9488 | 1032 g_string_append_printf(s, "<br><b>%s:</b> %s", _("Status Text"), tmp2); |
1033 g_free(statusstr); | |
1034 g_free(tmp2); | |
1035 } | |
1036 | |
1037 if (contactstr) { | |
1038 g_string_append_printf(s, "<br><b>%s:</b> %s", _("Preferred Contact"), contactstr); | |
1039 g_free(contactstr); | |
1040 } | |
1041 | |
1042 if (langstr) { | |
1043 g_string_append_printf(s, "<br><b>%s:</b> %s", _("Preferred Language"), langstr); | |
1044 g_free(langstr); | |
1045 } | |
1046 | |
1047 if (devicestr) { | |
1048 g_string_append_printf(s, "<br><b>%s:</b> %s", _("Device"), devicestr); | |
1049 g_free(devicestr); | |
1050 } | |
1051 | |
1052 if (tzstr) { | |
1053 g_string_append_printf(s, "<br><b>%s:</b> %s", _("Timezone"), tzstr); | |
1054 g_free(tzstr); | |
1055 } | |
1056 | |
1057 if (geostr) { | |
1058 g_string_append_printf(s, "<br><b>%s:</b> %s", _("Geolocation"), geostr); | |
1059 g_free(geostr); | |
1060 } | |
1061 | |
8849 | 1062 if (client_entry->server) |
9488 | 1063 g_string_append_printf(s, "<br><b>%s:</b> %s", _("Server"), client_entry->server); |
8849 | 1064 |
1065 if (channels && user_modes) { | |
1066 SilcUInt32 *umodes; | |
1067 SilcDList list = | |
1068 silc_channel_payload_parse_list(channels->data, | |
9488 | 1069 channels->len); |
8849 | 1070 if (list && silc_get_mode_list(user_modes, |
9488 | 1071 silc_dlist_count(list), |
1072 &umodes)) { | |
8849 | 1073 SilcChannelPayload entry; |
1074 int i = 0; | |
1075 | |
9488 | 1076 g_string_append_printf(s, "<br><b>%s:</b> ", _("Currently on")); |
8849 | 1077 memset(tmp, 0, sizeof(tmp)); |
1078 silc_dlist_start(list); | |
1079 while ((entry = silc_dlist_get(list)) | |
9488 | 1080 != SILC_LIST_END) { |
8849 | 1081 SilcUInt32 name_len; |
1082 char *m = silc_client_chumode_char(umodes[i++]); | |
11488 | 1083 char *name = (char *)silc_channel_get_name(entry, &name_len); |
8849 | 1084 if (m) |
1085 silc_strncat(tmp, sizeof(tmp) - 1, m, strlen(m)); | |
1086 silc_strncat(tmp, sizeof(tmp) - 1, name, name_len); | |
1087 silc_strncat(tmp, sizeof(tmp) - 1, " ", 1); | |
1088 silc_free(m); | |
1089 | |
1090 } | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10589
diff
changeset
|
1091 tmp2 = g_markup_escape_text(tmp, -1); |
9488 | 1092 g_string_append_printf(s, "%s", tmp2); |
1093 g_free(tmp2); | |
8849 | 1094 silc_free(umodes); |
1095 } | |
1096 } | |
1097 | |
1098 if (client_entry->public_key) { | |
1099 char *fingerprint, *babbleprint; | |
1100 unsigned char *pk; | |
1101 SilcUInt32 pk_len; | |
1102 pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); | |
1103 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); | |
1104 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); | |
9488 | 1105 g_string_append_printf(s, "<br><b>%s:</b><br>%s", _("Public Key Fingerprint"), fingerprint); |
1106 g_string_append_printf(s, "<br><b>%s:</b><br>%s", _("Public Key Babbleprint"), babbleprint); | |
8849 | 1107 silc_free(fingerprint); |
1108 silc_free(babbleprint); | |
1109 silc_free(pk); | |
1110 } | |
1111 | |
1112 buf = g_string_free(s, FALSE); | |
1113 #if 0 /* XXX for now, let's not show attrs here */ | |
1114 if (client_entry->attrs) | |
11201 | 1115 gaim_request_action(gc, _("User Information"), |
9488 | 1116 _("User Information"), |
1117 buf, 1, client_entry, 2, | |
1118 _("OK"), G_CALLBACK(silcgaim_whois_more), | |
1119 _("More..."), G_CALLBACK(silcgaim_whois_more)); | |
8849 | 1120 else |
1121 #endif | |
11533
c9b815aeddc1
[gaim-migrate @ 13782]
Richard Laager <rlaager@wiktel.com>
parents:
11531
diff
changeset
|
1122 gaim_notify_userinfo(gc, client_entry->nickname, buf, NULL, NULL); |
9488 | 1123 g_free(buf); |
1124 } | |
1125 break; | |
1126 | |
1127 case SILC_COMMAND_WHOWAS: | |
1128 { | |
1129 SilcClientEntry client_entry; | |
11531
bf763a1b2454
[gaim-migrate @ 13780]
Luke Schierer <lschiere@pidgin.im>
parents:
11522
diff
changeset
|
1130 char *buf, *nickname, *realname, *username, *tmp; |
9488 | 1131 GString *s; |
1132 | |
1133 if (!success) { | |
1134 gaim_notify_error(gc, _("User Information"), | |
1135 _("Cannot get user information"), | |
1136 silc_get_status_message(status)); | |
1137 break; | |
1138 } | |
1139 | |
1140 client_entry = va_arg(vp, SilcClientEntry); | |
1141 nickname = va_arg(vp, char *); | |
1142 username = va_arg(vp, char *); | |
1143 realname = va_arg(vp, char *); | |
1144 if (!nickname) | |
1145 break; | |
1146 | |
1147 s = g_string_new(""); | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10589
diff
changeset
|
1148 tmp = g_markup_escape_text(nickname, -1); |
9488 | 1149 g_string_append_printf(s, "<b>%s:</b> %s", _("Nickname"), tmp); |
1150 g_free(tmp); | |
1151 if (realname) { | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10589
diff
changeset
|
1152 tmp = g_markup_escape_text(realname, -1); |
9488 | 1153 g_string_append_printf(s, "<br><b>%s:</b> %s", _("Realname"), tmp); |
1154 g_free(tmp); | |
1155 } | |
1156 if (username) { | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10589
diff
changeset
|
1157 tmp = g_markup_escape_text(username, -1); |
9488 | 1158 if (client_entry && client_entry->hostname) |
1159 g_string_append_printf(s, "<br><b>%s:</b> %s@%s", _("Username"), tmp, client_entry->hostname); | |
1160 else | |
1161 g_string_append_printf(s, "<br><b>%s:</b> %s", _("Username"), tmp); | |
1162 g_free(tmp); | |
1163 } | |
1164 if (client_entry && client_entry->server) | |
1165 g_string_append_printf(s, "<br><b>%s:</b> %s", _("Server"), client_entry->server); | |
1166 | |
1167 | |
1168 if (client_entry && client_entry->public_key) { | |
1169 char *fingerprint, *babbleprint; | |
1170 unsigned char *pk; | |
1171 SilcUInt32 pk_len; | |
1172 pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); | |
1173 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); | |
1174 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); | |
1175 g_string_append_printf(s, "<br><b>%s:</b><br>%s", _("Public Key Fingerprint"), fingerprint); | |
1176 g_string_append_printf(s, "<br><b>%s:</b><br>%s", _("Public Key Babbleprint"), babbleprint); | |
1177 silc_free(fingerprint); | |
1178 silc_free(babbleprint); | |
1179 silc_free(pk); | |
1180 } | |
1181 | |
1182 buf = g_string_free(s, FALSE); | |
11533
c9b815aeddc1
[gaim-migrate @ 13782]
Richard Laager <rlaager@wiktel.com>
parents:
11531
diff
changeset
|
1183 gaim_notify_userinfo(gc, client_entry->nickname, buf, NULL, NULL); |
8849 | 1184 g_free(buf); |
1185 } | |
1186 break; | |
1187 | |
1188 case SILC_COMMAND_DETACH: | |
1189 if (!success) { | |
1190 gaim_notify_error(gc, _("Detach From Server"), _("Cannot detach"), | |
1191 silc_get_status_message(status)); | |
1192 return; | |
1193 } | |
1194 break; | |
1195 | |
1196 case SILC_COMMAND_TOPIC: | |
1197 { | |
1198 SilcChannelEntry channel; | |
1199 | |
1200 if (!success) { | |
1201 gaim_notify_error(gc, _("Topic"), _("Cannot set topic"), | |
1202 silc_get_status_message(status)); | |
1203 return; | |
1204 } | |
1205 | |
1206 channel = va_arg(vp, SilcChannelEntry); | |
1207 | |
11338 | 1208 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 1209 channel->channel_name, sg->account); |
9353 | 1210 if (!convo) { |
1211 gaim_debug_error("silc", "Got a topic for %s, which doesn't exist\n", | |
1212 channel->channel_name); | |
8849 | 1213 break; |
9353 | 1214 } |
1215 | |
8849 | 1216 /* Set topic */ |
1217 if (channel->topic) | |
1218 gaim_conv_chat_set_topic(GAIM_CONV_CHAT(convo), NULL, channel->topic); | |
1219 } | |
1220 break; | |
1221 | |
9353 | 1222 case SILC_COMMAND_NICK: |
1223 { | |
1224 /* I don't think we should need to do this because the server should | |
1225 * be sending a SILC_NOTIFY_TYPE_NICK_CHANGE when we change our own | |
1226 * nick, but it isn't, so we deal with it here instead. Stu. */ | |
1227 SilcClientEntry local_entry; | |
1228 SilcHashTableList htl; | |
1229 SilcChannelUser chu; | |
1230 const char *oldnick; | |
1231 | |
1232 if (!success) { | |
9488 | 1233 gaim_notify_error(gc, _("Nick"), _("Failed to change nickname"), |
1234 silc_get_status_message(status)); | |
9353 | 1235 return; |
1236 } | |
1237 | |
1238 local_entry = va_arg(vp, SilcClientEntry); | |
1239 | |
1240 /* Change nick on all channels */ | |
1241 silc_hash_table_list(local_entry->channels, &htl); | |
1242 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
11338 | 1243 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 1244 chu->channel->channel_name, sg->account); |
1245 if (!convo) | |
9353 | 1246 continue; |
1247 oldnick = gaim_conv_chat_get_nick(GAIM_CONV_CHAT(convo)); | |
11500
9fc7d0153332
[gaim-migrate @ 13745]
Richard Laager <rlaager@wiktel.com>
parents:
11488
diff
changeset
|
1248 if (strcmp(oldnick, gaim_normalize(gaim_conversation_get_account(convo), local_entry->nickname))) { |
9353 | 1249 gaim_conv_chat_rename_user(GAIM_CONV_CHAT(convo), |
1250 oldnick, local_entry->nickname); | |
1251 gaim_conv_chat_set_nick(GAIM_CONV_CHAT(convo), local_entry->nickname); | |
1252 } | |
1253 } | |
1254 silc_hash_table_list_reset(&htl); | |
9488 | 1255 |
1256 gaim_connection_set_display_name(gc, local_entry->nickname); | |
9353 | 1257 } |
1258 break; | |
1259 | |
8849 | 1260 case SILC_COMMAND_LIST: |
1261 { | |
1262 char *topic, *name; | |
1263 int usercount; | |
1264 GaimRoomlistRoom *room; | |
1265 | |
1266 if (sg->roomlist_canceled) | |
1267 break; | |
1268 | |
1269 if (!success) { | |
10091 | 1270 gaim_notify_error(gc, _("Error"), _("Error retrieving room list"), |
8849 | 1271 silc_get_status_message(status)); |
1272 gaim_roomlist_set_in_progress(sg->roomlist, FALSE); | |
1273 gaim_roomlist_unref(sg->roomlist); | |
1274 sg->roomlist = NULL; | |
1275 return; | |
1276 } | |
1277 | |
1278 (void)va_arg(vp, SilcChannelEntry); | |
1279 name = va_arg(vp, char *); | |
10855
2d3a935462aa
[gaim-migrate @ 12530]
Luke Schierer <lschiere@pidgin.im>
parents:
10774
diff
changeset
|
1280 if (!name) { |
2d3a935462aa
[gaim-migrate @ 12530]
Luke Schierer <lschiere@pidgin.im>
parents:
10774
diff
changeset
|
1281 gaim_notify_error(gc, _("Roomlist"), _("Cannot get room list"), |
2d3a935462aa
[gaim-migrate @ 12530]
Luke Schierer <lschiere@pidgin.im>
parents:
10774
diff
changeset
|
1282 silc_get_status_message(status)); |
2d3a935462aa
[gaim-migrate @ 12530]
Luke Schierer <lschiere@pidgin.im>
parents:
10774
diff
changeset
|
1283 gaim_roomlist_set_in_progress(sg->roomlist, FALSE); |
2d3a935462aa
[gaim-migrate @ 12530]
Luke Schierer <lschiere@pidgin.im>
parents:
10774
diff
changeset
|
1284 gaim_roomlist_unref(sg->roomlist); |
2d3a935462aa
[gaim-migrate @ 12530]
Luke Schierer <lschiere@pidgin.im>
parents:
10774
diff
changeset
|
1285 sg->roomlist = NULL; |
2d3a935462aa
[gaim-migrate @ 12530]
Luke Schierer <lschiere@pidgin.im>
parents:
10774
diff
changeset
|
1286 return; |
2d3a935462aa
[gaim-migrate @ 12530]
Luke Schierer <lschiere@pidgin.im>
parents:
10774
diff
changeset
|
1287 } |
8849 | 1288 topic = va_arg(vp, char *); |
1289 usercount = va_arg(vp, int); | |
1290 | |
1291 room = gaim_roomlist_room_new(GAIM_ROOMLIST_ROOMTYPE_ROOM, name, NULL); | |
1292 gaim_roomlist_room_add_field(sg->roomlist, room, name); | |
1293 gaim_roomlist_room_add_field(sg->roomlist, room, | |
1294 SILC_32_TO_PTR(usercount)); | |
1295 gaim_roomlist_room_add_field(sg->roomlist, room, | |
1296 topic ? topic : ""); | |
1297 gaim_roomlist_room_add(sg->roomlist, room); | |
1298 | |
1299 if (status == SILC_STATUS_LIST_END || | |
1300 status == SILC_STATUS_OK) { | |
1301 gaim_roomlist_set_in_progress(sg->roomlist, FALSE); | |
1302 gaim_roomlist_unref(sg->roomlist); | |
1303 sg->roomlist = NULL; | |
1304 } | |
1305 } | |
1306 break; | |
1307 | |
1308 case SILC_COMMAND_GETKEY: | |
1309 { | |
1310 SilcPublicKey public_key; | |
1311 | |
1312 if (!success) { | |
1313 gaim_notify_error(gc, _("Get Public Key"), | |
1314 _("Cannot fetch the public key"), | |
1315 silc_get_status_message(status)); | |
1316 return; | |
1317 } | |
1318 | |
1319 (void)va_arg(vp, SilcUInt32); | |
1320 (void)va_arg(vp, void *); | |
1321 public_key = va_arg(vp, SilcPublicKey); | |
1322 | |
1323 if (!public_key) | |
1324 gaim_notify_error(gc, _("Get Public Key"), | |
1325 _("Cannot fetch the public key"), | |
1326 _("No public key was received")); | |
1327 } | |
1328 break; | |
1329 | |
1330 case SILC_COMMAND_INFO: | |
1331 { | |
1332 | |
1333 SilcServerEntry server_entry; | |
1334 char *server_name; | |
1335 char *server_info; | |
10774 | 1336 char tmp[256]; |
8849 | 1337 |
1338 if (!success) { | |
1339 gaim_notify_error(gc, _("Server Information"), | |
1340 _("Cannot get server information"), | |
1341 silc_get_status_message(status)); | |
1342 return; | |
1343 } | |
1344 | |
1345 server_entry = va_arg(vp, SilcServerEntry); | |
1346 server_name = va_arg(vp, char *); | |
1347 server_info = va_arg(vp, char *); | |
1348 | |
1349 if (server_name && server_info) { | |
1350 g_snprintf(tmp, sizeof(tmp), "Server: %s\n%s", | |
1351 server_name, server_info); | |
10774 | 1352 gaim_notify_info(gc, NULL, _("Server Information"), tmp); |
8849 | 1353 } |
1354 } | |
1355 break; | |
1356 | |
9488 | 1357 case SILC_COMMAND_STATS: |
1358 { | |
1359 SilcUInt32 starttime, uptime, my_clients, my_channels, my_server_ops, | |
1360 my_router_ops, cell_clients, cell_channels, cell_servers, | |
1361 clients, channels, servers, routers, server_ops, router_ops; | |
1362 SilcUInt32 buffer_length; | |
1363 SilcBufferStruct buf; | |
1364 | |
1365 unsigned char *server_stats; | |
1366 char *msg; | |
1367 | |
1368 if (!success) { | |
1369 gaim_notify_error(gc, _("Server Statistics"), | |
9507 | 1370 _("Cannot get server statistics"), |
9488 | 1371 silc_get_status_message(status)); |
1372 return; | |
1373 } | |
1374 | |
1375 server_stats = va_arg(vp, unsigned char *); | |
1376 buffer_length = va_arg(vp, SilcUInt32); | |
1377 if (!server_stats || !buffer_length) { | |
1378 gaim_notify_error(gc, _("Server Statistics"), | |
9645 | 1379 _("No server statistics available"), NULL); |
9488 | 1380 break; |
1381 } | |
1382 silc_buffer_set(&buf, server_stats, buffer_length); | |
1383 silc_buffer_unformat(&buf, | |
1384 SILC_STR_UI_INT(&starttime), | |
1385 SILC_STR_UI_INT(&uptime), | |
1386 SILC_STR_UI_INT(&my_clients), | |
1387 SILC_STR_UI_INT(&my_channels), | |
1388 SILC_STR_UI_INT(&my_server_ops), | |
1389 SILC_STR_UI_INT(&my_router_ops), | |
1390 SILC_STR_UI_INT(&cell_clients), | |
1391 SILC_STR_UI_INT(&cell_channels), | |
1392 SILC_STR_UI_INT(&cell_servers), | |
1393 SILC_STR_UI_INT(&clients), | |
1394 SILC_STR_UI_INT(&channels), | |
1395 SILC_STR_UI_INT(&servers), | |
1396 SILC_STR_UI_INT(&routers), | |
1397 SILC_STR_UI_INT(&server_ops), | |
1398 SILC_STR_UI_INT(&router_ops), | |
1399 SILC_STR_END); | |
1400 | |
1401 msg = g_strdup_printf(_("Local server start time: %s\n" | |
1402 "Local server uptime: %s\n" | |
1403 "Local server clients: %d\n" | |
1404 "Local server channels: %d\n" | |
1405 "Local server operators: %d\n" | |
1406 "Local router operators: %d\n" | |
1407 "Local cell clients: %d\n" | |
1408 "Local cell channels: %d\n" | |
1409 "Local cell servers: %d\n" | |
1410 "Total clients: %d\n" | |
1411 "Total channels: %d\n" | |
1412 "Total servers: %d\n" | |
1413 "Total routers: %d\n" | |
1414 "Total server operators: %d\n" | |
1415 "Total router operators: %d\n"), | |
1416 silc_get_time(starttime), | |
1417 gaim_str_seconds_to_string((int)uptime), | |
1418 (int)my_clients, (int)my_channels, (int)my_server_ops, (int)my_router_ops, | |
1419 (int)cell_clients, (int)cell_channels, (int)cell_servers, | |
1420 (int)clients, (int)channels, (int)servers, (int)routers, | |
1421 (int)server_ops, (int)router_ops); | |
1422 | |
1423 gaim_notify_info(gc, NULL, | |
1424 _("Network Statistics"), msg); | |
1425 g_free(msg); | |
1426 } | |
1427 break; | |
1428 | |
1429 case SILC_COMMAND_PING: | |
1430 { | |
1431 if (!success) { | |
1432 gaim_notify_error(gc, _("Ping"), _("Ping failed"), | |
1433 silc_get_status_message(status)); | |
1434 return; | |
1435 } | |
1436 | |
1437 gaim_notify_info(gc, _("Ping"), _("Ping reply received from server"), | |
1438 NULL); | |
1439 } | |
1440 break; | |
1441 | |
8849 | 1442 case SILC_COMMAND_KILL: |
1443 if (!success) { | |
1444 gaim_notify_error(gc, _("Kill User"), | |
1445 _("Could not kill user"), | |
1446 silc_get_status_message(status)); | |
1447 return; | |
1448 } | |
1449 break; | |
1450 | |
1451 case SILC_COMMAND_CMODE: | |
1452 { | |
1453 SilcChannelEntry channel_entry; | |
1454 SilcBuffer channel_pubkeys; | |
1455 | |
1456 if (!success) | |
1457 return; | |
1458 | |
1459 channel_entry = va_arg(vp, SilcChannelEntry); | |
1460 (void)va_arg(vp, SilcUInt32); | |
1461 (void)va_arg(vp, SilcPublicKey); | |
1462 channel_pubkeys = va_arg(vp, SilcBuffer); | |
1463 | |
1464 if (sg->chpk) | |
1465 silcgaim_chat_chauth_show(sg, channel_entry, channel_pubkeys); | |
1466 } | |
1467 break; | |
1468 | |
1469 default: | |
9353 | 1470 if (success) |
1471 gaim_debug_info("silc", "Unhandled command: %d (succeeded)\n", command); | |
1472 else | |
1473 gaim_debug_info("silc", "Unhandled command: %d (failed: %s)\n", command, | |
1474 silc_get_status_message(status)); | |
8849 | 1475 break; |
1476 } | |
1477 | |
1478 va_end(vp); | |
1479 } | |
1480 | |
1481 | |
1482 /* Called to indicate that connection was either successfully established | |
1483 or connecting failed. This is also the first time application receives | |
9488 | 1484 the SilcClientConnection object which it should save somewhere. |
8849 | 1485 If the `success' is FALSE the application must always call the function |
1486 silc_client_close_connection. */ | |
1487 | |
1488 static void | |
1489 silc_connected(SilcClient client, SilcClientConnection conn, | |
1490 SilcClientConnectionStatus status) | |
1491 { | |
1492 GaimConnection *gc = client->application; | |
1493 SilcGaim sg = gc->proto_data; | |
1494 gboolean reject_watch, block_invites, block_ims; | |
1495 | |
1496 if (!gc) { | |
1497 sg->conn = NULL; | |
1498 silc_client_close_connection(client, conn); | |
1499 return; | |
1500 } | |
1501 | |
1502 switch (status) { | |
1503 case SILC_CLIENT_CONN_SUCCESS: | |
1504 case SILC_CLIENT_CONN_SUCCESS_RESUME: | |
1505 gaim_connection_set_state(gc, GAIM_CONNECTED); | |
10869 | 1506 |
1507 /* Send the server our buddy list */ | |
1508 silcgaim_send_buddylist(gc); | |
1509 | |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10336
diff
changeset
|
1510 g_unlink(silcgaim_session_file(gaim_account_get_username(sg->account))); |
8849 | 1511 |
1512 /* Send any UMODEs configured for account */ | |
1513 reject_watch = gaim_account_get_bool(sg->account, "reject-watch", FALSE); | |
1514 block_invites = gaim_account_get_bool(sg->account, "block-invites", FALSE); | |
1515 block_ims = gaim_account_get_bool(sg->account, "block-ims", FALSE); | |
1516 if (reject_watch || block_invites || block_ims) { | |
1517 char m[5]; | |
1518 g_snprintf(m, sizeof(m), "+%s%s%s", | |
9488 | 1519 reject_watch ? "w" : "", |
1520 block_invites ? "I" : "", | |
1521 block_ims ? "P" : ""); | |
8849 | 1522 silc_client_command_call(sg->client, sg->conn, NULL, |
9488 | 1523 "UMODE", m, NULL); |
8849 | 1524 } |
1525 | |
1526 return; | |
1527 break; | |
1528 case SILC_CLIENT_CONN_ERROR: | |
1529 gaim_connection_error(gc, _("Error during connecting to SILC Server")); | |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10336
diff
changeset
|
1530 g_unlink(silcgaim_session_file(gaim_account_get_username(sg->account))); |
8849 | 1531 break; |
1532 | |
1533 case SILC_CLIENT_CONN_ERROR_KE: | |
1534 gaim_connection_error(gc, _("Key Exchange failed")); | |
1535 break; | |
1536 | |
1537 case SILC_CLIENT_CONN_ERROR_AUTH: | |
1538 gaim_connection_error(gc, _("Authentication failed")); | |
1539 break; | |
1540 | |
1541 case SILC_CLIENT_CONN_ERROR_RESUME: | |
1542 gaim_connection_error(gc, | |
8910 | 1543 _("Resuming detached session failed. " |
8849 | 1544 "Press Reconnect to create new connection.")); |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10336
diff
changeset
|
1545 g_unlink(silcgaim_session_file(gaim_account_get_username(sg->account))); |
8849 | 1546 break; |
1547 | |
1548 case SILC_CLIENT_CONN_ERROR_TIMEOUT: | |
9039 | 1549 gaim_connection_error(gc, _("Connection Timeout")); |
8849 | 1550 break; |
1551 } | |
1552 | |
1553 /* Error */ | |
1554 sg->conn = NULL; | |
1555 silc_client_close_connection(client, conn); | |
1556 } | |
1557 | |
1558 | |
1559 /* Called to indicate that connection was disconnected to the server. | |
1560 The `status' may tell the reason of the disconnection, and if the | |
1561 `message' is non-NULL it may include the disconnection message | |
1562 received from server. */ | |
1563 | |
1564 static void | |
1565 silc_disconnected(SilcClient client, SilcClientConnection conn, | |
1566 SilcStatus status, const char *message) | |
1567 { | |
1568 GaimConnection *gc = client->application; | |
1569 SilcGaim sg = gc->proto_data; | |
1570 | |
1571 if (sg->resuming && !sg->detaching) | |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10336
diff
changeset
|
1572 g_unlink(silcgaim_session_file(gaim_account_get_username(sg->account))); |
8849 | 1573 |
1574 sg->conn = NULL; | |
1575 | |
1576 /* Close the connection */ | |
1577 if (!sg->detaching) | |
1578 gaim_connection_error(gc, _("Disconnected by server")); | |
1579 else | |
10740 | 1580 /* TODO: Does this work correctly? Maybe we need to set wants_to_die? */ |
1581 gaim_account_disconnect(gaim_connection_get_account(gc)); | |
8849 | 1582 } |
1583 | |
1584 | |
1585 typedef struct { | |
1586 SilcGetAuthMeth completion; | |
1587 void *context; | |
1588 } *SilcGaimGetAuthMethod; | |
1589 | |
1590 /* Callback called when we've received the authentication method information | |
1591 from the server after we've requested it. */ | |
1592 | |
1593 static void silc_get_auth_method_callback(SilcClient client, | |
1594 SilcClientConnection conn, | |
1595 SilcAuthMethod auth_meth, | |
1596 void *context) | |
1597 { | |
1598 SilcGaimGetAuthMethod internal = context; | |
1599 | |
1600 switch (auth_meth) { | |
1601 case SILC_AUTH_NONE: | |
1602 /* No authentication required. */ | |
1603 (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); | |
1604 break; | |
1605 | |
1606 case SILC_AUTH_PASSWORD: | |
1607 /* By returning NULL here the library will ask the passphrase from us | |
1608 by calling the silc_ask_passphrase. */ | |
1609 (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); | |
1610 break; | |
1611 | |
1612 case SILC_AUTH_PUBLIC_KEY: | |
1613 /* Do not get the authentication data now, the library will generate | |
1614 it using our default key, if we do not provide it here. */ | |
1615 (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); | |
1616 break; | |
1617 } | |
1618 | |
1619 silc_free(internal); | |
1620 } | |
1621 | |
1622 /* Find authentication method and authentication data by hostname and | |
1623 port. The hostname may be IP address as well. When the authentication | |
1624 method has been resolved the `completion' callback with the found | |
1625 authentication method and authentication data is called. The `conn' | |
1626 may be NULL. */ | |
1627 | |
1628 static void | |
1629 silc_get_auth_method(SilcClient client, SilcClientConnection conn, | |
1630 char *hostname, SilcUInt16 port, | |
1631 SilcGetAuthMeth completion, void *context) | |
1632 { | |
1633 GaimConnection *gc = client->application; | |
1634 SilcGaim sg = gc->proto_data; | |
1635 SilcGaimGetAuthMethod internal; | |
10751 | 1636 const char *password; |
8849 | 1637 |
1638 /* Progress */ | |
1639 if (sg->resuming) | |
1640 gaim_connection_update_progress(gc, _("Resuming session"), 4, 5); | |
1641 else | |
1642 gaim_connection_update_progress(gc, _("Authenticating connection"), 4, 5); | |
1643 | |
1644 /* Check configuration if we have this connection configured. If we | |
1645 have then return that data immediately, as it's faster way. */ | |
10336 | 1646 if (gaim_account_get_bool(sg->account, "pubkey-auth", FALSE)) { |
1647 completion(TRUE, SILC_AUTH_PUBLIC_KEY, NULL, 0, context); | |
1648 return; | |
1649 } | |
10751 | 1650 password = gaim_connection_get_password(gc); |
1651 if (password && *password) { | |
11488 | 1652 completion(TRUE, SILC_AUTH_PASSWORD, (unsigned char *)password, strlen(password), context); |
8849 | 1653 return; |
1654 } | |
1655 | |
1656 /* Resolve the authentication method from server, as we may not know it. */ | |
1657 internal = silc_calloc(1, sizeof(*internal)); | |
1658 if (!internal) | |
1659 return; | |
1660 internal->completion = completion; | |
1661 internal->context = context; | |
1662 silc_client_request_authentication_method(client, conn, | |
1663 silc_get_auth_method_callback, | |
1664 internal); | |
1665 } | |
1666 | |
1667 | |
1668 /* Verifies received public key. The `conn_type' indicates which entity | |
1669 (server, client etc.) has sent the public key. If user decides to trust | |
1670 the application may save the key as trusted public key for later | |
1671 use. The `completion' must be called after the public key has been | |
1672 verified. */ | |
1673 | |
1674 static void | |
1675 silc_verify_public_key(SilcClient client, SilcClientConnection conn, | |
1676 SilcSocketType conn_type, unsigned char *pk, | |
1677 SilcUInt32 pk_len, SilcSKEPKType pk_type, | |
1678 SilcVerifyPublicKey completion, void *context) | |
1679 { | |
1680 GaimConnection *gc = client->application; | |
1681 SilcGaim sg = gc->proto_data; | |
1682 | |
1683 if (!sg->conn && (conn_type == SILC_SOCKET_TYPE_SERVER || | |
1684 conn_type == SILC_SOCKET_TYPE_ROUTER)) { | |
1685 /* Progress */ | |
1686 if (sg->resuming) | |
1687 gaim_connection_update_progress(gc, _("Resuming session"), 3, 5); | |
1688 else | |
1689 gaim_connection_update_progress(gc, _("Verifying server public key"), | |
1690 3, 5); | |
1691 } | |
1692 | |
1693 /* Verify public key */ | |
1694 silcgaim_verify_public_key(client, conn, NULL, conn_type, pk, | |
1695 pk_len, pk_type, completion, context); | |
1696 } | |
1697 | |
1698 typedef struct { | |
1699 SilcAskPassphrase completion; | |
1700 void *context; | |
1701 } *SilcGaimAskPassphrase; | |
1702 | |
1703 static void | |
1704 silc_ask_passphrase_cb(SilcGaimAskPassphrase internal, const char *passphrase) | |
1705 { | |
1706 if (!passphrase || !(*passphrase)) | |
1707 internal->completion(NULL, 0, internal->context); | |
1708 else | |
1709 internal->completion((unsigned char *)passphrase, | |
1710 strlen(passphrase), internal->context); | |
1711 silc_free(internal); | |
1712 } | |
1713 | |
1714 /* Ask (interact, that is) a passphrase from user. The passphrase is | |
1715 returned to the library by calling the `completion' callback with | |
1716 the `context'. The returned passphrase SHOULD be in UTF-8 encoded, | |
1717 if not then the library will attempt to encode. */ | |
1718 | |
1719 static void | |
1720 silc_ask_passphrase(SilcClient client, SilcClientConnection conn, | |
1721 SilcAskPassphrase completion, void *context) | |
1722 { | |
1723 SilcGaimAskPassphrase internal = silc_calloc(1, sizeof(*internal)); | |
1724 | |
1725 if (!internal) | |
1726 return; | |
1727 internal->completion = completion; | |
1728 internal->context = context; | |
11201 | 1729 gaim_request_input(client->application, _("Passphrase"), NULL, |
8849 | 1730 _("Passphrase required"), NULL, FALSE, TRUE, NULL, |
1731 _("OK"), G_CALLBACK(silc_ask_passphrase_cb), | |
1732 _("Cancel"), G_CALLBACK(silc_ask_passphrase_cb), | |
1733 internal); | |
1734 } | |
1735 | |
1736 | |
1737 /* Notifies application that failure packet was received. This is called | |
1738 if there is some protocol active in the client. The `protocol' is the | |
1739 protocol context. The `failure' is opaque pointer to the failure | |
1740 indication. Note, that the `failure' is protocol dependant and | |
1741 application must explicitly cast it to correct type. Usually `failure' | |
1742 is 32 bit failure type (see protocol specs for all protocol failure | |
1743 types). */ | |
1744 | |
1745 static void | |
1746 silc_failure(SilcClient client, SilcClientConnection conn, | |
1747 SilcProtocol protocol, void *failure) | |
1748 { | |
1749 GaimConnection *gc = client->application; | |
1750 char buf[128]; | |
1751 | |
1752 memset(buf, 0, sizeof(buf)); | |
1753 | |
1754 if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) { | |
1755 SilcSKEStatus status = (SilcSKEStatus)SILC_PTR_TO_32(failure); | |
1756 | |
1757 if (status == SILC_SKE_STATUS_BAD_VERSION) | |
1758 g_snprintf(buf, sizeof(buf), | |
1759 _("Failure: Version mismatch, upgrade your client")); | |
1760 if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) | |
1761 g_snprintf(buf, sizeof(buf), | |
1762 _("Failure: Remote does not trust/support your public key")); | |
1763 if (status == SILC_SKE_STATUS_UNKNOWN_GROUP) | |
1764 g_snprintf(buf, sizeof(buf), | |
1765 _("Failure: Remote does not support proposed KE group")); | |
1766 if (status == SILC_SKE_STATUS_UNKNOWN_CIPHER) | |
1767 g_snprintf(buf, sizeof(buf), | |
1768 _("Failure: Remote does not support proposed cipher")); | |
1769 if (status == SILC_SKE_STATUS_UNKNOWN_PKCS) | |
1770 g_snprintf(buf, sizeof(buf), | |
1771 _("Failure: Remote does not support proposed PKCS")); | |
1772 if (status == SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION) | |
1773 g_snprintf(buf, sizeof(buf), | |
1774 _("Failure: Remote does not support proposed hash function")); | |
1775 if (status == SILC_SKE_STATUS_UNKNOWN_HMAC) | |
1776 g_snprintf(buf, sizeof(buf), | |
1777 _("Failure: Remote does not support proposed HMAC")); | |
1778 if (status == SILC_SKE_STATUS_INCORRECT_SIGNATURE) | |
1779 g_snprintf(buf, sizeof(buf), _("Failure: Incorrect signature")); | |
1780 if (status == SILC_SKE_STATUS_INVALID_COOKIE) | |
1781 g_snprintf(buf, sizeof(buf), _("Failure: Invalid cookie")); | |
1782 | |
1783 /* Show the error on the progress bar. A more generic error message | |
1784 is going to be showed to user after this in the silc_connected. */ | |
1785 gaim_connection_update_progress(gc, buf, 2, 5); | |
1786 } | |
1787 | |
1788 if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) { | |
1789 SilcUInt32 err = SILC_PTR_TO_32(failure); | |
1790 | |
1791 if (err == SILC_AUTH_FAILED) | |
1792 g_snprintf(buf, sizeof(buf), _("Failure: Authentication failed")); | |
1793 | |
1794 /* Show the error on the progress bar. A more generic error message | |
1795 is going to be showed to user after this in the silc_connected. */ | |
1796 gaim_connection_update_progress(gc, buf, 4, 5); | |
1797 } | |
1798 } | |
1799 | |
1800 /* Asks whether the user would like to perform the key agreement protocol. | |
1801 This is called after we have received an key agreement packet or an | |
1802 reply to our key agreement packet. This returns TRUE if the user wants | |
1803 the library to perform the key agreement protocol and FALSE if it is not | |
1804 desired (application may start it later by calling the function | |
1805 silc_client_perform_key_agreement). If TRUE is returned also the | |
1806 `completion' and `context' arguments must be set by the application. */ | |
1807 | |
1808 static bool | |
1809 silc_key_agreement(SilcClient client, SilcClientConnection conn, | |
1810 SilcClientEntry client_entry, const char *hostname, | |
1811 SilcUInt16 port, SilcKeyAgreementCallback *completion, | |
1812 void **context) | |
1813 { | |
1814 silcgaim_buddy_keyagr_request(client, conn, client_entry, hostname, port); | |
1815 *completion = NULL; | |
1816 *context = NULL; | |
1817 return FALSE; | |
1818 } | |
1819 | |
1820 | |
1821 /* Notifies application that file transfer protocol session is being | |
1822 requested by the remote client indicated by the `client_entry' from | |
1823 the `hostname' and `port'. The `session_id' is the file transfer | |
1824 session and it can be used to either accept or reject the file | |
1825 transfer request, by calling the silc_client_file_receive or | |
1826 silc_client_file_close, respectively. */ | |
1827 | |
1828 static void | |
1829 silc_ftp(SilcClient client, SilcClientConnection conn, | |
1830 SilcClientEntry client_entry, SilcUInt32 session_id, | |
1831 const char *hostname, SilcUInt16 port) | |
1832 { | |
1833 silcgaim_ftp_request(client, conn, client_entry, session_id, | |
1834 hostname, port); | |
1835 } | |
1836 | |
1837 | |
1838 /* Delivers SILC session detachment data indicated by `detach_data' to the | |
1839 application. If application has issued SILC_COMMAND_DETACH command | |
1840 the client session in the SILC network is not quit. The client remains | |
1841 in the network but is detached. The detachment data may be used later | |
1842 to resume the session in the SILC Network. The appliation is | |
1843 responsible of saving the `detach_data', to for example in a file. | |
1844 | |
1845 The detachment data can be given as argument to the functions | |
1846 silc_client_connect_to_server, or silc_client_add_connection when | |
1847 creating connection to remote server, inside SilcClientConnectionParams | |
1848 structure. If it is provided the client library will attempt to resume | |
1849 the session in the network. After the connection is created | |
1850 successfully, the application is responsible of setting the user | |
1851 interface for user into the same state it was before detaching (showing | |
1852 same channels, channel modes, etc). It can do this by fetching the | |
1853 information (like joined channels) from the client library. */ | |
1854 | |
1855 static void | |
1856 silc_detach(SilcClient client, SilcClientConnection conn, | |
1857 const unsigned char *detach_data, SilcUInt32 detach_data_len) | |
1858 { | |
1859 GaimConnection *gc = client->application; | |
1860 SilcGaim sg = gc->proto_data; | |
1861 const char *file; | |
1862 | |
1863 /* Save the detachment data to file. */ | |
1864 file = silcgaim_session_file(gaim_account_get_username(sg->account)); | |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10336
diff
changeset
|
1865 g_unlink(file); |
11488 | 1866 silc_file_writefile(file, (char *)detach_data, detach_data_len); |
8849 | 1867 } |
1868 | |
1869 SilcClientOperations ops = { | |
1870 silc_say, | |
1871 silc_channel_message, | |
1872 silc_private_message, | |
1873 silc_notify, | |
1874 silc_command, | |
1875 silc_command_reply, | |
1876 silc_connected, | |
1877 silc_disconnected, | |
1878 silc_get_auth_method, | |
1879 silc_verify_public_key, | |
1880 silc_ask_passphrase, | |
1881 silc_failure, | |
1882 silc_key_agreement, | |
1883 silc_ftp, | |
1884 silc_detach | |
1885 }; |