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