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