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