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