Mercurial > pidgin
annotate src/protocols/silc/chat.c @ 12216:4d3119205a33
[gaim-migrate @ 14518]
Remove GaimConvImFlags and GaimConvChatFlags - use GaimMessageFlags
everywhere instead.
Add a new GAIM_MESSAGE_IMAGES flag, and set it when sending a message
containing images.
When sending a message, the core will now always send "html" to the prpls,
just like it expects to receive html from the prpls for received messages.
This will allow text prpls such as SILC to support IM images and differentiate
them from user input. Previously gaim_unescape_html() was used before passing
the message to the prpl, now the prpl does this itself if it needs it.
I think I updated all the prpls correctly, but I'm not so sure about sametime.
committer: Tailor Script <tailor@pidgin.im>
author | Stu Tomlinson <stu@nosnilmot.com> |
---|---|
date | Thu, 24 Nov 2005 20:47:46 +0000 |
parents | 5851a9219bc7 |
children | 1baf4cbcf84d |
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)); |
153 g_string_append_printf(s, tmp); | |
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; |
9030 | 861 GaimBlistNodeAction *act; |
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 | |
9030 | 877 act = gaim_blist_node_action_new(_("Get Info"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
878 silcgaim_chat_getinfo_menu, |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
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) { | |
9030 | 885 act = gaim_blist_node_action_new(_("Invite List"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
886 silcgaim_chat_invitelist, |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
887 NULL, NULL); |
9030 | 888 m = g_list_append(m, act); |
8849 | 889 |
9030 | 890 act = gaim_blist_node_action_new(_("Ban List"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
891 silcgaim_chat_banlist, |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
892 NULL, NULL); |
9030 | 893 m = g_list_append(m, act); |
8849 | 894 } |
895 #endif | |
896 | |
897 if (chu) { | |
9030 | 898 act = gaim_blist_node_action_new(_("Add Private Group"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
899 silcgaim_chat_prv, |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
900 NULL, NULL); |
9030 | 901 m = g_list_append(m, act); |
8849 | 902 } |
903 | |
904 if (mode & SILC_CHANNEL_UMODE_CHANFO) { | |
9030 | 905 act = gaim_blist_node_action_new(_("Channel Authentication"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
906 silcgaim_chat_chauth, |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
907 NULL, NULL); |
9030 | 908 m = g_list_append(m, act); |
8849 | 909 |
910 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) { | |
9030 | 911 act = gaim_blist_node_action_new(_("Reset Permanent"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
912 silcgaim_chat_permanent_reset, |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
913 NULL, NULL); |
9030 | 914 m = g_list_append(m, act); |
8849 | 915 } else { |
9030 | 916 act = gaim_blist_node_action_new(_("Set Permanent"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
917 silcgaim_chat_permanent, |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
918 NULL, NULL); |
9030 | 919 m = g_list_append(m, act); |
8849 | 920 } |
921 } | |
922 | |
923 if (mode & SILC_CHANNEL_UMODE_CHANOP) { | |
9030 | 924 act = gaim_blist_node_action_new(_("Set User Limit"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
925 silcgaim_chat_ulimit, |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
926 NULL, NULL); |
9030 | 927 m = g_list_append(m, act); |
8849 | 928 |
929 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) { | |
9030 | 930 act = gaim_blist_node_action_new(_("Reset Topic Restriction"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
931 silcgaim_chat_resettopic, |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
932 NULL, NULL); |
9030 | 933 m = g_list_append(m, act); |
8849 | 934 } else { |
9030 | 935 act = gaim_blist_node_action_new(_("Set Topic Restriction"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
936 silcgaim_chat_settopic, |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
937 NULL, NULL); |
9030 | 938 m = g_list_append(m, act); |
8849 | 939 } |
940 | |
941 if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) { | |
9030 | 942 act = gaim_blist_node_action_new(_("Reset Private Channel"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
943 silcgaim_chat_resetprivate, |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
944 NULL, NULL); |
9030 | 945 m = g_list_append(m, act); |
8849 | 946 } else { |
9030 | 947 act = gaim_blist_node_action_new(_("Set Private Channel"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
948 silcgaim_chat_setprivate, |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
949 NULL, NULL); |
9030 | 950 m = g_list_append(m, act); |
8849 | 951 } |
952 | |
953 if (channel->mode & SILC_CHANNEL_MODE_SECRET) { | |
9030 | 954 act = gaim_blist_node_action_new(_("Reset Secret Channel"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
955 silcgaim_chat_resetsecret, |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
956 NULL, NULL); |
9030 | 957 m = g_list_append(m, act); |
8849 | 958 } else { |
9030 | 959 act = gaim_blist_node_action_new(_("Set Secret Channel"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
960 silcgaim_chat_setsecret, |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
961 NULL, NULL); |
9030 | 962 m = g_list_append(m, act); |
8849 | 963 } |
964 } | |
965 | |
12058 | 966 if (channel) { |
967 SilcGaimChatWb wb; | |
968 wb = silc_calloc(1, sizeof(*wb)); | |
969 wb->sg = sg; | |
970 wb->channel = channel; | |
971 act = gaim_blist_node_action_new(_("Draw On Whiteboard"), | |
972 silcgaim_chat_wb, (void *)wb, NULL); | |
973 m = g_list_append(m, act); | |
974 } | |
975 | |
8849 | 976 return m; |
977 } | |
978 | |
979 | |
980 /******************************* Joining Etc. ********************************/ | |
981 | |
982 void silcgaim_chat_join_done(SilcClient client, | |
983 SilcClientConnection conn, | |
984 SilcClientEntry *clients, | |
985 SilcUInt32 clients_count, | |
986 void *context) | |
987 { | |
988 GaimConnection *gc = client->application; | |
989 SilcGaim sg = gc->proto_data; | |
990 SilcChannelEntry channel = context; | |
991 GaimConversation *convo; | |
992 SilcUInt32 retry = SILC_PTR_TO_32(channel->context); | |
993 SilcHashTableList htl; | |
994 SilcChannelUser chu; | |
9554 | 995 GList *users = NULL, *flags = NULL; |
8849 | 996 char tmp[256]; |
997 | |
998 if (!clients && retry < 1) { | |
999 /* Resolving users failed, try again. */ | |
1000 channel->context = SILC_32_TO_PTR(retry + 1); | |
1001 silc_client_get_clients_by_channel(client, conn, channel, | |
1002 silcgaim_chat_join_done, channel); | |
1003 return; | |
1004 } | |
1005 | |
1006 /* Add channel to Gaim */ | |
1007 channel->context = SILC_32_TO_PTR(++sg->channel_ids); | |
1008 serv_got_joined_chat(gc, sg->channel_ids, channel->channel_name); | |
11338 | 1009 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 1010 channel->channel_name, sg->account); |
8849 | 1011 if (!convo) |
1012 return; | |
1013 | |
1014 /* Add all users to channel */ | |
1015 silc_hash_table_list(channel->user_list, &htl); | |
1016 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
9554 | 1017 GaimConvChatBuddyFlags f = GAIM_CBFLAGS_NONE; |
8849 | 1018 if (!chu->client->nickname) |
1019 continue; | |
1020 chu->context = SILC_32_TO_PTR(sg->channel_ids); | |
1021 | |
9554 | 1022 if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) |
1023 f |= GAIM_CBFLAGS_FOUNDER; | |
1024 if (chu->mode & SILC_CHANNEL_UMODE_CHANOP) | |
1025 f |= GAIM_CBFLAGS_OP; | |
8849 | 1026 users = g_list_append(users, g_strdup(chu->client->nickname)); |
9554 | 1027 flags = g_list_append(flags, GINT_TO_POINTER(f)); |
8849 | 1028 |
1029 if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) { | |
1030 if (chu->client == conn->local_entry) | |
1031 g_snprintf(tmp, sizeof(tmp), | |
1032 _("You are channel founder on <I>%s</I>"), | |
1033 channel->channel_name); | |
1034 else | |
1035 g_snprintf(tmp, sizeof(tmp), | |
1036 _("Channel founder on <I>%s</I> is <I>%s</I>"), | |
1037 channel->channel_name, chu->client->nickname); | |
1038 | |
1039 gaim_conversation_write(convo, NULL, tmp, | |
1040 GAIM_MESSAGE_SYSTEM, time(NULL)); | |
1041 | |
1042 } | |
1043 } | |
1044 silc_hash_table_list_reset(&htl); | |
1045 | |
11454
201617d49573
[gaim-migrate @ 13693]
Richard Laager <rlaager@wiktel.com>
parents:
11338
diff
changeset
|
1046 gaim_conv_chat_add_users(GAIM_CONV_CHAT(convo), users, NULL, flags, FALSE); |
8849 | 1047 g_list_free(users); |
9554 | 1048 g_list_free(flags); |
8849 | 1049 |
1050 /* Set topic */ | |
1051 if (channel->topic) | |
1052 gaim_conv_chat_set_topic(GAIM_CONV_CHAT(convo), NULL, channel->topic); | |
9353 | 1053 |
1054 /* Set nick */ | |
1055 gaim_conv_chat_set_nick(GAIM_CONV_CHAT(convo), conn->local_entry->nickname); | |
8849 | 1056 } |
1057 | |
9917 | 1058 char *silcgaim_get_chat_name(GHashTable *data) |
1059 { | |
1060 return g_strdup(g_hash_table_lookup(data, "channel")); | |
1061 } | |
1062 | |
8849 | 1063 void silcgaim_chat_join(GaimConnection *gc, GHashTable *data) |
1064 { | |
1065 SilcGaim sg = gc->proto_data; | |
1066 SilcClient client = sg->client; | |
1067 SilcClientConnection conn = sg->conn; | |
1068 const char *channel, *passphrase, *parentch; | |
1069 | |
1070 if (!conn) | |
1071 return; | |
1072 | |
1073 channel = g_hash_table_lookup(data, "channel"); | |
1074 passphrase = g_hash_table_lookup(data, "passphrase"); | |
1075 | |
1076 /* Check if we are joining a private group. Handle it | |
1077 purely locally as it's not a real channel */ | |
1078 if (strstr(channel, "[Private Group]")) { | |
1079 SilcChannelEntry channel_entry; | |
1080 SilcChannelPrivateKey key; | |
1081 GaimChat *c; | |
1082 SilcGaimPrvgrp grp; | |
1083 | |
1084 c = gaim_blist_find_chat(sg->account, channel); | |
1085 parentch = gaim_blist_node_get_string((GaimBlistNode *)c, "parentch"); | |
1086 if (!parentch) | |
1087 return; | |
1088 | |
1089 channel_entry = silc_client_get_channel(sg->client, sg->conn, | |
1090 (char *)parentch); | |
1091 if (!channel_entry || | |
1092 !silc_client_on_channel(channel_entry, sg->conn->local_entry)) { | |
1093 char tmp[512]; | |
1094 g_snprintf(tmp, sizeof(tmp), | |
1095 _("You have to join the %s channel before you are " | |
1096 "able to join the private group"), parentch); | |
1097 gaim_notify_error(gc, _("Join Private Group"), | |
1098 _("Cannot join private group"), tmp); | |
1099 return; | |
1100 } | |
1101 | |
1102 /* Add channel private key */ | |
1103 if (!silc_client_add_channel_private_key(client, conn, | |
1104 channel_entry, channel, | |
1105 NULL, NULL, | |
1106 (unsigned char *)passphrase, | |
1107 strlen(passphrase), &key)) | |
1108 return; | |
1109 | |
1110 /* Join the group */ | |
1111 grp = silc_calloc(1, sizeof(*grp)); | |
1112 if (!grp) | |
1113 return; | |
1114 grp->id = ++sg->channel_ids + SILCGAIM_PRVGRP; | |
1115 grp->chid = SILC_PTR_TO_32(channel_entry->context); | |
1116 grp->parentch = parentch; | |
1117 grp->channel = channel; | |
1118 grp->key = key; | |
1119 sg->grps = g_list_append(sg->grps, grp); | |
1120 serv_got_joined_chat(gc, grp->id, channel); | |
1121 return; | |
1122 } | |
1123 | |
1124 /* XXX We should have other properties here as well: | |
1125 1. whether to try to authenticate to the channel | |
1126 1a. with default key, | |
1127 1b. with specific key. | |
1128 2. whether to try to authenticate to become founder. | |
1129 2a. with default key, | |
1130 2b. with specific key. | |
1131 | |
1132 Since now such variety is not possible in the join dialog | |
1133 we always use -founder and -auth options, which try to | |
1134 do both 1 and 2 with default keys. */ | |
1135 | |
1136 /* Call JOIN */ | |
9172 | 1137 if ((passphrase != NULL) && (*passphrase != '\0')) |
8849 | 1138 silc_client_command_call(client, conn, NULL, "JOIN", |
1139 channel, passphrase, "-auth", "-founder", NULL); | |
1140 else | |
1141 silc_client_command_call(client, conn, NULL, "JOIN", | |
1142 channel, "-auth", "-founder", NULL); | |
1143 } | |
1144 | |
1145 void silcgaim_chat_invite(GaimConnection *gc, int id, const char *msg, | |
1146 const char *name) | |
1147 { | |
1148 SilcGaim sg = gc->proto_data; | |
1149 SilcClient client = sg->client; | |
1150 SilcClientConnection conn = sg->conn; | |
1151 SilcHashTableList htl; | |
1152 SilcChannelUser chu; | |
1153 gboolean found = FALSE; | |
1154 | |
1155 if (!conn) | |
1156 return; | |
1157 | |
1158 /* See if we are inviting on a private group. Invite | |
1159 to the actual channel */ | |
1160 if (id > SILCGAIM_PRVGRP) { | |
1161 GList *l; | |
1162 SilcGaimPrvgrp prv; | |
1163 | |
1164 for (l = sg->grps; l; l = l->next) | |
1165 if (((SilcGaimPrvgrp)l->data)->id == id) | |
1166 break; | |
1167 if (!l) | |
1168 return; | |
1169 prv = l->data; | |
1170 id = prv->chid; | |
1171 } | |
1172 | |
1173 /* Find channel by id */ | |
1174 silc_hash_table_list(conn->local_entry->channels, &htl); | |
1175 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
1176 if (SILC_PTR_TO_32(chu->channel->context) == id ) { | |
1177 found = TRUE; | |
1178 break; | |
1179 } | |
1180 } | |
1181 silc_hash_table_list_reset(&htl); | |
1182 if (!found) | |
1183 return; | |
1184 | |
1185 /* Call INVITE */ | |
1186 silc_client_command_call(client, conn, NULL, "INVITE", | |
1187 chu->channel->channel_name, | |
9353 | 1188 name, NULL); |
8849 | 1189 } |
1190 | |
1191 void silcgaim_chat_leave(GaimConnection *gc, int id) | |
1192 { | |
1193 SilcGaim sg = gc->proto_data; | |
1194 SilcClient client = sg->client; | |
1195 SilcClientConnection conn = sg->conn; | |
1196 SilcHashTableList htl; | |
1197 SilcChannelUser chu; | |
1198 gboolean found = FALSE; | |
1199 GList *l; | |
1200 SilcGaimPrvgrp prv; | |
1201 | |
1202 if (!conn) | |
1203 return; | |
1204 | |
1205 /* See if we are leaving a private group */ | |
1206 if (id > SILCGAIM_PRVGRP) { | |
1207 SilcChannelEntry channel; | |
1208 | |
1209 for (l = sg->grps; l; l = l->next) | |
1210 if (((SilcGaimPrvgrp)l->data)->id == id) | |
1211 break; | |
1212 if (!l) | |
1213 return; | |
1214 prv = l->data; | |
1215 channel = silc_client_get_channel(sg->client, sg->conn, | |
1216 (char *)prv->parentch); | |
1217 if (!channel) | |
1218 return; | |
1219 silc_client_del_channel_private_key(client, conn, | |
1220 channel, prv->key); | |
1221 silc_free(prv); | |
1222 sg->grps = g_list_remove(sg->grps, prv); | |
1223 serv_got_chat_left(gc, id); | |
1224 return; | |
1225 } | |
1226 | |
1227 /* Find channel by id */ | |
1228 silc_hash_table_list(conn->local_entry->channels, &htl); | |
1229 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
1230 if (SILC_PTR_TO_32(chu->channel->context) == id ) { | |
1231 found = TRUE; | |
1232 break; | |
1233 } | |
1234 } | |
1235 silc_hash_table_list_reset(&htl); | |
1236 if (!found) | |
1237 return; | |
1238 | |
1239 /* Call LEAVE */ | |
1240 silc_client_command_call(client, conn, NULL, "LEAVE", | |
1241 chu->channel->channel_name, NULL); | |
1242 | |
1243 serv_got_chat_left(gc, id); | |
1244 | |
1245 /* Leave from private groups on this channel as well */ | |
1246 for (l = sg->grps; l; l = l->next) | |
1247 if (((SilcGaimPrvgrp)l->data)->chid == id) { | |
1248 prv = l->data; | |
1249 silc_client_del_channel_private_key(client, conn, | |
1250 chu->channel, | |
1251 prv->key); | |
1252 serv_got_chat_left(gc, prv->id); | |
1253 silc_free(prv); | |
1254 sg->grps = g_list_remove(sg->grps, prv); | |
1255 if (!sg->grps) | |
1256 break; | |
1257 } | |
1258 } | |
1259 | |
12216 | 1260 int silcgaim_chat_send(GaimConnection *gc, int id, const char *msg, GaimMessageFlags msgflags) |
8849 | 1261 { |
1262 SilcGaim sg = gc->proto_data; | |
1263 SilcClient client = sg->client; | |
1264 SilcClientConnection conn = sg->conn; | |
1265 SilcHashTableList htl; | |
1266 SilcChannelUser chu; | |
1267 SilcChannelEntry channel = NULL; | |
1268 SilcChannelPrivateKey key = NULL; | |
1269 SilcUInt32 flags; | |
1270 int ret; | |
12216 | 1271 char *msg2, *tmp; |
8849 | 1272 gboolean found = FALSE; |
12167 | 1273 gboolean sign = gaim_account_get_bool(sg->account, "sign-verify", FALSE); |
8849 | 1274 |
1275 if (!msg || !conn) | |
1276 return 0; | |
1277 | |
9353 | 1278 flags = SILC_MESSAGE_FLAG_UTF8; |
1279 | |
12216 | 1280 tmp = msg2 = gaim_unescape_html(msg); |
9353 | 1281 |
1282 if (!g_ascii_strncasecmp(msg2, "/me ", 4)) | |
1283 { | |
1284 msg2 += 4; | |
12216 | 1285 if (!*msg2) { |
1286 g_free(tmp); | |
9353 | 1287 return 0; |
12216 | 1288 } |
9353 | 1289 flags |= SILC_MESSAGE_FLAG_ACTION; |
1290 } else if (strlen(msg) > 1 && msg[0] == '/') { | |
8849 | 1291 if (!silc_client_command_call(client, conn, msg + 1)) |
1292 gaim_notify_error(gc, ("Call Command"), _("Cannot call command"), | |
9353 | 1293 _("Unknown command")); |
12216 | 1294 g_free(tmp); |
8849 | 1295 return 0; |
1296 } | |
1297 | |
9353 | 1298 |
8849 | 1299 if (sign) |
1300 flags |= SILC_MESSAGE_FLAG_SIGNED; | |
1301 | |
1302 /* Get the channel private key if we are sending on | |
1303 private group */ | |
1304 if (id > SILCGAIM_PRVGRP) { | |
1305 GList *l; | |
1306 SilcGaimPrvgrp prv; | |
1307 | |
1308 for (l = sg->grps; l; l = l->next) | |
1309 if (((SilcGaimPrvgrp)l->data)->id == id) | |
1310 break; | |
12216 | 1311 if (!l) { |
1312 g_free(tmp); | |
8849 | 1313 return 0; |
12216 | 1314 } |
8849 | 1315 prv = l->data; |
1316 channel = silc_client_get_channel(sg->client, sg->conn, | |
1317 (char *)prv->parentch); | |
12216 | 1318 if (!channel) { |
1319 g_free(tmp); | |
8849 | 1320 return 0; |
12216 | 1321 } |
8849 | 1322 key = prv->key; |
1323 } | |
1324 | |
1325 if (!channel) { | |
1326 /* Find channel by id */ | |
1327 silc_hash_table_list(conn->local_entry->channels, &htl); | |
1328 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
1329 if (SILC_PTR_TO_32(chu->channel->context) == id ) { | |
1330 found = TRUE; | |
1331 break; | |
1332 } | |
1333 } | |
1334 silc_hash_table_list_reset(&htl); | |
12216 | 1335 if (!found) { |
1336 g_free(tmp); | |
8849 | 1337 return 0; |
12216 | 1338 } |
8849 | 1339 channel = chu->channel; |
1340 } | |
1341 | |
1342 /* Send channel message */ | |
1343 ret = silc_client_send_channel_message(client, conn, channel, key, | |
9353 | 1344 flags, (unsigned char *)msg2, |
1345 strlen(msg2), TRUE); | |
9359 | 1346 if (ret) { |
12216 | 1347 serv_got_chat_in(gc, id, gaim_connection_get_display_name(gc), 0, msg, |
8849 | 1348 time(NULL)); |
9359 | 1349 } |
12216 | 1350 g_free(tmp); |
8849 | 1351 |
1352 return ret; | |
1353 } | |
1354 | |
1355 void silcgaim_chat_set_topic(GaimConnection *gc, int id, const char *topic) | |
1356 { | |
1357 SilcGaim sg = gc->proto_data; | |
1358 SilcClient client = sg->client; | |
1359 SilcClientConnection conn = sg->conn; | |
1360 SilcHashTableList htl; | |
1361 SilcChannelUser chu; | |
1362 gboolean found = FALSE; | |
1363 | |
9353 | 1364 if (!conn) |
8849 | 1365 return; |
1366 | |
1367 /* See if setting topic on private group. Set it | |
1368 on the actual channel */ | |
1369 if (id > SILCGAIM_PRVGRP) { | |
1370 GList *l; | |
1371 SilcGaimPrvgrp prv; | |
1372 | |
1373 for (l = sg->grps; l; l = l->next) | |
1374 if (((SilcGaimPrvgrp)l->data)->id == id) | |
1375 break; | |
1376 if (!l) | |
1377 return; | |
1378 prv = l->data; | |
1379 id = prv->chid; | |
1380 } | |
1381 | |
1382 /* Find channel by id */ | |
1383 silc_hash_table_list(conn->local_entry->channels, &htl); | |
1384 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | |
1385 if (SILC_PTR_TO_32(chu->channel->context) == id ) { | |
1386 found = TRUE; | |
1387 break; | |
1388 } | |
1389 } | |
1390 silc_hash_table_list_reset(&htl); | |
1391 if (!found) | |
1392 return; | |
1393 | |
1394 /* Call TOPIC */ | |
1395 silc_client_command_call(client, conn, NULL, "TOPIC", | |
1396 chu->channel->channel_name, topic, NULL); | |
1397 } | |
1398 | |
1399 GaimRoomlist *silcgaim_roomlist_get_list(GaimConnection *gc) | |
1400 { | |
1401 SilcGaim sg = gc->proto_data; | |
1402 SilcClient client = sg->client; | |
1403 SilcClientConnection conn = sg->conn; | |
1404 GList *fields = NULL; | |
1405 GaimRoomlistField *f; | |
1406 | |
1407 if (!conn) | |
1408 return NULL; | |
1409 | |
1410 if (sg->roomlist) | |
1411 gaim_roomlist_unref(sg->roomlist); | |
1412 | |
1413 sg->roomlist_canceled = FALSE; | |
1414 | |
1415 sg->roomlist = gaim_roomlist_new(gaim_connection_get_account(gc)); | |
1416 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_STRING, "", "channel", TRUE); | |
1417 fields = g_list_append(fields, f); | |
1418 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_INT, | |
1419 _("Users"), "users", FALSE); | |
1420 fields = g_list_append(fields, f); | |
1421 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_STRING, | |
1422 _("Topic"), "topic", FALSE); | |
1423 fields = g_list_append(fields, f); | |
1424 gaim_roomlist_set_fields(sg->roomlist, fields); | |
1425 | |
1426 /* Call LIST */ | |
1427 silc_client_command_call(client, conn, "LIST"); | |
1428 | |
1429 gaim_roomlist_set_in_progress(sg->roomlist, TRUE); | |
1430 | |
1431 return sg->roomlist; | |
1432 } | |
1433 | |
1434 void silcgaim_roomlist_cancel(GaimRoomlist *list) | |
1435 { | |
1436 GaimConnection *gc = gaim_account_get_connection(list->account); | |
1437 SilcGaim sg; | |
1438 | |
1439 if (!gc) | |
1440 return; | |
1441 sg = gc->proto_data; | |
1442 | |
1443 gaim_roomlist_set_in_progress(list, FALSE); | |
1444 if (sg->roomlist == list) { | |
1445 gaim_roomlist_unref(sg->roomlist); | |
1446 sg->roomlist = NULL; | |
1447 sg->roomlist_canceled = TRUE; | |
1448 } | |
1449 } |