Mercurial > pidgin
annotate src/protocols/silc/chat.c @ 13967:99b9b58b19dd
[gaim-migrate @ 16523]
Fix a crazy MSN crash. Basically it's possible to have more than one
slplink associated with a given switchboard, but our code did not
allow for that. I think it happens when you're in a multi-user
chat and you do stuff with multiple users that involves slplinks.
Like maybe file transfer and buddy icon related stuff.
Tracking this down took an ungodly amount of time, but thanks to
Meebo for letting me do it :-)
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 20 Jul 2006 07:31:15 +0000 |
parents | 85267a333422 |
children |
rev | line source |
---|---|
8849 | 1 /* |
2 | |
3 silcgaim_chat.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 /***************************** Channel Routines ******************************/ | |
26 | |
27 GList *silcgaim_chat_info(GaimConnection *gc) | |
28 { | |
29 GList *ci = NULL; | |
30 struct proto_chat_entry *pce; | |
31 | |
32 pce = g_new0(struct proto_chat_entry, 1); | |
33 pce->label = _("_Channel:"); | |
34 pce->identifier = "channel"; | |
10519 | 35 pce->required = TRUE; |
8849 | 36 ci = g_list_append(ci, pce); |
37 | |
38 pce = g_new0(struct proto_chat_entry, 1); | |
39 pce->label = _("_Passphrase:"); | |
40 pce->identifier = "passphrase"; | |
41 pce->secret = TRUE; | |
42 ci = g_list_append(ci, pce); | |
43 | |
44 return ci; | |
45 } | |
46 | |
9754 | 47 GHashTable *silcgaim_chat_info_defaults(GaimConnection *gc, const char *chat_name) |
48 { | |
49 GHashTable *defaults; | |
50 | |
51 defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); | |
52 | |
53 if (chat_name != NULL) | |
54 g_hash_table_insert(defaults, "channel", g_strdup(chat_name)); | |
55 | |
56 return defaults; | |
57 } | |
58 | |
8849 | 59 static void |
9038 | 60 silcgaim_chat_getinfo(GaimConnection *gc, GHashTable *components); |
8849 | 61 |
62 static void | |
63 silcgaim_chat_getinfo_res(SilcClient client, | |
64 SilcClientConnection conn, | |
65 SilcChannelEntry *channels, | |
66 SilcUInt32 channels_count, | |
67 void *context) | |
68 { | |
69 GHashTable *components = context; | |
70 GaimConnection *gc = client->application; | |
71 const char *chname; | |
72 char tmp[256]; | |
73 | |
74 chname = g_hash_table_lookup(components, "channel"); | |
75 if (!chname) | |
76 return; | |
77 | |
78 if (!channels) { | |
79 g_snprintf(tmp, sizeof(tmp), | |
80 _("Channel %s does not exist in the network"), chname); | |
81 gaim_notify_error(gc, _("Channel Information"), | |
82 _("Cannot get channel information"), tmp); | |
83 return; | |
84 } | |
85 | |
86 silcgaim_chat_getinfo(gc, components); | |
87 } | |
88 | |
9038 | 89 |
8849 | 90 static void |
9038 | 91 silcgaim_chat_getinfo(GaimConnection *gc, GHashTable *components) |
8849 | 92 { |
9038 | 93 SilcGaim sg = gc->proto_data; |
8849 | 94 const char *chname; |
9488 | 95 char *buf, tmp[256], *tmp2; |
8849 | 96 GString *s; |
97 SilcChannelEntry channel; | |
98 SilcHashTableList htl; | |
99 SilcChannelUser chu; | |
100 | |
9038 | 101 if (!components) |
102 return; | |
8849 | 103 |
9038 | 104 chname = g_hash_table_lookup(components, "channel"); |
8849 | 105 if (!chname) |
106 return; | |
107 channel = silc_client_get_channel(sg->client, sg->conn, | |
108 (char *)chname); | |
109 if (!channel) { | |
110 silc_client_get_channel_resolve(sg->client, sg->conn, | |
111 (char *)chname, | |
112 silcgaim_chat_getinfo_res, | |
9038 | 113 components); |
8849 | 114 return; |
115 } | |
116 | |
117 s = g_string_new(""); | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10662
diff
changeset
|
118 tmp2 = g_markup_escape_text(channel->channel_name, -1); |
9488 | 119 g_string_append_printf(s, _("<b>Channel Name:</b> %s"), tmp2); |
120 g_free(tmp2); | |
8849 | 121 if (channel->user_list && silc_hash_table_count(channel->user_list)) |
9488 | 122 g_string_append_printf(s, _("<br><b>User Count:</b> %d"), |
8849 | 123 (int)silc_hash_table_count(channel->user_list)); |
124 | |
125 silc_hash_table_list(channel->user_list, &htl); | |
126 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
127 if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) { | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10662
diff
changeset
|
128 tmp2 = g_markup_escape_text(chu->client->nickname, -1); |
9488 | 129 g_string_append_printf(s, _("<br><b>Channel Founder:</b> %s"), |
130 tmp2); | |
131 g_free(tmp2); | |
8849 | 132 break; |
133 } | |
134 } | |
135 silc_hash_table_list_reset(&htl); | |
136 | |
137 if (channel->channel_key) | |
9488 | 138 g_string_append_printf(s, _("<br><b>Channel Cipher:</b> %s"), |
8849 | 139 silc_cipher_get_name(channel->channel_key)); |
140 if (channel->hmac) | |
13700
85267a333422
[gaim-migrate @ 16103]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
141 /* Definition of HMAC: http://en.wikipedia.org/wiki/HMAC */ |
9488 | 142 g_string_append_printf(s, _("<br><b>Channel HMAC:</b> %s"), |
8849 | 143 silc_hmac_get_name(channel->hmac)); |
144 | |
9488 | 145 if (channel->topic) { |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10662
diff
changeset
|
146 tmp2 = g_markup_escape_text(channel->topic, -1); |
9488 | 147 g_string_append_printf(s, _("<br><b>Channel Topic:</b><br>%s"), tmp2); |
148 g_free(tmp2); | |
149 } | |
8849 | 150 |
151 if (channel->mode) { | |
9488 | 152 g_string_append_printf(s, _("<br><b>Channel Modes:</b> ")); |
8849 | 153 silcgaim_get_chmode_string(channel->mode, tmp, sizeof(tmp)); |
12317
1baf4cbcf84d
[gaim-migrate @ 14621]
Richard Laager <rlaager@wiktel.com>
parents:
12216
diff
changeset
|
154 g_string_append(s, tmp); |
8849 | 155 } |
156 | |
157 if (channel->founder_key) { | |
158 char *fingerprint, *babbleprint; | |
159 unsigned char *pk; | |
160 SilcUInt32 pk_len; | |
161 pk = silc_pkcs_public_key_encode(channel->founder_key, &pk_len); | |
162 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); | |
163 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); | |
164 | |
9488 | 165 g_string_append_printf(s, _("<br><b>Founder Key Fingerprint:</b><br>%s"), fingerprint); |
166 g_string_append_printf(s, _("<br><b>Founder Key Babbleprint:</b><br>%s"), babbleprint); | |
8849 | 167 |
168 silc_free(fingerprint); | |
169 silc_free(babbleprint); | |
170 silc_free(pk); | |
171 } | |
172 | |
173 buf = g_string_free(s, FALSE); | |
9488 | 174 gaim_notify_formatted(gc, NULL, _("Channel Information"), NULL, buf, NULL, NULL); |
8849 | 175 g_free(buf); |
176 } | |
177 | |
178 | |
9038 | 179 static void |
180 silcgaim_chat_getinfo_menu(GaimBlistNode *node, gpointer data) | |
181 { | |
9272 | 182 GaimChat *chat = (GaimChat *)node; |
183 silcgaim_chat_getinfo(chat->account->gc, chat->components); | |
9038 | 184 } |
185 | |
186 | |
8849 | 187 #if 0 /* XXX For now these are not implemented. We need better |
188 listview dialog from Gaim for these. */ | |
189 /************************** Channel Invite List ******************************/ | |
190 | |
191 static void | |
9030 | 192 silcgaim_chat_invitelist(GaimBlistNode *node, gpointer data); |
8849 | 193 { |
194 | |
195 } | |
196 | |
197 | |
198 /**************************** Channel Ban List *******************************/ | |
199 | |
200 static void | |
9030 | 201 silcgaim_chat_banlist(GaimBlistNode *node, gpointer data); |
8849 | 202 { |
203 | |
204 } | |
205 #endif | |
206 | |
207 | |
208 /************************* Channel Authentication ****************************/ | |
209 | |
210 typedef struct { | |
211 SilcGaim sg; | |
212 SilcChannelEntry channel; | |
213 GaimChat *c; | |
214 SilcBuffer pubkeys; | |
215 } *SilcGaimChauth; | |
216 | |
217 static void | |
218 silcgaim_chat_chpk_add(void *user_data, const char *name) | |
219 { | |
220 SilcGaimChauth sgc = (SilcGaimChauth)user_data; | |
221 SilcGaim sg = sgc->sg; | |
222 SilcClient client = sg->client; | |
223 SilcClientConnection conn = sg->conn; | |
224 SilcPublicKey public_key; | |
225 SilcBuffer chpks, pk, chidp; | |
226 unsigned char mode[4]; | |
227 SilcUInt32 m; | |
228 | |
229 /* Load the public key */ | |
230 if (!silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_PEM) && | |
231 !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) { | |
232 silcgaim_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys); | |
233 silc_buffer_free(sgc->pubkeys); | |
234 silc_free(sgc); | |
235 gaim_notify_error(client->application, | |
236 _("Add Channel Public Key"), | |
237 _("Could not load public key"), NULL); | |
238 return; | |
239 } | |
240 | |
241 pk = silc_pkcs_public_key_payload_encode(public_key); | |
242 chpks = silc_buffer_alloc_size(2); | |
243 SILC_PUT16_MSB(1, chpks->head); | |
244 chpks = silc_argument_payload_encode_one(chpks, pk->data, | |
245 pk->len, 0x00); | |
246 silc_buffer_free(pk); | |
247 | |
248 m = sgc->channel->mode; | |
249 m |= SILC_CHANNEL_MODE_CHANNEL_AUTH; | |
250 | |
251 /* Send CMODE */ | |
252 SILC_PUT32_MSB(m, mode); | |
253 chidp = silc_id_payload_encode(sgc->channel->id, SILC_ID_CHANNEL); | |
254 silc_client_command_send(client, conn, SILC_COMMAND_CMODE, | |
255 ++conn->cmd_ident, 3, | |
256 1, chidp->data, chidp->len, | |
257 2, mode, sizeof(mode), | |
258 9, chpks->data, chpks->len); | |
259 silc_buffer_free(chpks); | |
260 silc_buffer_free(chidp); | |
261 silc_buffer_free(sgc->pubkeys); | |
262 silc_free(sgc); | |
263 } | |
264 | |
265 static void | |
266 silcgaim_chat_chpk_cancel(void *user_data, const char *name) | |
267 { | |
268 SilcGaimChauth sgc = (SilcGaimChauth)user_data; | |
269 silcgaim_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys); | |
270 silc_buffer_free(sgc->pubkeys); | |
271 silc_free(sgc); | |
272 } | |
273 | |
274 static void | |
275 silcgaim_chat_chpk_cb(SilcGaimChauth sgc, GaimRequestFields *fields) | |
276 { | |
277 SilcGaim sg = sgc->sg; | |
278 SilcClient client = sg->client; | |
279 SilcClientConnection conn = sg->conn; | |
280 GaimRequestField *f; | |
281 const GList *list; | |
282 SilcPublicKey public_key; | |
283 SilcBuffer chpks, pk, chidp; | |
284 SilcUInt16 c = 0, ct; | |
285 unsigned char mode[4]; | |
286 SilcUInt32 m; | |
287 | |
288 f = gaim_request_fields_get_field(fields, "list"); | |
289 if (!gaim_request_field_list_get_selected(f)) { | |
290 /* Add new public key */ | |
11201 | 291 gaim_request_file(sg->gc, _("Open Public Key..."), NULL, FALSE, |
8849 | 292 G_CALLBACK(silcgaim_chat_chpk_add), |
293 G_CALLBACK(silcgaim_chat_chpk_cancel), sgc); | |
294 return; | |
295 } | |
296 | |
297 list = gaim_request_field_list_get_items(f); | |
298 chpks = silc_buffer_alloc_size(2); | |
299 | |
300 for (ct = 0; list; list = list->next, ct++) { | |
301 public_key = gaim_request_field_list_get_data(f, list->data); | |
302 if (gaim_request_field_list_is_selected(f, list->data)) { | |
303 /* Delete this public key */ | |
304 pk = silc_pkcs_public_key_payload_encode(public_key); | |
305 chpks = silc_argument_payload_encode_one(chpks, pk->data, | |
306 pk->len, 0x01); | |
307 silc_buffer_free(pk); | |
308 c++; | |
309 } | |
310 silc_pkcs_public_key_free(public_key); | |
311 } | |
312 if (!c) { | |
313 silc_buffer_free(chpks); | |
314 return; | |
315 } | |
316 SILC_PUT16_MSB(c, chpks->head); | |
317 | |
318 m = sgc->channel->mode; | |
319 if (ct == c) | |
320 m &= ~SILC_CHANNEL_MODE_CHANNEL_AUTH; | |
321 | |
322 /* Send CMODE */ | |
323 SILC_PUT32_MSB(m, mode); | |
324 chidp = silc_id_payload_encode(sgc->channel->id, SILC_ID_CHANNEL); | |
325 silc_client_command_send(client, conn, SILC_COMMAND_CMODE, | |
326 ++conn->cmd_ident, 3, | |
327 1, chidp->data, chidp->len, | |
328 2, mode, sizeof(mode), | |
329 9, chpks->data, chpks->len); | |
330 silc_buffer_free(chpks); | |
331 silc_buffer_free(chidp); | |
332 silc_buffer_free(sgc->pubkeys); | |
333 silc_free(sgc); | |
334 } | |
335 | |
336 static void | |
337 silcgaim_chat_chauth_ok(SilcGaimChauth sgc, GaimRequestFields *fields) | |
338 { | |
339 SilcGaim sg = sgc->sg; | |
340 GaimRequestField *f; | |
341 const char *curpass, *val; | |
342 int set; | |
343 | |
344 f = gaim_request_fields_get_field(fields, "passphrase"); | |
345 val = gaim_request_field_string_get_value(f); | |
346 curpass = gaim_blist_node_get_string((GaimBlistNode *)sgc->c, "passphrase"); | |
347 | |
348 if (!val && curpass) | |
349 set = 0; | |
350 else if (val && !curpass) | |
351 set = 1; | |
352 else if (val && curpass && strcmp(val, curpass)) | |
353 set = 1; | |
354 else | |
355 set = -1; | |
356 | |
357 if (set == 1) { | |
358 silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", | |
359 sgc->channel->channel_name, "+a", val, NULL); | |
360 gaim_blist_node_set_string((GaimBlistNode *)sgc->c, "passphrase", val); | |
361 } else if (set == 0) { | |
362 silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", | |
363 sgc->channel->channel_name, "-a", NULL); | |
364 gaim_blist_node_remove_setting((GaimBlistNode *)sgc->c, "passphrase"); | |
365 } | |
366 | |
367 silc_buffer_free(sgc->pubkeys); | |
368 silc_free(sgc); | |
369 } | |
370 | |
371 void silcgaim_chat_chauth_show(SilcGaim sg, SilcChannelEntry channel, | |
372 SilcBuffer channel_pubkeys) | |
373 { | |
374 SilcUInt16 argc; | |
375 SilcArgumentPayload chpks; | |
376 unsigned char *pk; | |
377 SilcUInt32 pk_len, type; | |
378 char *fingerprint, *babbleprint; | |
379 SilcPublicKey pubkey; | |
380 SilcPublicKeyIdentifier ident; | |
381 char tmp2[1024], t[512]; | |
382 GaimRequestFields *fields; | |
383 GaimRequestFieldGroup *g; | |
384 GaimRequestField *f; | |
385 SilcGaimChauth sgc; | |
386 const char *curpass = NULL; | |
387 | |
388 sgc = silc_calloc(1, sizeof(*sgc)); | |
389 if (!sgc) | |
390 return; | |
391 sgc->sg = sg; | |
392 sgc->channel = channel; | |
393 | |
394 fields = gaim_request_fields_new(); | |
395 | |
396 if (sgc->c) | |
397 curpass = gaim_blist_node_get_string((GaimBlistNode *)sgc->c, "passphrase"); | |
398 | |
399 g = gaim_request_field_group_new(NULL); | |
400 f = gaim_request_field_string_new("passphrase", _("Channel Passphrase"), | |
401 curpass, FALSE); | |
402 gaim_request_field_string_set_masked(f, TRUE); | |
403 gaim_request_field_group_add_field(g, f); | |
404 gaim_request_fields_add_group(fields, g); | |
405 | |
406 g = gaim_request_field_group_new(NULL); | |
407 f = gaim_request_field_label_new("l1", _("Channel Public Keys List")); | |
408 gaim_request_field_group_add_field(g, f); | |
409 gaim_request_fields_add_group(fields, g); | |
410 | |
411 g_snprintf(t, sizeof(t), | |
412 _("Channel authentication is used to secure the channel from " | |
413 "unauthorized access. The authentication may be based on " | |
414 "passphrase and digital signatures. If passphrase is set, it " | |
415 "is required to be able to join. If channel public keys are set " | |
416 "then only users whose public keys are listed are able to join.")); | |
417 | |
418 if (!channel_pubkeys) { | |
419 f = gaim_request_field_list_new("list", NULL); | |
420 gaim_request_field_group_add_field(g, f); | |
11201 | 421 gaim_request_fields(sg->gc, _("Channel Authentication"), |
8849 | 422 _("Channel Authentication"), t, fields, |
9275 | 423 _("Add / Remove"), G_CALLBACK(silcgaim_chat_chpk_cb), |
424 _("OK"), G_CALLBACK(silcgaim_chat_chauth_ok), sgc); | |
8849 | 425 return; |
426 } | |
427 sgc->pubkeys = silc_buffer_copy(channel_pubkeys); | |
428 | |
429 g = gaim_request_field_group_new(NULL); | |
430 f = gaim_request_field_list_new("list", NULL); | |
431 gaim_request_field_group_add_field(g, f); | |
432 gaim_request_fields_add_group(fields, g); | |
433 | |
434 SILC_GET16_MSB(argc, channel_pubkeys->data); | |
435 chpks = silc_argument_payload_parse(channel_pubkeys->data + 2, | |
436 channel_pubkeys->len - 2, argc); | |
437 if (!chpks) | |
438 return; | |
439 | |
440 pk = silc_argument_get_first_arg(chpks, &type, &pk_len); | |
441 while (pk) { | |
442 fingerprint = silc_hash_fingerprint(NULL, pk + 4, pk_len - 4); | |
443 babbleprint = silc_hash_babbleprint(NULL, pk + 4, pk_len - 4); | |
444 silc_pkcs_public_key_payload_decode(pk, pk_len, &pubkey); | |
445 ident = silc_pkcs_decode_identifier(pubkey->identifier); | |
446 | |
447 g_snprintf(tmp2, sizeof(tmp2), "%s\n %s\n %s", | |
448 ident->realname ? ident->realname : ident->username ? | |
449 ident->username : "", fingerprint, babbleprint); | |
450 gaim_request_field_list_add(f, tmp2, pubkey); | |
451 | |
452 silc_free(fingerprint); | |
453 silc_free(babbleprint); | |
454 silc_pkcs_free_identifier(ident); | |
455 pk = silc_argument_get_next_arg(chpks, &type, &pk_len); | |
456 } | |
457 | |
458 gaim_request_field_list_set_multi_select(f, FALSE); | |
11201 | 459 gaim_request_fields(sg->gc, _("Channel Authentication"), |
8849 | 460 _("Channel Authentication"), t, fields, |
9275 | 461 _("Add / Remove"), G_CALLBACK(silcgaim_chat_chpk_cb), |
462 _("OK"), G_CALLBACK(silcgaim_chat_chauth_ok), sgc); | |
8849 | 463 |
464 silc_argument_payload_free(chpks); | |
465 } | |
466 | |
467 static void | |
9030 | 468 silcgaim_chat_chauth(GaimBlistNode *node, gpointer data) |
8849 | 469 { |
9030 | 470 GaimChat *chat; |
471 GaimConnection *gc; | |
472 SilcGaim sg; | |
473 | |
474 g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node)); | |
475 | |
476 chat = (GaimChat *) node; | |
477 gc = gaim_account_get_connection(chat->account); | |
478 sg = gc->proto_data; | |
479 | |
8849 | 480 silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", |
9030 | 481 g_hash_table_lookup(chat->components, "channel"), |
8849 | 482 "+C", NULL); |
483 } | |
484 | |
485 | |
486 /************************** Channel Private Groups **************************/ | |
487 | |
488 /* Private groups are "virtual" channels. They are groups inside a channel. | |
489 This is implemented by using channel private keys. By knowing a channel | |
490 private key user becomes part of that group and is able to talk on that | |
491 group. Other users, on the same channel, won't be able to see the | |
492 messages of that group. It is possible to have multiple groups inside | |
493 a channel - and thus having multiple private keys on the channel. */ | |
494 | |
495 typedef struct { | |
496 SilcGaim sg; | |
497 GaimChat *c; | |
498 const char *channel; | |
499 } *SilcGaimCharPrv; | |
500 | |
501 static void | |
502 silcgaim_chat_prv_add(SilcGaimCharPrv p, GaimRequestFields *fields) | |
503 { | |
504 SilcGaim sg = p->sg; | |
505 char tmp[512]; | |
506 GaimRequestField *f; | |
507 const char *name, *passphrase, *alias; | |
508 GHashTable *comp; | |
509 GaimGroup *g; | |
510 GaimChat *cn; | |
511 | |
512 f = gaim_request_fields_get_field(fields, "name"); | |
513 name = gaim_request_field_string_get_value(f); | |
514 if (!name) { | |
515 silc_free(p); | |
516 return; | |
517 } | |
518 f = gaim_request_fields_get_field(fields, "passphrase"); | |
519 passphrase = gaim_request_field_string_get_value(f); | |
520 f = gaim_request_fields_get_field(fields, "alias"); | |
521 alias = gaim_request_field_string_get_value(f); | |
522 | |
523 /* Add private group to buddy list */ | |
524 g_snprintf(tmp, sizeof(tmp), "%s [Private Group]", name); | |
525 comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | |
526 g_hash_table_replace(comp, g_strdup("channel"), g_strdup(tmp)); | |
527 g_hash_table_replace(comp, g_strdup("passphrase"), g_strdup(passphrase)); | |
528 | |
529 cn = gaim_chat_new(sg->account, alias, comp); | |
530 g = (GaimGroup *)p->c->node.parent; | |
531 gaim_blist_add_chat(cn, g, (GaimBlistNode *)p->c); | |
532 | |
533 /* Associate to a real channel */ | |
534 gaim_blist_node_set_string((GaimBlistNode *)cn, "parentch", p->channel); | |
535 | |
536 /* Join the group */ | |
537 silcgaim_chat_join(sg->gc, comp); | |
538 | |
539 silc_free(p); | |
540 } | |
541 | |
542 static void | |
543 silcgaim_chat_prv_cancel(SilcGaimCharPrv p, GaimRequestFields *fields) | |
544 { | |
545 silc_free(p); | |
546 } | |
547 | |
548 static void | |
9030 | 549 silcgaim_chat_prv(GaimBlistNode *node, gpointer data) |
8849 | 550 { |
9030 | 551 GaimChat *chat; |
552 GaimConnection *gc; | |
553 SilcGaim sg; | |
554 | |
8849 | 555 SilcGaimCharPrv p; |
556 GaimRequestFields *fields; | |
557 GaimRequestFieldGroup *g; | |
558 GaimRequestField *f; | |
559 char tmp[512]; | |
560 | |
9030 | 561 g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node)); |
562 | |
563 chat = (GaimChat *) node; | |
564 gc = gaim_account_get_connection(chat->account); | |
565 sg = gc->proto_data; | |
566 | |
8849 | 567 p = silc_calloc(1, sizeof(*p)); |
568 if (!p) | |
569 return; | |
570 p->sg = sg; | |
571 | |
9030 | 572 p->channel = g_hash_table_lookup(chat->components, "channel"); |
8849 | 573 p->c = gaim_blist_find_chat(sg->account, p->channel); |
574 | |
575 fields = gaim_request_fields_new(); | |
576 | |
577 g = gaim_request_field_group_new(NULL); | |
578 f = gaim_request_field_string_new("name", _("Group Name"), | |
579 NULL, FALSE); | |
580 gaim_request_field_group_add_field(g, f); | |
581 | |
582 f = gaim_request_field_string_new("passphrase", _("Passphrase"), | |
583 NULL, FALSE); | |
584 gaim_request_field_string_set_masked(f, TRUE); | |
585 gaim_request_field_group_add_field(g, f); | |
586 | |
587 f = gaim_request_field_string_new("alias", _("Alias"), | |
588 NULL, FALSE); | |
589 gaim_request_field_group_add_field(g, f); | |
590 gaim_request_fields_add_group(fields, g); | |
591 | |
592 g_snprintf(tmp, sizeof(tmp), | |
593 _("Please enter the %s channel private group name and passphrase."), | |
594 p->channel); | |
11201 | 595 gaim_request_fields(gc, _("Add Channel Private Group"), NULL, tmp, fields, |
9275 | 596 _("Add"), G_CALLBACK(silcgaim_chat_prv_add), |
597 _("Cancel"), G_CALLBACK(silcgaim_chat_prv_cancel), p); | |
8849 | 598 } |
599 | |
600 | |
601 /****************************** Channel Modes ********************************/ | |
602 | |
603 static void | |
9030 | 604 silcgaim_chat_permanent_reset(GaimBlistNode *node, gpointer data) |
8849 | 605 { |
9030 | 606 GaimChat *chat; |
607 GaimConnection *gc; | |
608 SilcGaim sg; | |
609 | |
610 g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node)); | |
611 | |
612 chat = (GaimChat *) node; | |
613 gc = gaim_account_get_connection(chat->account); | |
614 sg = gc->proto_data; | |
615 | |
8849 | 616 silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", |
9030 | 617 g_hash_table_lookup(chat->components, "channel"), |
8849 | 618 "-f", NULL); |
619 } | |
620 | |
621 static void | |
9030 | 622 silcgaim_chat_permanent(GaimBlistNode *node, gpointer data) |
8849 | 623 { |
9030 | 624 GaimChat *chat; |
625 GaimConnection *gc; | |
626 SilcGaim sg; | |
8849 | 627 const char *channel; |
628 | |
9030 | 629 g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node)); |
630 | |
631 chat = (GaimChat *) node; | |
632 gc = gaim_account_get_connection(chat->account); | |
633 sg = gc->proto_data; | |
634 | |
8849 | 635 if (!sg->conn) |
636 return; | |
637 | |
638 /* XXX we should have ability to define which founder | |
639 key to use. Now we use the user's own public key | |
640 (default key). */ | |
641 | |
642 /* Call CMODE */ | |
9030 | 643 channel = g_hash_table_lookup(chat->components, "channel"); |
8849 | 644 silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", channel, |
645 "+f", NULL); | |
646 } | |
647 | |
648 typedef struct { | |
649 SilcGaim sg; | |
650 const char *channel; | |
651 } *SilcGaimChatInput; | |
652 | |
653 static void | |
654 silcgaim_chat_ulimit_cb(SilcGaimChatInput s, const char *limit) | |
655 { | |
656 SilcChannelEntry channel; | |
657 int ulimit = 0; | |
658 | |
659 channel = silc_client_get_channel(s->sg->client, s->sg->conn, | |
660 (char *)s->channel); | |
661 if (!channel) | |
662 return; | |
663 if (limit) | |
664 ulimit = atoi(limit); | |
665 | |
666 if (!limit || !(*limit) || *limit == '0') { | |
667 if (limit && ulimit == channel->user_limit) { | |
668 silc_free(s); | |
669 return; | |
670 } | |
671 silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE", | |
672 s->channel, "-l", NULL); | |
673 | |
674 silc_free(s); | |
675 return; | |
676 } | |
677 | |
678 if (ulimit == channel->user_limit) { | |
679 silc_free(s); | |
680 return; | |
681 } | |
682 | |
683 /* Call CMODE */ | |
684 silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE", | |
685 s->channel, "+l", limit, NULL); | |
686 | |
687 silc_free(s); | |
688 } | |
689 | |
690 static void | |
9030 | 691 silcgaim_chat_ulimit(GaimBlistNode *node, gpointer data) |
8849 | 692 { |
9030 | 693 GaimChat *chat; |
694 GaimConnection *gc; | |
695 SilcGaim sg; | |
696 | |
8849 | 697 SilcGaimChatInput s; |
698 SilcChannelEntry channel; | |
699 const char *ch; | |
700 char tmp[32]; | |
701 | |
9030 | 702 g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node)); |
703 | |
704 chat = (GaimChat *) node; | |
705 gc = gaim_account_get_connection(chat->account); | |
706 sg = gc->proto_data; | |
707 | |
8849 | 708 if (!sg->conn) |
709 return; | |
710 | |
9030 | 711 ch = g_strdup(g_hash_table_lookup(chat->components, "channel")); |
8849 | 712 channel = silc_client_get_channel(sg->client, sg->conn, (char *)ch); |
713 if (!channel) | |
714 return; | |
715 | |
716 s = silc_calloc(1, sizeof(*s)); | |
717 if (!s) | |
718 return; | |
719 s->channel = ch; | |
720 s->sg = sg; | |
721 g_snprintf(tmp, sizeof(tmp), "%d", (int)channel->user_limit); | |
11201 | 722 gaim_request_input(gc, _("User Limit"), NULL, |
8849 | 723 _("Set user limit on channel. Set to zero to reset user limit."), |
724 tmp, FALSE, FALSE, NULL, | |
725 _("OK"), G_CALLBACK(silcgaim_chat_ulimit_cb), | |
726 _("Cancel"), G_CALLBACK(silcgaim_chat_ulimit_cb), s); | |
727 } | |
728 | |
729 static void | |
9030 | 730 silcgaim_chat_resettopic(GaimBlistNode *node, gpointer data) |
8849 | 731 { |
9030 | 732 GaimChat *chat; |
733 GaimConnection *gc; | |
734 SilcGaim sg; | |
735 | |
736 g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node)); | |
737 | |
738 chat = (GaimChat *) node; | |
739 gc = gaim_account_get_connection(chat->account); | |
740 sg = gc->proto_data; | |
741 | |
8849 | 742 silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", |
9030 | 743 g_hash_table_lookup(chat->components, "channel"), |
8849 | 744 "-t", NULL); |
745 } | |
746 | |
747 static void | |
9030 | 748 silcgaim_chat_settopic(GaimBlistNode *node, gpointer data) |
8849 | 749 { |
9030 | 750 GaimChat *chat; |
751 GaimConnection *gc; | |
752 SilcGaim sg; | |
753 | |
754 g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node)); | |
755 | |
756 chat = (GaimChat *) node; | |
757 gc = gaim_account_get_connection(chat->account); | |
758 sg = gc->proto_data; | |
759 | |
8849 | 760 silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", |
9030 | 761 g_hash_table_lookup(chat->components, "channel"), |
8849 | 762 "+t", NULL); |
763 } | |
764 | |
765 static void | |
9030 | 766 silcgaim_chat_resetprivate(GaimBlistNode *node, gpointer data) |
8849 | 767 { |
9030 | 768 GaimChat *chat; |
769 GaimConnection *gc; | |
770 SilcGaim sg; | |
771 | |
772 g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node)); | |
773 | |
774 chat = (GaimChat *) node; | |
775 gc = gaim_account_get_connection(chat->account); | |
776 sg = gc->proto_data; | |
777 | |
8849 | 778 silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", |
9030 | 779 g_hash_table_lookup(chat->components, "channel"), |
8849 | 780 "-p", NULL); |
781 } | |
782 | |
783 static void | |
9030 | 784 silcgaim_chat_setprivate(GaimBlistNode *node, gpointer data) |
8849 | 785 { |
9030 | 786 GaimChat *chat; |
787 GaimConnection *gc; | |
788 SilcGaim sg; | |
789 | |
790 g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node)); | |
791 | |
792 chat = (GaimChat *) node; | |
793 gc = gaim_account_get_connection(chat->account); | |
794 sg = gc->proto_data; | |
795 | |
8849 | 796 silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", |
9030 | 797 g_hash_table_lookup(chat->components, "channel"), |
8849 | 798 "+p", NULL); |
799 } | |
800 | |
801 static void | |
9030 | 802 silcgaim_chat_resetsecret(GaimBlistNode *node, gpointer data) |
8849 | 803 { |
9030 | 804 GaimChat *chat; |
805 GaimConnection *gc; | |
806 SilcGaim sg; | |
807 | |
808 g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node)); | |
809 | |
810 chat = (GaimChat *) node; | |
811 gc = gaim_account_get_connection(chat->account); | |
812 sg = gc->proto_data; | |
813 | |
8849 | 814 silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", |
9030 | 815 g_hash_table_lookup(chat->components, "channel"), |
8849 | 816 "-s", NULL); |
817 } | |
818 | |
819 static void | |
9030 | 820 silcgaim_chat_setsecret(GaimBlistNode *node, gpointer data) |
8849 | 821 { |
9030 | 822 GaimChat *chat; |
823 GaimConnection *gc; | |
824 SilcGaim sg; | |
825 | |
826 g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node)); | |
827 | |
828 chat = (GaimChat *) node; | |
829 gc = gaim_account_get_connection(chat->account); | |
830 sg = gc->proto_data; | |
831 | |
8849 | 832 silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", |
9030 | 833 g_hash_table_lookup(chat->components, "channel"), |
8849 | 834 "+s", NULL); |
835 } | |
836 | |
12058 | 837 typedef struct { |
838 SilcGaim sg; | |
839 SilcChannelEntry channel; | |
840 } *SilcGaimChatWb; | |
841 | |
842 static void | |
843 silcgaim_chat_wb(GaimBlistNode *node, gpointer data) | |
844 { | |
845 SilcGaimChatWb wb = data; | |
846 silcgaim_wb_init_ch(wb->sg, wb->channel); | |
847 silc_free(wb); | |
848 } | |
849 | |
9030 | 850 GList *silcgaim_chat_menu(GaimChat *chat) |
8849 | 851 { |
9038 | 852 GHashTable *components = chat->components; |
9030 | 853 GaimConnection *gc = gaim_account_get_connection(chat->account); |
8849 | 854 SilcGaim sg = gc->proto_data; |
855 SilcClientConnection conn = sg->conn; | |
856 const char *chname = NULL; | |
857 SilcChannelEntry channel = NULL; | |
858 SilcChannelUser chu = NULL; | |
859 SilcUInt32 mode = 0; | |
860 | |
9038 | 861 GList *m = NULL; |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
862 GaimMenuAction *act; |
9030 | 863 |
8849 | 864 if (components) |
865 chname = g_hash_table_lookup(components, "channel"); | |
866 if (chname) | |
867 channel = silc_client_get_channel(sg->client, sg->conn, | |
868 (char *)chname); | |
869 if (channel) { | |
870 chu = silc_client_on_channel(channel, conn->local_entry); | |
871 if (chu) | |
872 mode = chu->mode; | |
873 } | |
874 | |
875 if (strstr(chname, "[Private Group]")) | |
876 return NULL; | |
877 | |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
878 act = gaim_menu_action_new(_("Get Info"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
879 GAIM_CALLBACK(silcgaim_chat_getinfo_menu), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
880 NULL, NULL); |
9030 | 881 m = g_list_append(m, act); |
8849 | 882 |
883 #if 0 /* XXX For now these are not implemented. We need better | |
884 listview dialog from Gaim for these. */ | |
885 if (mode & SILC_CHANNEL_UMODE_CHANOP) { | |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
886 act = gaim_menu_action_new(_("Invite List"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
887 GAIM_CALLBACK(silcgaim_chat_invitelist), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
888 NULL, NULL); |
9030 | 889 m = g_list_append(m, act); |
8849 | 890 |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
891 act = gaim_menu_action_new(_("Ban List"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
892 GAIM_CALLBACK(silcgaim_chat_banlist), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
893 NULL, NULL); |
9030 | 894 m = g_list_append(m, act); |
8849 | 895 } |
896 #endif | |
897 | |
898 if (chu) { | |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
899 act = gaim_menu_action_new(_("Add Private Group"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
900 GAIM_CALLBACK(silcgaim_chat_prv), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
901 NULL, NULL); |
9030 | 902 m = g_list_append(m, act); |
8849 | 903 } |
904 | |
905 if (mode & SILC_CHANNEL_UMODE_CHANFO) { | |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
906 act = gaim_menu_action_new(_("Channel Authentication"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
907 GAIM_CALLBACK(silcgaim_chat_chauth), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
908 NULL, NULL); |
9030 | 909 m = g_list_append(m, act); |
8849 | 910 |
911 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) { | |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
912 act = gaim_menu_action_new(_("Reset Permanent"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
913 GAIM_CALLBACK(silcgaim_chat_permanent_reset), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
914 NULL, NULL); |
9030 | 915 m = g_list_append(m, act); |
8849 | 916 } else { |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
917 act = gaim_menu_action_new(_("Set Permanent"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
918 GAIM_CALLBACK(silcgaim_chat_permanent), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
919 NULL, NULL); |
9030 | 920 m = g_list_append(m, act); |
8849 | 921 } |
922 } | |
923 | |
924 if (mode & SILC_CHANNEL_UMODE_CHANOP) { | |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
925 act = gaim_menu_action_new(_("Set User Limit"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
926 GAIM_CALLBACK(silcgaim_chat_ulimit), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
927 NULL, NULL); |
9030 | 928 m = g_list_append(m, act); |
8849 | 929 |
930 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) { | |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
931 act = gaim_menu_action_new(_("Reset Topic Restriction"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
932 GAIM_CALLBACK(silcgaim_chat_resettopic), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
933 NULL, NULL); |
9030 | 934 m = g_list_append(m, act); |
8849 | 935 } else { |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
936 act = gaim_menu_action_new(_("Set Topic Restriction"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
937 GAIM_CALLBACK(silcgaim_chat_settopic), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
938 NULL, NULL); |
9030 | 939 m = g_list_append(m, act); |
8849 | 940 } |
941 | |
942 if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) { | |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
943 act = gaim_menu_action_new(_("Reset Private Channel"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
944 GAIM_CALLBACK(silcgaim_chat_resetprivate), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
945 NULL, NULL); |
9030 | 946 m = g_list_append(m, act); |
8849 | 947 } else { |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
948 act = gaim_menu_action_new(_("Set Private Channel"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
949 GAIM_CALLBACK(silcgaim_chat_setprivate), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
950 NULL, NULL); |
9030 | 951 m = g_list_append(m, act); |
8849 | 952 } |
953 | |
954 if (channel->mode & SILC_CHANNEL_MODE_SECRET) { | |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
955 act = gaim_menu_action_new(_("Reset Secret Channel"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
956 GAIM_CALLBACK(silcgaim_chat_resetsecret), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
957 NULL, NULL); |
9030 | 958 m = g_list_append(m, act); |
8849 | 959 } else { |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
960 act = gaim_menu_action_new(_("Set Secret Channel"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
961 GAIM_CALLBACK(silcgaim_chat_setsecret), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
962 NULL, NULL); |
9030 | 963 m = g_list_append(m, act); |
8849 | 964 } |
965 } | |
966 | |
12058 | 967 if (channel) { |
968 SilcGaimChatWb wb; | |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
969 wb = silc_calloc(1, sizeof(*wb)); |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
970 wb->sg = sg; |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
971 wb->channel = channel; |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
972 act = gaim_menu_action_new(_("Draw On Whiteboard"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
973 GAIM_CALLBACK(silcgaim_chat_wb), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
974 (void *)wb, NULL); |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12885
diff
changeset
|
975 m = g_list_append(m, act); |
12058 | 976 } |
977 | |
8849 | 978 return m; |
979 } | |
980 | |
981 | |
982 /******************************* Joining Etc. ********************************/ | |
983 | |
984 void silcgaim_chat_join_done(SilcClient client, | |
985 SilcClientConnection conn, | |
986 SilcClientEntry *clients, | |
987 SilcUInt32 clients_count, | |
988 void *context) | |
989 { | |
990 GaimConnection *gc = client->application; | |
991 SilcGaim sg = gc->proto_data; | |
992 SilcChannelEntry channel = context; | |
993 GaimConversation *convo; | |
994 SilcUInt32 retry = SILC_PTR_TO_32(channel->context); | |
995 SilcHashTableList htl; | |
996 SilcChannelUser chu; | |
9554 | 997 GList *users = NULL, *flags = NULL; |
8849 | 998 char tmp[256]; |
999 | |
1000 if (!clients && retry < 1) { | |
1001 /* Resolving users failed, try again. */ | |
1002 channel->context = SILC_32_TO_PTR(retry + 1); | |
1003 silc_client_get_clients_by_channel(client, conn, channel, | |
1004 silcgaim_chat_join_done, channel); | |
1005 return; | |
1006 } | |
1007 | |
1008 /* Add channel to Gaim */ | |
1009 channel->context = SILC_32_TO_PTR(++sg->channel_ids); | |
1010 serv_got_joined_chat(gc, sg->channel_ids, channel->channel_name); | |
11338 | 1011 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 1012 channel->channel_name, sg->account); |
8849 | 1013 if (!convo) |
1014 return; | |
1015 | |
1016 /* Add all users to channel */ | |
1017 silc_hash_table_list(channel->user_list, &htl); | |
1018 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
9554 | 1019 GaimConvChatBuddyFlags f = GAIM_CBFLAGS_NONE; |
8849 | 1020 if (!chu->client->nickname) |
1021 continue; | |
1022 chu->context = SILC_32_TO_PTR(sg->channel_ids); | |
1023 | |
9554 | 1024 if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) |
1025 f |= GAIM_CBFLAGS_FOUNDER; | |
1026 if (chu->mode & SILC_CHANNEL_UMODE_CHANOP) | |
1027 f |= GAIM_CBFLAGS_OP; | |
8849 | 1028 users = g_list_append(users, g_strdup(chu->client->nickname)); |
9554 | 1029 flags = g_list_append(flags, GINT_TO_POINTER(f)); |
8849 | 1030 |
1031 if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) { | |
1032 if (chu->client == conn->local_entry) | |
1033 g_snprintf(tmp, sizeof(tmp), | |
1034 _("You are channel founder on <I>%s</I>"), | |
1035 channel->channel_name); | |
1036 else | |
1037 g_snprintf(tmp, sizeof(tmp), | |
1038 _("Channel founder on <I>%s</I> is <I>%s</I>"), | |
1039 channel->channel_name, chu->client->nickname); | |
1040 | |
1041 gaim_conversation_write(convo, NULL, tmp, | |
1042 GAIM_MESSAGE_SYSTEM, time(NULL)); | |
1043 | |
1044 } | |
1045 } | |
1046 silc_hash_table_list_reset(&htl); | |
1047 | |
11454
201617d49573
[gaim-migrate @ 13693]
Richard Laager <rlaager@wiktel.com>
parents:
11338
diff
changeset
|
1048 gaim_conv_chat_add_users(GAIM_CONV_CHAT(convo), users, NULL, flags, FALSE); |
8849 | 1049 g_list_free(users); |
9554 | 1050 g_list_free(flags); |
8849 | 1051 |
1052 /* Set topic */ | |
1053 if (channel->topic) | |
1054 gaim_conv_chat_set_topic(GAIM_CONV_CHAT(convo), NULL, channel->topic); | |
9353 | 1055 |
1056 /* Set nick */ | |
1057 gaim_conv_chat_set_nick(GAIM_CONV_CHAT(convo), conn->local_entry->nickname); | |
8849 | 1058 } |
1059 | |
9917 | 1060 char *silcgaim_get_chat_name(GHashTable *data) |
1061 { | |
1062 return g_strdup(g_hash_table_lookup(data, "channel")); | |
1063 } | |
1064 | |
8849 | 1065 void silcgaim_chat_join(GaimConnection *gc, GHashTable *data) |
1066 { | |
1067 SilcGaim sg = gc->proto_data; | |
1068 SilcClient client = sg->client; | |
1069 SilcClientConnection conn = sg->conn; | |
1070 const char *channel, *passphrase, *parentch; | |
1071 | |
1072 if (!conn) | |
1073 return; | |
1074 | |
1075 channel = g_hash_table_lookup(data, "channel"); | |
1076 passphrase = g_hash_table_lookup(data, "passphrase"); | |
1077 | |
1078 /* Check if we are joining a private group. Handle it | |
1079 purely locally as it's not a real channel */ | |
1080 if (strstr(channel, "[Private Group]")) { | |
1081 SilcChannelEntry channel_entry; | |
1082 SilcChannelPrivateKey key; | |
1083 GaimChat *c; | |
1084 SilcGaimPrvgrp grp; | |
1085 | |
1086 c = gaim_blist_find_chat(sg->account, channel); | |
1087 parentch = gaim_blist_node_get_string((GaimBlistNode *)c, "parentch"); | |
1088 if (!parentch) | |
1089 return; | |
1090 | |
1091 channel_entry = silc_client_get_channel(sg->client, sg->conn, | |
1092 (char *)parentch); | |
1093 if (!channel_entry || | |
1094 !silc_client_on_channel(channel_entry, sg->conn->local_entry)) { | |
1095 char tmp[512]; | |
1096 g_snprintf(tmp, sizeof(tmp), | |
1097 _("You have to join the %s channel before you are " | |
1098 "able to join the private group"), parentch); | |
1099 gaim_notify_error(gc, _("Join Private Group"), | |
1100 _("Cannot join private group"), tmp); | |
1101 return; | |
1102 } | |
1103 | |
1104 /* Add channel private key */ | |
1105 if (!silc_client_add_channel_private_key(client, conn, | |
1106 channel_entry, channel, | |
1107 NULL, NULL, | |
1108 (unsigned char *)passphrase, | |
1109 strlen(passphrase), &key)) | |
1110 return; | |
1111 | |
1112 /* Join the group */ | |
1113 grp = silc_calloc(1, sizeof(*grp)); | |
1114 if (!grp) | |
1115 return; | |
1116 grp->id = ++sg->channel_ids + SILCGAIM_PRVGRP; | |
1117 grp->chid = SILC_PTR_TO_32(channel_entry->context); | |
1118 grp->parentch = parentch; | |
1119 grp->channel = channel; | |
1120 grp->key = key; | |
1121 sg->grps = g_list_append(sg->grps, grp); | |
1122 serv_got_joined_chat(gc, grp->id, channel); | |
1123 return; | |
1124 } | |
1125 | |
1126 /* XXX We should have other properties here as well: | |
1127 1. whether to try to authenticate to the channel | |
1128 1a. with default key, | |
1129 1b. with specific key. | |
1130 2. whether to try to authenticate to become founder. | |
1131 2a. with default key, | |
1132 2b. with specific key. | |
1133 | |
1134 Since now such variety is not possible in the join dialog | |
1135 we always use -founder and -auth options, which try to | |
1136 do both 1 and 2 with default keys. */ | |
1137 | |
1138 /* Call JOIN */ | |
9172 | 1139 if ((passphrase != NULL) && (*passphrase != '\0')) |
8849 | 1140 silc_client_command_call(client, conn, NULL, "JOIN", |
1141 channel, passphrase, "-auth", "-founder", NULL); | |
1142 else | |
1143 silc_client_command_call(client, conn, NULL, "JOIN", | |
1144 channel, "-auth", "-founder", NULL); | |
1145 } | |
1146 | |
1147 void silcgaim_chat_invite(GaimConnection *gc, int id, const char *msg, | |
1148 const char *name) | |
1149 { | |
1150 SilcGaim sg = gc->proto_data; | |
1151 SilcClient client = sg->client; | |
1152 SilcClientConnection conn = sg->conn; | |
1153 SilcHashTableList htl; | |
1154 SilcChannelUser chu; | |
1155 gboolean found = FALSE; | |
1156 | |
1157 if (!conn) | |
1158 return; | |
1159 | |
1160 /* See if we are inviting on a private group. Invite | |
1161 to the actual channel */ | |
1162 if (id > SILCGAIM_PRVGRP) { | |
1163 GList *l; | |
1164 SilcGaimPrvgrp prv; | |
1165 | |
1166 for (l = sg->grps; l; l = l->next) | |
1167 if (((SilcGaimPrvgrp)l->data)->id == id) | |
1168 break; | |
1169 if (!l) | |
1170 return; | |
1171 prv = l->data; | |
1172 id = prv->chid; | |
1173 } | |
1174 | |
1175 /* Find channel by id */ | |
1176 silc_hash_table_list(conn->local_entry->channels, &htl); | |
1177 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
1178 if (SILC_PTR_TO_32(chu->channel->context) == id ) { | |
1179 found = TRUE; | |
1180 break; | |
1181 } | |
1182 } | |
1183 silc_hash_table_list_reset(&htl); | |
1184 if (!found) | |
1185 return; | |
1186 | |
1187 /* Call INVITE */ | |
1188 silc_client_command_call(client, conn, NULL, "INVITE", | |
1189 chu->channel->channel_name, | |
9353 | 1190 name, NULL); |
8849 | 1191 } |
1192 | |
1193 void silcgaim_chat_leave(GaimConnection *gc, int id) | |
1194 { | |
1195 SilcGaim sg = gc->proto_data; | |
1196 SilcClient client = sg->client; | |
1197 SilcClientConnection conn = sg->conn; | |
1198 SilcHashTableList htl; | |
1199 SilcChannelUser chu; | |
1200 gboolean found = FALSE; | |
1201 GList *l; | |
1202 SilcGaimPrvgrp prv; | |
1203 | |
1204 if (!conn) | |
1205 return; | |
1206 | |
1207 /* See if we are leaving a private group */ | |
1208 if (id > SILCGAIM_PRVGRP) { | |
1209 SilcChannelEntry channel; | |
1210 | |
1211 for (l = sg->grps; l; l = l->next) | |
1212 if (((SilcGaimPrvgrp)l->data)->id == id) | |
1213 break; | |
1214 if (!l) | |
1215 return; | |
1216 prv = l->data; | |
1217 channel = silc_client_get_channel(sg->client, sg->conn, | |
1218 (char *)prv->parentch); | |
1219 if (!channel) | |
1220 return; | |
1221 silc_client_del_channel_private_key(client, conn, | |
1222 channel, prv->key); | |
1223 silc_free(prv); | |
1224 sg->grps = g_list_remove(sg->grps, prv); | |
1225 serv_got_chat_left(gc, id); | |
1226 return; | |
1227 } | |
1228 | |
1229 /* Find channel by id */ | |
1230 silc_hash_table_list(conn->local_entry->channels, &htl); | |
1231 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
1232 if (SILC_PTR_TO_32(chu->channel->context) == id ) { | |
1233 found = TRUE; | |
1234 break; | |
1235 } | |
1236 } | |
1237 silc_hash_table_list_reset(&htl); | |
1238 if (!found) | |
1239 return; | |
1240 | |
1241 /* Call LEAVE */ | |
1242 silc_client_command_call(client, conn, NULL, "LEAVE", | |
1243 chu->channel->channel_name, NULL); | |
1244 | |
1245 serv_got_chat_left(gc, id); | |
1246 | |
1247 /* Leave from private groups on this channel as well */ | |
1248 for (l = sg->grps; l; l = l->next) | |
1249 if (((SilcGaimPrvgrp)l->data)->chid == id) { | |
1250 prv = l->data; | |
1251 silc_client_del_channel_private_key(client, conn, | |
1252 chu->channel, | |
1253 prv->key); | |
1254 serv_got_chat_left(gc, prv->id); | |
1255 silc_free(prv); | |
1256 sg->grps = g_list_remove(sg->grps, prv); | |
1257 if (!sg->grps) | |
1258 break; | |
1259 } | |
1260 } | |
1261 | |
12216 | 1262 int silcgaim_chat_send(GaimConnection *gc, int id, const char *msg, GaimMessageFlags msgflags) |
8849 | 1263 { |
1264 SilcGaim sg = gc->proto_data; | |
1265 SilcClient client = sg->client; | |
1266 SilcClientConnection conn = sg->conn; | |
1267 SilcHashTableList htl; | |
1268 SilcChannelUser chu; | |
1269 SilcChannelEntry channel = NULL; | |
1270 SilcChannelPrivateKey key = NULL; | |
1271 SilcUInt32 flags; | |
1272 int ret; | |
12216 | 1273 char *msg2, *tmp; |
8849 | 1274 gboolean found = FALSE; |
12167 | 1275 gboolean sign = gaim_account_get_bool(sg->account, "sign-verify", FALSE); |
8849 | 1276 |
1277 if (!msg || !conn) | |
1278 return 0; | |
1279 | |
9353 | 1280 flags = SILC_MESSAGE_FLAG_UTF8; |
1281 | |
12216 | 1282 tmp = msg2 = gaim_unescape_html(msg); |
9353 | 1283 |
1284 if (!g_ascii_strncasecmp(msg2, "/me ", 4)) | |
1285 { | |
1286 msg2 += 4; | |
12216 | 1287 if (!*msg2) { |
1288 g_free(tmp); | |
9353 | 1289 return 0; |
12216 | 1290 } |
9353 | 1291 flags |= SILC_MESSAGE_FLAG_ACTION; |
1292 } else if (strlen(msg) > 1 && msg[0] == '/') { | |
8849 | 1293 if (!silc_client_command_call(client, conn, msg + 1)) |
12885 | 1294 gaim_notify_error(gc, _("Call Command"), _("Cannot call command"), |
9353 | 1295 _("Unknown command")); |
12216 | 1296 g_free(tmp); |
8849 | 1297 return 0; |
1298 } | |
1299 | |
9353 | 1300 |
8849 | 1301 if (sign) |
1302 flags |= SILC_MESSAGE_FLAG_SIGNED; | |
1303 | |
1304 /* Get the channel private key if we are sending on | |
1305 private group */ | |
1306 if (id > SILCGAIM_PRVGRP) { | |
1307 GList *l; | |
1308 SilcGaimPrvgrp prv; | |
1309 | |
1310 for (l = sg->grps; l; l = l->next) | |
1311 if (((SilcGaimPrvgrp)l->data)->id == id) | |
1312 break; | |
12216 | 1313 if (!l) { |
1314 g_free(tmp); | |
8849 | 1315 return 0; |
12216 | 1316 } |
8849 | 1317 prv = l->data; |
1318 channel = silc_client_get_channel(sg->client, sg->conn, | |
1319 (char *)prv->parentch); | |
12216 | 1320 if (!channel) { |
1321 g_free(tmp); | |
8849 | 1322 return 0; |
12216 | 1323 } |
8849 | 1324 key = prv->key; |
1325 } | |
1326 | |
1327 if (!channel) { | |
1328 /* Find channel by id */ | |
1329 silc_hash_table_list(conn->local_entry->channels, &htl); | |
1330 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
1331 if (SILC_PTR_TO_32(chu->channel->context) == id ) { | |
1332 found = TRUE; | |
1333 break; | |
1334 } | |
1335 } | |
1336 silc_hash_table_list_reset(&htl); | |
12216 | 1337 if (!found) { |
1338 g_free(tmp); | |
8849 | 1339 return 0; |
12216 | 1340 } |
8849 | 1341 channel = chu->channel; |
1342 } | |
1343 | |
1344 /* Send channel message */ | |
1345 ret = silc_client_send_channel_message(client, conn, channel, key, | |
9353 | 1346 flags, (unsigned char *)msg2, |
1347 strlen(msg2), TRUE); | |
9359 | 1348 if (ret) { |
12216 | 1349 serv_got_chat_in(gc, id, gaim_connection_get_display_name(gc), 0, msg, |
8849 | 1350 time(NULL)); |
9359 | 1351 } |
12216 | 1352 g_free(tmp); |
8849 | 1353 |
1354 return ret; | |
1355 } | |
1356 | |
1357 void silcgaim_chat_set_topic(GaimConnection *gc, int id, const char *topic) | |
1358 { | |
1359 SilcGaim sg = gc->proto_data; | |
1360 SilcClient client = sg->client; | |
1361 SilcClientConnection conn = sg->conn; | |
1362 SilcHashTableList htl; | |
1363 SilcChannelUser chu; | |
1364 gboolean found = FALSE; | |
1365 | |
9353 | 1366 if (!conn) |
8849 | 1367 return; |
1368 | |
1369 /* See if setting topic on private group. Set it | |
1370 on the actual channel */ | |
1371 if (id > SILCGAIM_PRVGRP) { | |
1372 GList *l; | |
1373 SilcGaimPrvgrp prv; | |
1374 | |
1375 for (l = sg->grps; l; l = l->next) | |
1376 if (((SilcGaimPrvgrp)l->data)->id == id) | |
1377 break; | |
1378 if (!l) | |
1379 return; | |
1380 prv = l->data; | |
1381 id = prv->chid; | |
1382 } | |
1383 | |
1384 /* Find channel by id */ | |
1385 silc_hash_table_list(conn->local_entry->channels, &htl); | |
1386 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
1387 if (SILC_PTR_TO_32(chu->channel->context) == id ) { | |
1388 found = TRUE; | |
1389 break; | |
1390 } | |
1391 } | |
1392 silc_hash_table_list_reset(&htl); | |
1393 if (!found) | |
1394 return; | |
1395 | |
1396 /* Call TOPIC */ | |
1397 silc_client_command_call(client, conn, NULL, "TOPIC", | |
1398 chu->channel->channel_name, topic, NULL); | |
1399 } | |
1400 | |
1401 GaimRoomlist *silcgaim_roomlist_get_list(GaimConnection *gc) | |
1402 { | |
1403 SilcGaim sg = gc->proto_data; | |
1404 SilcClient client = sg->client; | |
1405 SilcClientConnection conn = sg->conn; | |
1406 GList *fields = NULL; | |
1407 GaimRoomlistField *f; | |
1408 | |
1409 if (!conn) | |
1410 return NULL; | |
1411 | |
1412 if (sg->roomlist) | |
1413 gaim_roomlist_unref(sg->roomlist); | |
1414 | |
1415 sg->roomlist_canceled = FALSE; | |
1416 | |
1417 sg->roomlist = gaim_roomlist_new(gaim_connection_get_account(gc)); | |
1418 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_STRING, "", "channel", TRUE); | |
1419 fields = g_list_append(fields, f); | |
1420 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_INT, | |
1421 _("Users"), "users", FALSE); | |
1422 fields = g_list_append(fields, f); | |
1423 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_STRING, | |
1424 _("Topic"), "topic", FALSE); | |
1425 fields = g_list_append(fields, f); | |
1426 gaim_roomlist_set_fields(sg->roomlist, fields); | |
1427 | |
1428 /* Call LIST */ | |
1429 silc_client_command_call(client, conn, "LIST"); | |
1430 | |
1431 gaim_roomlist_set_in_progress(sg->roomlist, TRUE); | |
1432 | |
1433 return sg->roomlist; | |
1434 } | |
1435 | |
1436 void silcgaim_roomlist_cancel(GaimRoomlist *list) | |
1437 { | |
1438 GaimConnection *gc = gaim_account_get_connection(list->account); | |
1439 SilcGaim sg; | |
1440 | |
1441 if (!gc) | |
1442 return; | |
1443 sg = gc->proto_data; | |
1444 | |
1445 gaim_roomlist_set_in_progress(list, FALSE); | |
1446 if (sg->roomlist == list) { | |
1447 gaim_roomlist_unref(sg->roomlist); | |
1448 sg->roomlist = NULL; | |
1449 sg->roomlist_canceled = TRUE; | |
1450 } | |
1451 } |