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