| 17674:aafdd7bed36d | 17675:e7069bf1de1a |
|---|---|
| 2 | 2 |
| 3 silcpurple_ops.c | 3 silcpurple_ops.c |
| 4 | 4 |
| 5 Author: Pekka Riikonen <priikone@silcnet.org> | 5 Author: Pekka Riikonen <priikone@silcnet.org> |
| 6 | 6 |
| 7 Copyright (C) 2004 Pekka Riikonen | 7 Copyright (C) 2004 - 2007 Pekka Riikonen |
| 8 | 8 |
| 9 This program is free software; you can redistribute it and/or modify | 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 | 10 it under the terms of the GNU General Public License as published by |
| 11 the Free Software Foundation; version 2 of the License. | 11 the Free Software Foundation; version 2 of the License. |
| 12 | 12 |
| 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 GNU General Public License for more details. | 16 GNU General Public License for more details. |
| 17 | 17 |
| 18 */ | 18 */ |
| 19 | 19 |
| 20 #include "silcincludes.h" | 20 #include "silc.h" |
| 21 #include "silcclient.h" | 21 #include "silcclient.h" |
| 22 #include "silcpurple.h" | 22 #include "silcpurple.h" |
| 23 #include "imgstore.h" | 23 #include "imgstore.h" |
| 24 #include "wb.h" | 24 #include "wb.h" |
| 25 | 25 |
| 26 static void | 26 static void |
| 27 silc_channel_message(SilcClient client, SilcClientConnection conn, | 27 silc_channel_message(SilcClient client, SilcClientConnection conn, |
| 28 SilcClientEntry sender, SilcChannelEntry channel, | 28 SilcClientEntry sender, SilcChannelEntry channel, |
| 29 SilcMessagePayload payload, SilcChannelPrivateKey key, | 29 SilcMessagePayload payload, |
| 30 SilcMessageFlags flags, const unsigned char *message, | 30 SilcChannelPrivateKey key, SilcMessageFlags flags, |
| 31 const unsigned char *message, | |
| 31 SilcUInt32 message_len); | 32 SilcUInt32 message_len); |
| 32 static void | 33 static void |
| 33 silc_private_message(SilcClient client, SilcClientConnection conn, | 34 silc_private_message(SilcClient client, SilcClientConnection conn, |
| 34 SilcClientEntry sender, SilcMessagePayload payload, | 35 SilcClientEntry sender, SilcMessagePayload payload, |
| 35 SilcMessageFlags flags, const unsigned char *message, | 36 SilcMessageFlags flags, const unsigned char *message, |
| 36 SilcUInt32 message_len); | 37 SilcUInt32 message_len); |
| 38 static void | |
| 39 silc_ask_passphrase(SilcClient client, SilcClientConnection conn, | |
| 40 SilcAskPassphrase completion, void *context); | |
| 37 | 41 |
| 38 /* Message sent to the application by library. `conn' associates the | 42 /* Message sent to the application by library. `conn' associates the |
| 39 message to a specific connection. `conn', however, may be NULL. | 43 message to a specific connection. `conn', however, may be NULL. |
| 40 The `type' indicates the type of the message sent by the library. | 44 The `type' indicates the type of the message sent by the library. |
| 41 The application can for example filter the message according the | 45 The application can for example filter the message according the |
| 42 type. */ | 46 type. */ |
| 43 | 47 |
| 44 static void | 48 void silc_say(SilcClient client, SilcClientConnection conn, |
| 45 silc_say(SilcClient client, SilcClientConnection conn, | 49 SilcClientMessageType type, char *msg, ...) |
| 46 SilcClientMessageType type, char *msg, ...) | |
| 47 { | 50 { |
| 48 /* Nothing */ | 51 if (type == SILC_CLIENT_MESSAGE_ERROR) { |
| 52 char tmp[256]; | |
| 53 va_list va; | |
| 54 | |
| 55 va_start(va, msg); | |
| 56 silc_vsnprintf(tmp, sizeof(tmp), msg, va); | |
| 57 purple_notify_error(NULL, _("Error"), _("Error occurred"), tmp); | |
| 58 | |
| 59 va_end(va); | |
| 60 return; | |
| 61 } | |
| 49 } | 62 } |
| 50 | 63 |
| 51 #ifdef HAVE_SILCMIME_H | 64 #ifdef HAVE_SILCMIME_H |
| 52 /* Processes incoming MIME message. Can be private message or channel | 65 /* Processes incoming MIME message. Can be private message or channel |
| 53 message. */ | 66 message. Returns TRUE if the message `mime' was displayed. */ |
| 54 | 67 |
| 55 static void | 68 static SilcBool |
| 56 silcpurple_mime_message(SilcClient client, SilcClientConnection conn, | 69 silcpurple_mime_message(SilcClient client, SilcClientConnection conn, |
| 57 SilcClientEntry sender, SilcChannelEntry channel, | 70 SilcClientEntry sender, SilcChannelEntry channel, |
| 58 SilcMessagePayload payload, SilcChannelPrivateKey key, | 71 SilcMessagePayload payload, SilcChannelPrivateKey key, |
| 59 SilcMessageFlags flags, SilcMime mime, | 72 SilcMessageFlags flags, SilcMime mime, |
| 60 gboolean recursive) | 73 gboolean recursive) |
| 61 { | 74 { |
| 62 PurpleConnection *gc = client->application; | 75 PurpleConnection *gc = client->application; |
| 63 SilcPurple sg = gc->proto_data; | 76 SilcPurple sg = gc->proto_data; |
| 64 const char *type; | 77 const char *type; |
| 65 const unsigned char *data; | 78 const unsigned char *data; |
| 66 SilcUInt32 data_len; | 79 SilcUInt32 data_len; |
| 67 PurpleMessageFlags cflags = 0; | 80 PurpleMessageFlags cflags = 0; |
| 68 PurpleConversation *convo = NULL; | 81 PurpleConversation *convo = NULL; |
| 82 SilcBool ret = FALSE; | |
| 69 | 83 |
| 70 if (!mime) | 84 if (!mime) |
| 71 return; | 85 return FALSE; |
| 72 | 86 |
| 73 /* Check for fragmented MIME message */ | 87 /* Check for fragmented MIME message */ |
| 74 if (silc_mime_is_partial(mime)) { | 88 if (silc_mime_is_partial(mime)) { |
| 75 if (!sg->mimeass) | 89 if (!sg->mimeass) |
| 76 sg->mimeass = silc_mime_assembler_alloc(); | 90 sg->mimeass = silc_mime_assembler_alloc(); |
| 77 | 91 |
| 78 /* Defragment */ | 92 /* Defragment */ |
| 79 mime = silc_mime_assemble(sg->mimeass, mime); | 93 mime = silc_mime_assemble(sg->mimeass, mime); |
| 80 if (!mime) | 94 if (!mime) |
| 81 /* More fragments to come */ | 95 /* More fragments to come */ |
| 82 return; | 96 return FALSE; |
| 83 | 97 |
| 84 /* Process the complete message */ | 98 /* Process the complete message */ |
| 85 silcpurple_mime_message(client, conn, sender, channel, | 99 return silcpurple_mime_message(client, conn, sender, channel, |
| 86 payload, key, flags, mime, FALSE); | 100 payload, key, flags, mime, |
| 87 return; | 101 FALSE); |
| 88 } | 102 } |
| 89 | 103 |
| 90 /* Check for multipart message */ | 104 /* Check for multipart message */ |
| 91 if (silc_mime_is_multipart(mime)) { | 105 if (silc_mime_is_multipart(mime)) { |
| 92 SilcMime p; | 106 SilcMime p; |
| 93 const char *mtype; | 107 const char *mtype; |
| 94 SilcDList parts = silc_mime_get_multiparts(mime, &mtype); | 108 SilcDList parts = silc_mime_get_multiparts(mime, &mtype); |
| 95 | 109 SilcBool ret; |
| 96 /* Only "mixed" type supported */ | 110 |
| 97 if (strcmp(mtype, "mixed")) | 111 if (!strcmp(mtype, "mixed")) { |
| 98 goto out; | 112 /* Contains multiple messages */ |
| 99 | 113 silc_dlist_start(parts); |
| 100 silc_dlist_start(parts); | 114 while ((p = silc_dlist_get(parts)) != SILC_LIST_END) { |
| 101 while ((p = silc_dlist_get(parts)) != SILC_LIST_END) { | 115 /* Recursively process parts */ |
| 102 /* Recursively process parts */ | 116 ret = silcpurple_mime_message(client, conn, sender, channel, |
| 103 silcpurple_mime_message(client, conn, sender, channel, | 117 payload, key, flags, p, TRUE); |
| 104 payload, key, flags, p, TRUE); | 118 } |
| 105 } | 119 } |
| 120 | |
| 121 if (!strcmp(mtype, "alternative")) { | |
| 122 /* Same message in alternative formats. Kopete sends | |
| 123 these. Go in order from last to first. */ | |
| 124 silc_dlist_end(parts); | |
| 125 while ((p = silc_dlist_get(parts)) != SILC_LIST_END) { | |
| 126 /* Go through the alternatives and display the first | |
| 127 one we support. */ | |
| 128 if (silcpurple_mime_message(client, conn, sender, channel, | |
| 129 payload, key, flags, p, TRUE)) { | |
| 130 ret = TRUE; | |
| 131 break; | |
| 132 } | |
| 133 } | |
| 134 } | |
| 135 | |
| 106 goto out; | 136 goto out; |
| 107 } | 137 } |
| 108 | 138 |
| 109 /* Get content type and MIME data */ | 139 /* Get content type and MIME data */ |
| 110 type = silc_mime_get_field(mime, "Content-Type"); | 140 type = silc_mime_get_field(mime, "Content-Type"); |
| 122 if (!strstr(type, "utf-8")) | 152 if (!strstr(type, "utf-8")) |
| 123 goto out; | 153 goto out; |
| 124 | 154 |
| 125 if (channel) | 155 if (channel) |
| 126 silc_channel_message(client, conn, sender, channel, | 156 silc_channel_message(client, conn, sender, channel, |
| 127 payload, key, | 157 payload, key, |
| 128 SILC_MESSAGE_FLAG_UTF8, data, | 158 SILC_MESSAGE_FLAG_UTF8, data, |
| 129 data_len); | 159 data_len); |
| 130 else | 160 else |
| 131 silc_private_message(client, conn, sender, payload, | 161 silc_private_message(client, conn, sender, payload, |
| 132 SILC_MESSAGE_FLAG_UTF8, data, | 162 SILC_MESSAGE_FLAG_UTF8, data, |
| 133 data_len); | 163 data_len); |
| 164 ret = TRUE; | |
| 134 goto out; | 165 goto out; |
| 135 } | 166 } |
| 136 | 167 |
| 137 /* Image */ | 168 /* Image */ |
| 138 if (strstr(type, "image/png") || | 169 if (strstr(type, "image/png") || |
| 155 break; | 186 break; |
| 156 } | 187 } |
| 157 } | 188 } |
| 158 if (channel && !convo) | 189 if (channel && !convo) |
| 159 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, | 190 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, |
| 160 channel->channel_name, sg->account); | 191 channel->channel_name, sg->account); |
| 161 if (channel && !convo) | 192 if (channel && !convo) |
| 162 goto out; | 193 goto out; |
| 163 | 194 |
| 164 imgid = purple_imgstore_add_with_id(g_memdup(data, data_len), data_len, ""); | 195 imgid = purple_imgstore_add_with_id(g_memdup(data, data_len), data_len, ""); |
| 165 if (imgid) { | 196 if (imgid) { |
| 166 cflags |= PURPLE_MESSAGE_IMAGES | PURPLE_MESSAGE_RECV; | 197 cflags |= PURPLE_MESSAGE_IMAGES | PURPLE_MESSAGE_RECV; |
| 167 g_snprintf(tmp, sizeof(tmp), "<IMG ID=\"%d\">", imgid); | 198 g_snprintf(tmp, sizeof(tmp), "<IMG ID=\"%d\">", imgid); |
| 168 | 199 |
| 169 if (channel) | 200 if (channel) |
| 170 serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), | 201 serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), |
| 171 sender->nickname ? | 202 sender->nickname ? |
| 172 sender->nickname : | 203 sender->nickname : |
| 173 "<unknown>", cflags, | 204 "<unknown>", cflags, |
| 174 tmp, time(NULL)); | 205 tmp, time(NULL)); |
| 175 else | 206 else |
| 176 serv_got_im(gc, sender->nickname ? | 207 serv_got_im(gc, sender->nickname ? |
| 177 sender->nickname : "<unknown>", | 208 sender->nickname : "<unknown>", |
| 178 tmp, cflags, time(NULL)); | 209 tmp, cflags, time(NULL)); |
| 179 | 210 |
| 180 purple_imgstore_unref_by_id(imgid); | 211 purple_imgstore_unref_by_id(imgid); |
| 181 cflags = 0; | 212 cflags = 0; |
| 213 ret = TRUE; | |
| 182 } | 214 } |
| 183 goto out; | 215 goto out; |
| 184 } | 216 } |
| 185 | 217 |
| 186 /* Whiteboard message */ | 218 /* Whiteboard message */ |
| 189 if (channel) | 221 if (channel) |
| 190 silcpurple_wb_receive_ch(client, conn, sender, channel, | 222 silcpurple_wb_receive_ch(client, conn, sender, channel, |
| 191 payload, flags, data, data_len); | 223 payload, flags, data, data_len); |
| 192 else | 224 else |
| 193 silcpurple_wb_receive(client, conn, sender, payload, | 225 silcpurple_wb_receive(client, conn, sender, payload, |
| 194 flags, data, data_len); | 226 flags, data, data_len); |
| 227 ret = TRUE; | |
| 195 goto out; | 228 goto out; |
| 196 } | 229 } |
| 197 | 230 |
| 198 out: | 231 out: |
| 199 if (!recursive) | 232 if (!recursive) |
| 200 silc_mime_free(mime); | 233 silc_mime_free(mime); |
| 234 return ret; | |
| 201 } | 235 } |
| 202 #endif /* HAVE_SILCMIME_H */ | 236 #endif /* HAVE_SILCMIME_H */ |
| 203 | 237 |
| 204 /* Message for a channel. The `sender' is the sender of the message | 238 /* Message for a channel. The `sender' is the sender of the message |
| 205 The `channel' is the channel. The `message' is the message. Note | 239 The `channel' is the channel. The `message' is the message. Note |
| 208 (like it may tell the message is multimedia message). */ | 242 (like it may tell the message is multimedia message). */ |
| 209 | 243 |
| 210 static void | 244 static void |
| 211 silc_channel_message(SilcClient client, SilcClientConnection conn, | 245 silc_channel_message(SilcClient client, SilcClientConnection conn, |
| 212 SilcClientEntry sender, SilcChannelEntry channel, | 246 SilcClientEntry sender, SilcChannelEntry channel, |
| 213 SilcMessagePayload payload, SilcChannelPrivateKey key, | 247 SilcMessagePayload payload, |
| 214 SilcMessageFlags flags, const unsigned char *message, | 248 SilcChannelPrivateKey key, SilcMessageFlags flags, |
| 249 const unsigned char *message, | |
| 215 SilcUInt32 message_len) | 250 SilcUInt32 message_len) |
| 216 { | 251 { |
| 217 PurpleConnection *gc = client->application; | 252 PurpleConnection *gc = client->application; |
| 218 SilcPurple sg = gc->proto_data; | 253 SilcPurple sg = gc->proto_data; |
| 219 PurpleConversation *convo = NULL; | 254 PurpleConversation *convo = NULL; |
| 234 break; | 269 break; |
| 235 } | 270 } |
| 236 } | 271 } |
| 237 if (!convo) | 272 if (!convo) |
| 238 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, | 273 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, |
| 239 channel->channel_name, sg->account); | 274 channel->channel_name, sg->account); |
| 240 if (!convo) | 275 if (!convo) |
| 241 return; | 276 return; |
| 242 | 277 |
| 243 if (flags & SILC_MESSAGE_FLAG_SIGNED && | 278 if (flags & SILC_MESSAGE_FLAG_SIGNED && |
| 244 purple_account_get_bool(sg->account, "sign-verify", FALSE)) { | 279 purple_account_get_bool(sg->account, "sign-verify", FALSE)) { |
| 247 | 282 |
| 248 if (flags & SILC_MESSAGE_FLAG_DATA) { | 283 if (flags & SILC_MESSAGE_FLAG_DATA) { |
| 249 /* Process MIME message */ | 284 /* Process MIME message */ |
| 250 #ifdef HAVE_SILCMIME_H | 285 #ifdef HAVE_SILCMIME_H |
| 251 SilcMime mime; | 286 SilcMime mime; |
| 252 mime = silc_mime_decode(message, message_len); | 287 mime = silc_mime_decode(NULL, message, message_len); |
| 253 silcpurple_mime_message(client, conn, sender, channel, payload, | 288 silcpurple_mime_message(client, conn, sender, channel, payload, |
| 254 key, flags, mime, FALSE); | 289 key, flags, mime, FALSE); |
| 255 #else | 290 #else |
| 256 char type[128], enc[128]; | 291 char type[128], enc[128]; |
| 257 unsigned char *data; | 292 unsigned char *data; |
| 258 SilcUInt32 data_len; | 293 SilcUInt32 data_len; |
| 259 | 294 |
| 281 return; | 316 return; |
| 282 | 317 |
| 283 tmp = g_markup_escape_text(msg, -1); | 318 tmp = g_markup_escape_text(msg, -1); |
| 284 /* Send to Purple */ | 319 /* Send to Purple */ |
| 285 serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), | 320 serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), |
| 286 sender->nickname ? | 321 sender->nickname, 0, tmp, time(NULL)); |
| 287 sender->nickname : "<unknown>", 0, | |
| 288 tmp, time(NULL)); | |
| 289 g_free(tmp); | 322 g_free(tmp); |
| 290 g_free(msg); | 323 g_free(msg); |
| 291 return; | 324 return; |
| 292 } | 325 } |
| 293 | 326 |
| 294 if (flags & SILC_MESSAGE_FLAG_NOTICE) { | 327 if (flags & SILC_MESSAGE_FLAG_NOTICE) { |
| 295 msg = g_strdup_printf("(notice) <I>%s</I> %s", | 328 msg = g_strdup_printf("(notice) <I>%s</I> %s", |
| 296 sender->nickname ? | 329 sender->nickname, (const char *)message); |
| 297 sender->nickname : "<unknown>", | |
| 298 (const char *)message); | |
| 299 if (!msg) | 330 if (!msg) |
| 300 return; | 331 return; |
| 301 | 332 |
| 302 /* Send to Purple */ | 333 /* Send to Purple */ |
| 303 purple_conversation_write(convo, NULL, (const char *)msg, | 334 purple_conversation_write(convo, NULL, (const char *)msg, |
| 308 | 339 |
| 309 if (flags & SILC_MESSAGE_FLAG_UTF8) { | 340 if (flags & SILC_MESSAGE_FLAG_UTF8) { |
| 310 tmp = g_markup_escape_text((const char *)message, -1); | 341 tmp = g_markup_escape_text((const char *)message, -1); |
| 311 /* Send to Purple */ | 342 /* Send to Purple */ |
| 312 serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), | 343 serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), |
| 313 sender->nickname ? | 344 sender->nickname, 0, tmp, time(NULL)); |
| 314 sender->nickname : "<unknown>", 0, | |
| 315 tmp, time(NULL)); | |
| 316 g_free(tmp); | 345 g_free(tmp); |
| 317 } | 346 } |
| 318 } | 347 } |
| 319 | 348 |
| 320 | 349 |
| 339 return; | 368 return; |
| 340 | 369 |
| 341 if (sender->nickname) | 370 if (sender->nickname) |
| 342 /* XXX - Should this be PURPLE_CONV_TYPE_IM? */ | 371 /* XXX - Should this be PURPLE_CONV_TYPE_IM? */ |
| 343 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, | 372 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, |
| 344 sender->nickname, sg->account); | 373 sender->nickname, sg->account); |
| 345 | 374 |
| 346 if (flags & SILC_MESSAGE_FLAG_SIGNED && | 375 if (flags & SILC_MESSAGE_FLAG_SIGNED && |
| 347 purple_account_get_bool(sg->account, "sign-verify", FALSE)) { | 376 purple_account_get_bool(sg->account, "sign-verify", FALSE)) { |
| 348 /* XXX */ | 377 /* XXX */ |
| 349 } | 378 } |
| 350 | 379 |
| 351 if (flags & SILC_MESSAGE_FLAG_DATA) { | 380 if (flags & SILC_MESSAGE_FLAG_DATA) { |
| 352 #ifdef HAVE_SILCMIME_H | 381 #ifdef HAVE_SILCMIME_H |
| 353 /* Process MIME message */ | 382 /* Process MIME message */ |
| 354 SilcMime mime; | 383 SilcMime mime; |
| 355 mime = silc_mime_decode(message, message_len); | 384 mime = silc_mime_decode(NULL, message, message_len); |
| 356 silcpurple_mime_message(client, conn, sender, NULL, payload, | 385 silcpurple_mime_message(client, conn, sender, NULL, payload, |
| 357 NULL, flags, mime, FALSE); | 386 NULL, flags, mime, FALSE); |
| 358 #else | 387 #else |
| 359 char type[128], enc[128]; | 388 char type[128], enc[128]; |
| 360 unsigned char *data; | 389 unsigned char *data; |
| 362 | 391 |
| 363 memset(type, 0, sizeof(type)); | 392 memset(type, 0, sizeof(type)); |
| 364 memset(enc, 0, sizeof(enc)); | 393 memset(enc, 0, sizeof(enc)); |
| 365 | 394 |
| 366 if (!silc_mime_parse(message, message_len, NULL, 0, | 395 if (!silc_mime_parse(message, message_len, NULL, 0, |
| 367 type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data, | 396 type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data, |
| 368 &data_len)) | 397 &data_len)) |
| 369 return; | 398 return; |
| 370 | 399 |
| 371 if (!strcmp(type, "application/x-wb") && | 400 if (!strcmp(type, "application/x-wb") && |
| 372 !strcmp(enc, "binary") && | 401 !strcmp(enc, "binary") && |
| 381 msg = g_strdup_printf("/me %s", | 410 msg = g_strdup_printf("/me %s", |
| 382 (const char *)message); | 411 (const char *)message); |
| 383 if (!msg) | 412 if (!msg) |
| 384 return; | 413 return; |
| 385 | 414 |
| 415 /* Send to Purple */ | |
| 386 tmp = g_markup_escape_text(msg, -1); | 416 tmp = g_markup_escape_text(msg, -1); |
| 387 /* Send to Purple */ | 417 serv_got_im(gc, sender->nickname, tmp, 0, time(NULL)); |
| 388 serv_got_im(gc, sender->nickname ? | |
| 389 sender->nickname : "<unknown>", | |
| 390 tmp, 0, time(NULL)); | |
| 391 g_free(msg); | 418 g_free(msg); |
| 392 g_free(tmp); | 419 g_free(tmp); |
| 393 return; | 420 return; |
| 394 } | 421 } |
| 395 | 422 |
| 396 if (flags & SILC_MESSAGE_FLAG_NOTICE && convo) { | 423 if (flags & SILC_MESSAGE_FLAG_NOTICE && convo) { |
| 397 msg = g_strdup_printf("(notice) <I>%s</I> %s", | 424 msg = g_strdup_printf("(notice) <I>%s</I> %s", |
| 398 sender->nickname ? | 425 sender->nickname, (const char *)message); |
| 399 sender->nickname : "<unknown>", | |
| 400 (const char *)message); | |
| 401 if (!msg) | 426 if (!msg) |
| 402 return; | 427 return; |
| 403 | 428 |
| 404 /* Send to Purple */ | 429 /* Send to Purple */ |
| 405 purple_conversation_write(convo, NULL, (const char *)msg, | 430 purple_conversation_write(convo, NULL, (const char *)msg, |
| 406 PURPLE_MESSAGE_SYSTEM, time(NULL)); | 431 PURPLE_MESSAGE_SYSTEM, time(NULL)); |
| 407 g_free(msg); | 432 g_free(msg); |
| 408 return; | 433 return; |
| 409 } | 434 } |
| 410 | 435 |
| 411 if (flags & SILC_MESSAGE_FLAG_UTF8) { | 436 if (flags & SILC_MESSAGE_FLAG_UTF8) { |
| 412 tmp = g_markup_escape_text((const char *)message, -1); | 437 tmp = g_markup_escape_text((const char *)message, -1); |
| 413 /* Send to Purple */ | 438 /* Send to Purple */ |
| 414 serv_got_im(gc, sender->nickname ? | 439 serv_got_im(gc, sender->nickname, tmp, 0, time(NULL)); |
| 415 sender->nickname : "<unknown>", | |
| 416 tmp, 0, time(NULL)); | |
| 417 g_free(tmp); | 440 g_free(tmp); |
| 418 } | 441 } |
| 419 } | 442 } |
| 420 | 443 |
| 421 | 444 |
| 445 SilcHashTableList htl; | 468 SilcHashTableList htl; |
| 446 SilcChannelUser chu; | 469 SilcChannelUser chu; |
| 447 char buf[512], buf2[512], *tmp, *name; | 470 char buf[512], buf2[512], *tmp, *name; |
| 448 SilcNotifyType notify; | 471 SilcNotifyType notify; |
| 449 PurpleBuddy *b; | 472 PurpleBuddy *b; |
| 473 SilcDList list; | |
| 450 int i; | 474 int i; |
| 451 | 475 |
| 452 va_start(va, type); | 476 va_start(va, type); |
| 453 memset(buf, 0, sizeof(buf)); | 477 memset(buf, 0, sizeof(buf)); |
| 454 | 478 |
| 458 break; | 482 break; |
| 459 | 483 |
| 460 case SILC_NOTIFY_TYPE_INVITE: | 484 case SILC_NOTIFY_TYPE_INVITE: |
| 461 { | 485 { |
| 462 GHashTable *components; | 486 GHashTable *components; |
| 463 va_arg(va, SilcChannelEntry); | 487 (void)va_arg(va, SilcChannelEntry); |
| 464 name = va_arg(va, char *); | 488 name = va_arg(va, char *); |
| 465 client_entry = va_arg(va, SilcClientEntry); | 489 client_entry = va_arg(va, SilcClientEntry); |
| 466 | 490 |
| 467 components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | 491 components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); |
| 468 g_hash_table_insert(components, strdup("channel"), strdup(name)); | 492 g_hash_table_insert(components, strdup("channel"), strdup(name)); |
| 477 /* If we joined channel, do nothing */ | 501 /* If we joined channel, do nothing */ |
| 478 if (client_entry == conn->local_entry) | 502 if (client_entry == conn->local_entry) |
| 479 break; | 503 break; |
| 480 | 504 |
| 481 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, | 505 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, |
| 482 channel->channel_name, sg->account); | 506 channel->channel_name, sg->account); |
| 483 if (!convo) | 507 if (!convo) |
| 484 break; | 508 break; |
| 485 | 509 |
| 486 /* Join user to channel */ | 510 /* Join user to channel */ |
| 487 g_snprintf(buf, sizeof(buf), "%s@%s", | 511 g_snprintf(buf, sizeof(buf), "%s@%s", |
| 488 client_entry->username, client_entry->hostname); | 512 client_entry->username, client_entry->hostname); |
| 489 purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), | 513 purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), |
| 490 g_strdup(client_entry->nickname), buf, PURPLE_CBFLAGS_NONE, TRUE); | 514 g_strdup(client_entry->nickname), buf, PURPLE_CBFLAGS_NONE, TRUE); |
| 491 | 515 |
| 492 break; | 516 break; |
| 493 | 517 |
| 494 case SILC_NOTIFY_TYPE_LEAVE: | 518 case SILC_NOTIFY_TYPE_LEAVE: |
| 495 client_entry = va_arg(va, SilcClientEntry); | 519 client_entry = va_arg(va, SilcClientEntry); |
| 496 channel = va_arg(va, SilcChannelEntry); | 520 channel = va_arg(va, SilcChannelEntry); |
| 497 | 521 |
| 498 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, | 522 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, |
| 499 channel->channel_name, sg->account); | 523 channel->channel_name, sg->account); |
| 500 if (!convo) | 524 if (!convo) |
| 501 break; | 525 break; |
| 502 | 526 |
| 503 /* Remove user from channel */ | 527 /* Remove user from channel */ |
| 504 purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), | 528 purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), |
| 505 client_entry->nickname, NULL); | 529 client_entry->nickname, NULL); |
| 506 | 530 |
| 507 break; | 531 break; |
| 508 | 532 |
| 509 case SILC_NOTIFY_TYPE_SIGNOFF: | 533 case SILC_NOTIFY_TYPE_SIGNOFF: |
| 510 client_entry = va_arg(va, SilcClientEntry); | 534 client_entry = va_arg(va, SilcClientEntry); |
| 511 tmp = va_arg(va, char *); | 535 tmp = va_arg(va, char *); |
| 512 | |
| 513 if (!client_entry->nickname) | |
| 514 break; | |
| 515 | 536 |
| 516 /* Remove from all channels */ | 537 /* Remove from all channels */ |
| 517 silc_hash_table_list(client_entry->channels, &htl); | 538 silc_hash_table_list(client_entry->channels, &htl); |
| 518 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | 539 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { |
| 519 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, | 540 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, |
| 520 chu->channel->channel_name, sg->account); | 541 chu->channel->channel_name, sg->account); |
| 521 if (!convo) | 542 if (!convo) |
| 522 continue; | 543 continue; |
| 523 purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), | 544 purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), |
| 524 client_entry->nickname, | 545 client_entry->nickname, |
| 525 tmp); | 546 tmp); |
| 526 } | 547 } |
| 527 silc_hash_table_list_reset(&htl); | 548 silc_hash_table_list_reset(&htl); |
| 528 | 549 |
| 529 break; | 550 break; |
| 530 | 551 |
| 535 entry = va_arg(va, void *); | 556 entry = va_arg(va, void *); |
| 536 tmp = va_arg(va, char *); | 557 tmp = va_arg(va, char *); |
| 537 channel = va_arg(va, SilcChannelEntry); | 558 channel = va_arg(va, SilcChannelEntry); |
| 538 | 559 |
| 539 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, | 560 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, |
| 540 channel->channel_name, sg->account); | 561 channel->channel_name, sg->account); |
| 541 if (!convo) | 562 if (!convo) |
| 542 break; | 563 break; |
| 543 | 564 |
| 544 if (!tmp) | 565 if (!tmp) |
| 545 break; | 566 break; |
| 584 break; | 605 break; |
| 585 | 606 |
| 586 } | 607 } |
| 587 case SILC_NOTIFY_TYPE_NICK_CHANGE: | 608 case SILC_NOTIFY_TYPE_NICK_CHANGE: |
| 588 client_entry = va_arg(va, SilcClientEntry); | 609 client_entry = va_arg(va, SilcClientEntry); |
| 589 client_entry2 = va_arg(va, SilcClientEntry); | 610 tmp = va_arg(va, char *); /* Old nick */ |
| 590 | 611 name = va_arg(va, char *); /* New nick */ |
| 591 if (!strcmp(client_entry->nickname, client_entry2->nickname)) | 612 |
| 613 if (!strcmp(tmp, name)) | |
| 592 break; | 614 break; |
| 593 | 615 |
| 594 /* Change nick on all channels */ | 616 /* Change nick on all channels */ |
| 595 silc_hash_table_list(client_entry2->channels, &htl); | 617 silc_hash_table_list(client_entry->channels, &htl); |
| 596 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | 618 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { |
| 597 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, | 619 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, |
| 598 chu->channel->channel_name, sg->account); | 620 chu->channel->channel_name, sg->account); |
| 599 if (!convo) | 621 if (!convo) |
| 600 continue; | 622 continue; |
| 601 if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(convo), client_entry->nickname)) | 623 if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(convo), client_entry->nickname)) |
| 602 purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo), | 624 purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo), |
| 603 client_entry->nickname, | 625 tmp, name); |
| 604 client_entry2->nickname); | |
| 605 } | 626 } |
| 606 silc_hash_table_list_reset(&htl); | 627 silc_hash_table_list_reset(&htl); |
| 607 | 628 |
| 608 break; | 629 break; |
| 609 | 630 |
| 613 mode = va_arg(va, SilcUInt32); | 634 mode = va_arg(va, SilcUInt32); |
| 614 (void)va_arg(va, char *); | 635 (void)va_arg(va, char *); |
| 615 (void)va_arg(va, char *); | 636 (void)va_arg(va, char *); |
| 616 (void)va_arg(va, char *); | 637 (void)va_arg(va, char *); |
| 617 (void)va_arg(va, SilcPublicKey); | 638 (void)va_arg(va, SilcPublicKey); |
| 618 (void)va_arg(va, SilcBuffer); | 639 (void)va_arg(va, SilcDList); |
| 619 channel = va_arg(va, SilcChannelEntry); | 640 channel = va_arg(va, SilcChannelEntry); |
| 620 | 641 |
| 621 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, | 642 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, |
| 622 channel->channel_name, sg->account); | 643 channel->channel_name, sg->account); |
| 623 if (!convo) | 644 if (!convo) |
| 624 break; | 645 break; |
| 625 | 646 |
| 626 if (idtype == SILC_ID_CLIENT) | 647 if (idtype == SILC_ID_CLIENT) |
| 627 name = ((SilcClientEntry)entry)->nickname; | 648 name = ((SilcClientEntry)entry)->nickname; |
| 641 g_snprintf(buf, sizeof(buf), | 662 g_snprintf(buf, sizeof(buf), |
| 642 _("<I>%s</I> removed all channel <I>%s</I> modes"), name, | 663 _("<I>%s</I> removed all channel <I>%s</I> modes"), name, |
| 643 channel->channel_name); | 664 channel->channel_name); |
| 644 } | 665 } |
| 645 purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name, | 666 purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name, |
| 646 buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); | 667 buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); |
| 647 break; | 668 break; |
| 648 | 669 |
| 649 case SILC_NOTIFY_TYPE_CUMODE_CHANGE: | 670 case SILC_NOTIFY_TYPE_CUMODE_CHANGE: |
| 650 { | 671 { |
| 651 PurpleConvChatBuddyFlags flags = PURPLE_CBFLAGS_NONE; | 672 PurpleConvChatBuddyFlags flags = PURPLE_CBFLAGS_NONE; |
| 654 mode = va_arg(va, SilcUInt32); | 675 mode = va_arg(va, SilcUInt32); |
| 655 client_entry2 = va_arg(va, SilcClientEntry); | 676 client_entry2 = va_arg(va, SilcClientEntry); |
| 656 channel = va_arg(va, SilcChannelEntry); | 677 channel = va_arg(va, SilcChannelEntry); |
| 657 | 678 |
| 658 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, | 679 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, |
| 659 channel->channel_name, sg->account); | 680 channel->channel_name, sg->account); |
| 660 if (!convo) | 681 if (!convo) |
| 661 break; | 682 break; |
| 662 | 683 |
| 663 if (idtype == SILC_ID_CLIENT) | 684 if (idtype == SILC_ID_CLIENT) |
| 664 name = ((SilcClientEntry)entry)->nickname; | 685 name = ((SilcClientEntry)entry)->nickname; |
| 670 break; | 691 break; |
| 671 | 692 |
| 672 if (mode) { | 693 if (mode) { |
| 673 silcpurple_get_chumode_string(mode, buf2, sizeof(buf2)); | 694 silcpurple_get_chumode_string(mode, buf2, sizeof(buf2)); |
| 674 g_snprintf(buf, sizeof(buf), | 695 g_snprintf(buf, sizeof(buf), |
| 675 _("<I>%s</I> set <I>%s's</I> modes to: %s"), name, | 696 _("<I>%s</I> set <I>%s's</I> modes to: %s"), name, |
| 676 client_entry2->nickname, buf2); | 697 client_entry2->nickname, buf2); |
| 677 if (mode & SILC_CHANNEL_UMODE_CHANFO) | 698 if (mode & SILC_CHANNEL_UMODE_CHANFO) |
| 678 flags |= PURPLE_CBFLAGS_FOUNDER; | 699 flags |= PURPLE_CBFLAGS_FOUNDER; |
| 679 if (mode & SILC_CHANNEL_UMODE_CHANOP) | 700 if (mode & SILC_CHANNEL_UMODE_CHANOP) |
| 680 flags |= PURPLE_CBFLAGS_OP; | 701 flags |= PURPLE_CBFLAGS_OP; |
| 681 } else { | 702 } else { |
| 682 g_snprintf(buf, sizeof(buf), | 703 g_snprintf(buf, sizeof(buf), |
| 683 _("<I>%s</I> removed all <I>%s's</I> modes"), name, | 704 _("<I>%s</I> removed all <I>%s's</I> modes"), name, |
| 684 client_entry2->nickname); | 705 client_entry2->nickname); |
| 685 } | 706 } |
| 686 purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name, | 707 purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name, |
| 687 buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); | 708 buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); |
| 688 purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(convo), client_entry2->nickname, flags); | 709 purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(convo), client_entry2->nickname, flags); |
| 689 break; | 710 break; |
| 690 } | 711 } |
| 691 | 712 |
| 692 case SILC_NOTIFY_TYPE_MOTD: | 713 case SILC_NOTIFY_TYPE_MOTD: |
| 700 tmp = va_arg(va, char *); | 721 tmp = va_arg(va, char *); |
| 701 client_entry2 = va_arg(va, SilcClientEntry); | 722 client_entry2 = va_arg(va, SilcClientEntry); |
| 702 channel = va_arg(va, SilcChannelEntry); | 723 channel = va_arg(va, SilcChannelEntry); |
| 703 | 724 |
| 704 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, | 725 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, |
| 705 channel->channel_name, sg->account); | 726 channel->channel_name, sg->account); |
| 706 if (!convo) | 727 if (!convo) |
| 707 break; | 728 break; |
| 708 | 729 |
| 709 if (client_entry == conn->local_entry) { | 730 if (client_entry == conn->local_entry) { |
| 710 /* Remove us from channel */ | 731 /* Remove us from channel */ |
| 711 g_snprintf(buf, sizeof(buf), | 732 g_snprintf(buf, sizeof(buf), |
| 712 _("You have been kicked off <I>%s</I> by <I>%s</I> (%s)"), | 733 _("You have been kicked off <I>%s</I> by <I>%s</I> (%s)"), |
| 713 channel->channel_name, client_entry2->nickname, | 734 channel->channel_name, client_entry2->nickname, |
| 714 tmp ? tmp : ""); | 735 tmp ? tmp : ""); |
| 715 purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname, | 736 purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname, |
| 716 buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); | 737 buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); |
| 717 serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo))); | 738 serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo))); |
| 718 } else { | 739 } else { |
| 719 /* Remove user from channel */ | 740 /* Remove user from channel */ |
| 720 g_snprintf(buf, sizeof(buf), _("Kicked by %s (%s)"), | 741 g_snprintf(buf, sizeof(buf), _("Kicked by %s (%s)"), |
| 721 client_entry2->nickname, tmp ? tmp : ""); | 742 client_entry2->nickname, tmp ? tmp : ""); |
| 722 purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), | 743 purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), |
| 723 client_entry->nickname, | 744 client_entry->nickname, |
| 724 buf); | 745 buf); |
| 725 } | 746 } |
| 726 | 747 |
| 727 break; | 748 break; |
| 728 | 749 |
| 729 case SILC_NOTIFY_TYPE_KILLED: | 750 case SILC_NOTIFY_TYPE_KILLED: |
| 730 client_entry = va_arg(va, SilcClientEntry); | 751 client_entry = va_arg(va, SilcClientEntry); |
| 731 tmp = va_arg(va, char *); | 752 tmp = va_arg(va, char *); |
| 732 idtype = va_arg(va, int); | 753 idtype = va_arg(va, int); |
| 733 entry = va_arg(va, SilcClientEntry); | 754 entry = va_arg(va, SilcClientEntry); |
| 734 | |
| 735 if (!client_entry->nickname) | |
| 736 break; | |
| 737 | 755 |
| 738 if (client_entry == conn->local_entry) { | 756 if (client_entry == conn->local_entry) { |
| 739 if (idtype == SILC_ID_CLIENT) { | 757 if (idtype == SILC_ID_CLIENT) { |
| 740 client_entry2 = (SilcClientEntry)entry; | 758 client_entry2 = (SilcClientEntry)entry; |
| 741 g_snprintf(buf, sizeof(buf), | 759 g_snprintf(buf, sizeof(buf), |
| 759 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, | 777 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, |
| 760 chu->channel->channel_name, sg->account); | 778 chu->channel->channel_name, sg->account); |
| 761 if (!convo) | 779 if (!convo) |
| 762 continue; | 780 continue; |
| 763 purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname, | 781 purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname, |
| 764 buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); | 782 buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); |
| 765 serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo))); | 783 serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo))); |
| 766 } | 784 } |
| 767 silc_hash_table_list_reset(&htl); | 785 silc_hash_table_list_reset(&htl); |
| 768 | 786 |
| 769 } else { | 787 } else { |
| 790 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, | 808 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, |
| 791 chu->channel->channel_name, sg->account); | 809 chu->channel->channel_name, sg->account); |
| 792 if (!convo) | 810 if (!convo) |
| 793 continue; | 811 continue; |
| 794 purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), | 812 purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), |
| 795 client_entry->nickname, tmp); | 813 client_entry->nickname, tmp); |
| 796 } | 814 } |
| 797 silc_hash_table_list_reset(&htl); | 815 silc_hash_table_list_reset(&htl); |
| 798 } | 816 } |
| 799 | 817 |
| 800 break; | 818 break; |
| 801 | 819 |
| 802 case SILC_NOTIFY_TYPE_CHANNEL_CHANGE: | 820 case SILC_NOTIFY_TYPE_CHANNEL_CHANGE: |
| 803 break; | 821 break; |
| 804 | 822 |
| 805 case SILC_NOTIFY_TYPE_SERVER_SIGNOFF: | 823 case SILC_NOTIFY_TYPE_SERVER_SIGNOFF: |
| 806 { | 824 (void)va_arg(va, void *); |
| 807 int i; | 825 list = va_arg(va, SilcDList); |
| 808 SilcClientEntry *clients; | 826 |
| 809 SilcUInt32 clients_count; | 827 silc_dlist_start(list); |
| 810 | 828 while ((client_entry = silc_dlist_get(list))) { |
| 811 (void)va_arg(va, void *); | 829 /* Remove from all channels */ |
| 812 clients = va_arg(va, SilcClientEntry *); | 830 silc_hash_table_list(client_entry->channels, &htl); |
| 813 clients_count = va_arg(va, SilcUInt32); | 831 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { |
| 814 | 832 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, |
| 815 for (i = 0; i < clients_count; i++) { | 833 chu->channel->channel_name, sg->account); |
| 816 if (!clients[i]->nickname) | 834 if (!convo) |
| 817 break; | 835 continue; |
| 818 | 836 purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), |
| 819 /* Remove from all channels */ | 837 client_entry->nickname, |
| 820 silc_hash_table_list(clients[i]->channels, &htl); | 838 _("Server signoff")); |
| 821 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | 839 } |
| 822 convo = | 840 silc_hash_table_list_reset(&htl); |
| 823 purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, | |
| 824 chu->channel->channel_name, sg->account); | |
| 825 if (!convo) | |
| 826 continue; | |
| 827 purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), | |
| 828 clients[i]->nickname, | |
| 829 _("Server signoff")); | |
| 830 } | |
| 831 silc_hash_table_list_reset(&htl); | |
| 832 } | |
| 833 } | 841 } |
| 834 break; | 842 break; |
| 835 | 843 |
| 836 case SILC_NOTIFY_TYPE_ERROR: | 844 case SILC_NOTIFY_TYPE_ERROR: |
| 837 { | 845 { |
| 838 SilcStatus error = va_arg(va, int); | 846 SilcStatus error = va_arg(va, int); |
| 839 purple_notify_error(gc, "Error Notify", | 847 purple_notify_error(gc, "Error Notify", |
| 840 silc_get_status_message(error), | 848 silc_get_status_message(error), |
| 841 NULL); | 849 NULL); |
| 842 } | 850 } |
| 843 break; | 851 break; |
| 844 | 852 |
| 845 case SILC_NOTIFY_TYPE_WATCH: | 853 case SILC_NOTIFY_TYPE_WATCH: |
| 846 { | 854 { |
| 907 break; | 915 break; |
| 908 } | 916 } |
| 909 } | 917 } |
| 910 | 918 |
| 911 silc_free(b->proto_data); | 919 silc_free(b->proto_data); |
| 912 b->proto_data = silc_memdup(client_entry->id, | 920 b->proto_data = silc_memdup(&client_entry->id, |
| 913 sizeof(*client_entry->id)); | 921 sizeof(client_entry->id)); |
| 914 if (notify == SILC_NOTIFY_TYPE_NICK_CHANGE) { | 922 if (notify == SILC_NOTIFY_TYPE_NICK_CHANGE) { |
| 915 break; | 923 break; |
| 916 } else if (notify == SILC_NOTIFY_TYPE_UMODE_CHANGE) { | 924 } else if (notify == SILC_NOTIFY_TYPE_UMODE_CHANGE) { |
| 917 /* See if client was away and is now present */ | 925 /* See if client was away and is now present */ |
| 918 if (!(mode & (SILC_UMODE_GONE | SILC_UMODE_INDISPOSED | | 926 if (!(mode & (SILC_UMODE_GONE | SILC_UMODE_INDISPOSED | |
| 953 | 961 |
| 954 va_end(va); | 962 va_end(va); |
| 955 } | 963 } |
| 956 | 964 |
| 957 | 965 |
| 958 /* Command handler. This function is called always in the command function. | 966 /* Command handler. This function is called always after application has |
| 959 If error occurs it will be called as well. `conn' is the associated | 967 called a command. It will be called to indicate that the command |
| 960 client connection. `cmd_context' is the command context that was | 968 was processed. It will also be called if error occurs while processing |
| 961 originally sent to the command. `success' is FALSE if error occurred | 969 the command. The `success' indicates whether the command was sent |
| 962 during command. `command' is the command being processed. It must be | 970 or if error occurred. The `status' indicates the actual error. |
| 963 noted that this is not reply from server. This is merely called just | 971 The `argc' and `argv' are the command line arguments sent to the |
| 964 after application has called the command. Just to tell application | 972 command by application. Note that, this is not reply to the command |
| 965 that the command really was processed. */ | 973 from server, this is merely and indication to application that the |
| 974 command was processed. */ | |
| 966 | 975 |
| 967 static void | 976 static void |
| 968 silc_command(SilcClient client, SilcClientConnection conn, | 977 silc_command(SilcClient client, SilcClientConnection conn, |
| 969 SilcClientCommandContext cmd_context, bool success, | 978 SilcBool success, SilcCommand command, SilcStatus status, |
| 970 SilcCommand command, SilcStatus status) | 979 SilcUInt32 argc, unsigned char **argv) |
| 971 { | 980 { |
| 972 PurpleConnection *gc = client->application; | 981 PurpleConnection *gc = client->application; |
| 973 SilcPurple sg = gc->proto_data; | 982 SilcPurple sg = gc->proto_data; |
| 974 | 983 |
| 975 switch (command) { | 984 switch (command) { |
| 976 | 985 |
| 977 case SILC_COMMAND_CMODE: | 986 case SILC_COMMAND_CMODE: |
| 978 if (cmd_context->argc == 3 && | 987 if (argc == 3 && !strcmp((char *)argv[2], "+C")) |
| 979 !strcmp((char *)cmd_context->argv[2], "+C")) | |
| 980 sg->chpk = TRUE; | 988 sg->chpk = TRUE; |
| 981 else | 989 else |
| 982 sg->chpk = FALSE; | 990 sg->chpk = FALSE; |
| 983 break; | 991 break; |
| 984 | 992 |
| 1088 buf); | 1096 buf); |
| 1089 g_free(buf); | 1097 g_free(buf); |
| 1090 } | 1098 } |
| 1091 #endif | 1099 #endif |
| 1092 | 1100 |
| 1093 /* Command reply handler. This function is called always in the command reply | 1101 |
| 1094 function. If error occurs it will be called as well. Normal scenario | 1102 /* Command reply handler. Delivers a reply to command that was sent |
| 1095 is that it will be called after the received command data has been parsed | 1103 earlier. The `conn' is the associated client connection. The `command' |
| 1096 and processed. The function is used to pass the received command data to | 1104 indicates the command reply type. If the `status' other than |
| 1097 the application. | 1105 SILC_STATUS_OK an error occurred. In this case the `error' will indicate |
| 1098 | 1106 the error. It is possible to receive list of command replies and list |
| 1099 `conn' is the associated client connection. `cmd_payload' is the command | 1107 of errors. In this case the `status' will indicate it is an list entry |
| 1100 payload data received from server and it can be ignored. It is provided | 1108 (the `status' is SILC_STATUS_LIST_START, SILC_STATUS_LIST_ITEM and/or |
| 1101 if the application would like to re-parse the received command data, | 1109 SILC_STATUS_LIST_END). |
| 1102 however, it must be noted that the data is parsed already by the library | 1110 |
| 1103 thus the payload can be ignored. `success' is FALSE if error occurred. | 1111 The arguments received in `ap' are command specific. See a separate |
| 1104 In this case arguments are not sent to the application. The `status' is | 1112 documentation in the Toolkit Reference Manual for the command reply |
| 1105 the command reply status server returned. The `command' is the command | 1113 arguments. */ |
| 1106 reply being processed. The function has variable argument list and each | |
| 1107 command defines the number and type of arguments it passes to the | |
| 1108 application (on error they are not sent). */ | |
| 1109 | 1114 |
| 1110 static void | 1115 static void |
| 1111 silc_command_reply(SilcClient client, SilcClientConnection conn, | 1116 silc_command_reply(SilcClient client, SilcClientConnection conn, |
| 1112 SilcCommandPayload cmd_payload, bool success, | 1117 SilcCommand command, SilcStatus status, |
| 1113 SilcCommand command, SilcStatus status, ...) | 1118 SilcStatus error, va_list ap) |
| 1114 { | 1119 { |
| 1115 PurpleConnection *gc = client->application; | 1120 PurpleConnection *gc = client->application; |
| 1116 SilcPurple sg = gc->proto_data; | 1121 SilcPurple sg = gc->proto_data; |
| 1117 PurpleConversation *convo; | 1122 PurpleConversation *convo; |
| 1118 va_list vp; | |
| 1119 | |
| 1120 va_start(vp, status); | |
| 1121 | 1123 |
| 1122 switch (command) { | 1124 switch (command) { |
| 1123 case SILC_COMMAND_JOIN: | 1125 case SILC_COMMAND_JOIN: |
| 1124 { | 1126 { |
| 1125 SilcChannelEntry channel_entry; | 1127 SilcChannelEntry channel; |
| 1126 | 1128 PurpleConversation *convo; |
| 1127 if (!success) { | 1129 SilcHashTableList *user_list; |
| 1130 SilcChannelUser chu; | |
| 1131 GList *users = NULL, *flags = NULL; | |
| 1132 char tmp[256], *topic; | |
| 1133 | |
| 1134 if (status != SILC_STATUS_OK) { | |
| 1128 purple_notify_error(gc, _("Join Chat"), _("Cannot join channel"), | 1135 purple_notify_error(gc, _("Join Chat"), _("Cannot join channel"), |
| 1129 silc_get_status_message(status)); | 1136 silc_get_status_message(error)); |
| 1130 return; | 1137 return; |
| 1131 } | 1138 } |
| 1132 | 1139 |
| 1133 (void)va_arg(vp, char *); | 1140 (void)va_arg(ap, char *); |
| 1134 channel_entry = va_arg(vp, SilcChannelEntry); | 1141 channel = va_arg(ap, SilcChannelEntry); |
| 1135 | 1142 (void)va_arg(ap, SilcUInt32); |
| 1136 /* Resolve users on channel */ | 1143 user_list = va_arg(ap, SilcHashTableList *); |
| 1137 silc_client_get_clients_by_channel(client, conn, channel_entry, | 1144 topic = va_arg(ap, char *); |
| 1138 silcpurple_chat_join_done, | 1145 |
| 1139 channel_entry); | 1146 /* Add channel to Purple */ |
| 1147 channel->context = SILC_32_TO_PTR(++sg->channel_ids); | |
| 1148 serv_got_joined_chat(gc, sg->channel_ids, channel->channel_name); | |
| 1149 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, | |
| 1150 channel->channel_name, sg->account); | |
| 1151 if (!convo) | |
| 1152 return; | |
| 1153 | |
| 1154 /* Add all users to channel */ | |
| 1155 while (silc_hash_table_get(user_list, NULL, (void *)&chu)) { | |
| 1156 PurpleConvChatBuddyFlags f = PURPLE_CBFLAGS_NONE; | |
| 1157 chu->context = SILC_32_TO_PTR(sg->channel_ids); | |
| 1158 | |
| 1159 if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) | |
| 1160 f |= PURPLE_CBFLAGS_FOUNDER; | |
| 1161 if (chu->mode & SILC_CHANNEL_UMODE_CHANOP) | |
| 1162 f |= PURPLE_CBFLAGS_OP; | |
| 1163 users = g_list_append(users, g_strdup(chu->client->nickname)); | |
| 1164 flags = g_list_append(flags, GINT_TO_POINTER(f)); | |
| 1165 | |
| 1166 if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) { | |
| 1167 if (chu->client == conn->local_entry) | |
| 1168 g_snprintf(tmp, sizeof(tmp), | |
| 1169 _("You are channel founder on <I>%s</I>"), | |
| 1170 channel->channel_name); | |
| 1171 else | |
| 1172 g_snprintf(tmp, sizeof(tmp), | |
| 1173 _("Channel founder on <I>%s</I> is <I>%s</I>"), | |
| 1174 channel->channel_name, chu->client->nickname); | |
| 1175 | |
| 1176 purple_conversation_write(convo, NULL, tmp, | |
| 1177 PURPLE_MESSAGE_SYSTEM, time(NULL)); | |
| 1178 } | |
| 1179 } | |
| 1180 | |
| 1181 purple_conv_chat_add_users(PURPLE_CONV_CHAT(convo), users, NULL, flags, FALSE); | |
| 1182 g_list_free(users); | |
| 1183 g_list_free(flags); | |
| 1184 | |
| 1185 /* Set topic */ | |
| 1186 if (topic) | |
| 1187 purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, topic); | |
| 1188 | |
| 1189 /* Set nick */ | |
| 1190 purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), conn->local_entry->nickname); | |
| 1140 } | 1191 } |
| 1141 break; | 1192 break; |
| 1142 | 1193 |
| 1143 case SILC_COMMAND_LEAVE: | 1194 case SILC_COMMAND_LEAVE: |
| 1144 break; | 1195 break; |
| 1146 case SILC_COMMAND_USERS: | 1197 case SILC_COMMAND_USERS: |
| 1147 break; | 1198 break; |
| 1148 | 1199 |
| 1149 case SILC_COMMAND_WHOIS: | 1200 case SILC_COMMAND_WHOIS: |
| 1150 { | 1201 { |
| 1151 SilcUInt32 idle, mode; | 1202 SilcUInt32 idle, *user_modes; |
| 1152 SilcBuffer channels, user_modes; | 1203 SilcDList channels; |
| 1153 SilcClientEntry client_entry; | 1204 SilcClientEntry client_entry; |
| 1154 char tmp[1024], *tmp2; | 1205 char tmp[1024], *tmp2; |
| 1155 char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr; | 1206 char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr; |
| 1156 PurpleNotifyUserInfo *user_info; | 1207 PurpleNotifyUserInfo *user_info; |
| 1157 | 1208 |
| 1158 if (!success) { | 1209 if (status != SILC_STATUS_OK) { |
| 1159 purple_notify_error(gc, _("User Information"), | 1210 purple_notify_error(gc, _("User Information"), |
| 1160 _("Cannot get user information"), | 1211 _("Cannot get user information"), |
| 1161 silc_get_status_message(status)); | 1212 silc_get_status_message(error)); |
| 1162 break; | 1213 break; |
| 1163 } | 1214 } |
| 1164 | 1215 |
| 1165 client_entry = va_arg(vp, SilcClientEntry); | 1216 client_entry = va_arg(ap, SilcClientEntry); |
| 1166 if (!client_entry->nickname) | 1217 (void)va_arg(ap, char *); |
| 1167 break; | 1218 (void)va_arg(ap, char *); |
| 1168 (void)va_arg(vp, char *); | 1219 (void)va_arg(ap, char *); |
| 1169 (void)va_arg(vp, char *); | 1220 channels = va_arg(ap, SilcDList); |
| 1170 (void)va_arg(vp, char *); | 1221 (void)va_arg(ap, SilcUInt32); |
| 1171 channels = va_arg(vp, SilcBuffer); | 1222 idle = va_arg(ap, SilcUInt32); |
| 1172 mode = va_arg(vp, SilcUInt32); | 1223 (void)va_arg(ap, unsigned char *); |
| 1173 idle = va_arg(vp, SilcUInt32); | 1224 user_modes = va_arg(ap, SilcUInt32 *); |
| 1174 (void)va_arg(vp, unsigned char *); | |
| 1175 user_modes = va_arg(vp, SilcBuffer); | |
| 1176 | 1225 |
| 1177 user_info = purple_notify_user_info_new(); | 1226 user_info = purple_notify_user_info_new(); |
| 1178 tmp2 = g_markup_escape_text(client_entry->nickname, -1); | 1227 tmp2 = g_markup_escape_text(client_entry->nickname, -1); |
| 1179 purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp2); | 1228 purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp2); |
| 1180 g_free(tmp2); | 1229 g_free(tmp2); |
| 1181 if (client_entry->realname) { | 1230 if (client_entry->realname) { |
| 1182 tmp2 = g_markup_escape_text(client_entry->realname, -1); | 1231 tmp2 = g_markup_escape_text(client_entry->realname, -1); |
| 1183 purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp2); | 1232 purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp2); |
| 1184 g_free(tmp2); | 1233 g_free(tmp2); |
| 1185 } | 1234 } |
| 1186 if (client_entry->username) { | 1235 tmp2 = g_markup_escape_text(client_entry->username, -1); |
| 1187 tmp2 = g_markup_escape_text(client_entry->username, -1); | 1236 if (*client_entry->hostname) { |
| 1188 if (client_entry->hostname) { | 1237 gchar *tmp3; |
| 1189 gchar *tmp3; | 1238 tmp3 = g_strdup_printf("%s@%s", tmp2, client_entry->hostname); |
| 1190 tmp3 = g_strdup_printf("%s@%s", tmp2, client_entry->hostname); | 1239 purple_notify_user_info_add_pair(user_info, _("Username"), tmp3); |
| 1191 purple_notify_user_info_add_pair(user_info, _("Username"), tmp3); | 1240 g_free(tmp3); |
| 1192 g_free(tmp3); | 1241 } else |
| 1193 } else | 1242 purple_notify_user_info_add_pair(user_info, _("Username"), tmp2); |
| 1194 purple_notify_user_info_add_pair(user_info, _("Username"), tmp2); | 1243 g_free(tmp2); |
| 1195 g_free(tmp2); | |
| 1196 } | |
| 1197 | 1244 |
| 1198 if (client_entry->mode) { | 1245 if (client_entry->mode) { |
| 1199 memset(tmp, 0, sizeof(tmp)); | 1246 memset(tmp, 0, sizeof(tmp)); |
| 1200 silcpurple_get_umode_string(client_entry->mode, | 1247 silcpurple_get_umode_string(client_entry->mode, |
| 1201 tmp, sizeof(tmp) - strlen(tmp)); | 1248 tmp, sizeof(tmp) - strlen(tmp)); |
| 1202 purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp); | 1249 purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp); |
| 1203 } | 1250 } |
| 1204 | 1251 |
| 1205 silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr); | 1252 silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr); |
| 1206 if (moodstr) { | 1253 if (moodstr) { |
| 1238 if (geostr) { | 1285 if (geostr) { |
| 1239 purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr); | 1286 purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr); |
| 1240 g_free(geostr); | 1287 g_free(geostr); |
| 1241 } | 1288 } |
| 1242 | 1289 |
| 1243 if (client_entry->server) | 1290 if (*client_entry->server) |
| 1244 purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server); | 1291 purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server); |
| 1245 | 1292 |
| 1246 if (channels && user_modes) { | 1293 if (channels && user_modes) { |
| 1247 SilcUInt32 *umodes; | 1294 SilcChannelPayload entry; |
| 1248 SilcDList list = | 1295 int i = 0; |
| 1249 silc_channel_payload_parse_list(channels->data, | 1296 |
| 1250 channels->len); | 1297 memset(tmp, 0, sizeof(tmp)); |
| 1251 if (list && silc_get_mode_list(user_modes, | 1298 silc_dlist_start(channels); |
| 1252 silc_dlist_count(list), | 1299 while ((entry = silc_dlist_get(channels))) { |
| 1253 &umodes)) { | 1300 SilcUInt32 name_len; |
| 1254 SilcChannelPayload entry; | 1301 char *m = silc_client_chumode_char(user_modes[i++]); |
| 1255 int i = 0; | 1302 char *name = (char *)silc_channel_get_name(entry, &name_len); |
| 1256 | 1303 if (m) |
| 1257 memset(tmp, 0, sizeof(tmp)); | 1304 silc_strncat(tmp, sizeof(tmp) - 1, m, strlen(m)); |
| 1258 silc_dlist_start(list); | 1305 silc_strncat(tmp, sizeof(tmp) - 1, name, name_len); |
| 1259 while ((entry = silc_dlist_get(list)) | 1306 silc_strncat(tmp, sizeof(tmp) - 1, " ", 1); |
| 1260 != SILC_LIST_END) { | 1307 silc_free(m); |
| 1261 SilcUInt32 name_len; | |
| 1262 char *m = silc_client_chumode_char(umodes[i++]); | |
| 1263 char *name = (char *)silc_channel_get_name(entry, &name_len); | |
| 1264 if (m) | |
| 1265 silc_strncat(tmp, sizeof(tmp) - 1, m, strlen(m)); | |
| 1266 silc_strncat(tmp, sizeof(tmp) - 1, name, name_len); | |
| 1267 silc_strncat(tmp, sizeof(tmp) - 1, " ", 1); | |
| 1268 silc_free(m); | |
| 1269 | |
| 1270 } | |
| 1271 tmp2 = g_markup_escape_text(tmp, -1); | |
| 1272 purple_notify_user_info_add_pair(user_info, _("Currently on"), tmp2); | |
| 1273 g_free(tmp2); | |
| 1274 silc_free(umodes); | |
| 1275 } | 1308 } |
| 1309 tmp2 = g_markup_escape_text(tmp, -1); | |
| 1310 purple_notify_user_info_add_pair(user_info, _("Currently on"), tmp2); | |
| 1311 g_free(tmp2); | |
| 1276 } | 1312 } |
| 1277 | 1313 |
| 1278 if (client_entry->public_key) { | 1314 if (client_entry->public_key) { |
| 1279 char *fingerprint, *babbleprint; | 1315 char *fingerprint, *babbleprint; |
| 1280 unsigned char *pk; | 1316 unsigned char *pk; |
| 1295 _("User Information"), | 1331 _("User Information"), |
| 1296 buf, 1, client_entry, 2, | 1332 buf, 1, client_entry, 2, |
| 1297 _("OK"), G_CALLBACK(silcpurple_whois_more), | 1333 _("OK"), G_CALLBACK(silcpurple_whois_more), |
| 1298 _("_More..."), G_CALLBACK(silcpurple_whois_more), gc->account, NULL, NULL); | 1334 _("_More..."), G_CALLBACK(silcpurple_whois_more), gc->account, NULL, NULL); |
| 1299 else | 1335 else |
| 1300 #endif | 1336 #endif /* 0 */ |
| 1301 purple_notify_userinfo(gc, client_entry->nickname, user_info, NULL, NULL); | 1337 purple_notify_userinfo(gc, client_entry->nickname, user_info, NULL, NULL); |
| 1302 purple_notify_user_info_destroy(user_info); | 1338 purple_notify_user_info_destroy(user_info); |
| 1303 } | 1339 } |
| 1304 break; | 1340 break; |
| 1305 | 1341 |
| 1307 { | 1343 { |
| 1308 SilcClientEntry client_entry; | 1344 SilcClientEntry client_entry; |
| 1309 char *nickname, *realname, *username, *tmp; | 1345 char *nickname, *realname, *username, *tmp; |
| 1310 PurpleNotifyUserInfo *user_info; | 1346 PurpleNotifyUserInfo *user_info; |
| 1311 | 1347 |
| 1312 if (!success) { | 1348 if (status != SILC_STATUS_OK) { |
| 1313 purple_notify_error(gc, _("User Information"), | 1349 purple_notify_error(gc, _("User Information"), |
| 1314 _("Cannot get user information"), | 1350 _("Cannot get user information"), |
| 1315 silc_get_status_message(status)); | 1351 silc_get_status_message(error)); |
| 1316 break; | 1352 break; |
| 1317 } | 1353 } |
| 1318 | 1354 |
| 1319 client_entry = va_arg(vp, SilcClientEntry); | 1355 client_entry = va_arg(ap, SilcClientEntry); |
| 1320 nickname = va_arg(vp, char *); | 1356 nickname = va_arg(ap, char *); |
| 1321 username = va_arg(vp, char *); | 1357 username = va_arg(ap, char *); |
| 1322 realname = va_arg(vp, char *); | 1358 realname = va_arg(ap, char *); |
| 1323 if (!nickname) | 1359 if (!nickname) |
| 1324 break; | 1360 break; |
| 1325 | 1361 |
| 1326 user_info = purple_notify_user_info_new(); | 1362 user_info = purple_notify_user_info_new(); |
| 1327 tmp = g_markup_escape_text(nickname, -1); | 1363 tmp = g_markup_escape_text(nickname, -1); |
| 1332 purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp); | 1368 purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp); |
| 1333 g_free(tmp); | 1369 g_free(tmp); |
| 1334 } | 1370 } |
| 1335 if (username) { | 1371 if (username) { |
| 1336 tmp = g_markup_escape_text(username, -1); | 1372 tmp = g_markup_escape_text(username, -1); |
| 1337 if (client_entry && client_entry->hostname) { | 1373 if (client_entry && *client_entry->hostname) { |
| 1338 gchar *tmp3; | 1374 gchar *tmp3; |
| 1339 tmp3 = g_strdup_printf("%s@%s", tmp, client_entry->hostname); | 1375 tmp3 = g_strdup_printf("%s@%s", tmp, client_entry->hostname); |
| 1340 purple_notify_user_info_add_pair(user_info, _("Username"), tmp3); | 1376 purple_notify_user_info_add_pair(user_info, _("Username"), tmp3); |
| 1341 g_free(tmp3); | 1377 g_free(tmp3); |
| 1342 } else | 1378 } else |
| 1343 purple_notify_user_info_add_pair(user_info, _("Username"), tmp); | 1379 purple_notify_user_info_add_pair(user_info, _("Username"), tmp); |
| 1344 g_free(tmp); | 1380 g_free(tmp); |
| 1345 } | 1381 } |
| 1346 if (client_entry && client_entry->server) | 1382 if (client_entry && *client_entry->server) |
| 1347 purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server); | 1383 purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server); |
| 1348 | 1384 |
| 1349 | 1385 |
| 1350 if (client_entry && client_entry->public_key) { | 1386 if (client_entry && client_entry->public_key) { |
| 1351 char *fingerprint, *babbleprint; | 1387 char *fingerprint, *babbleprint; |
| 1365 purple_notify_user_info_destroy(user_info); | 1401 purple_notify_user_info_destroy(user_info); |
| 1366 } | 1402 } |
| 1367 break; | 1403 break; |
| 1368 | 1404 |
| 1369 case SILC_COMMAND_DETACH: | 1405 case SILC_COMMAND_DETACH: |
| 1370 if (!success) { | 1406 { |
| 1371 purple_notify_error(gc, _("Detach From Server"), _("Cannot detach"), | 1407 const char *file; |
| 1372 silc_get_status_message(status)); | 1408 SilcBuffer detach_data; |
| 1373 return; | 1409 |
| 1410 if (status != SILC_STATUS_OK) { | |
| 1411 purple_notify_error(gc, _("Detach From Server"), _("Cannot detach"), | |
| 1412 silc_get_status_message(error)); | |
| 1413 return; | |
| 1414 } | |
| 1415 | |
| 1416 detach_data = va_arg(ap, SilcBuffer); | |
| 1417 | |
| 1418 /* Save the detachment data to file. */ | |
| 1419 file = silcpurple_session_file(purple_account_get_username(sg->account)); | |
| 1420 g_unlink(file); | |
| 1421 silc_file_writefile(file, (const char *)silc_buffer_data(detach_data), | |
| 1422 silc_buffer_len(detach_data)); | |
| 1374 } | 1423 } |
| 1375 break; | 1424 break; |
| 1376 | 1425 |
| 1377 case SILC_COMMAND_TOPIC: | 1426 case SILC_COMMAND_TOPIC: |
| 1378 { | 1427 { |
| 1379 SilcChannelEntry channel; | 1428 SilcChannelEntry channel; |
| 1380 | 1429 |
| 1381 if (!success) { | 1430 if (status != SILC_STATUS_OK) { |
| 1382 purple_notify_error(gc, _("Topic"), _("Cannot set topic"), | 1431 purple_notify_error(gc, _("Topic"), _("Cannot set topic"), |
| 1383 silc_get_status_message(status)); | 1432 silc_get_status_message(error)); |
| 1384 return; | 1433 return; |
| 1385 } | 1434 } |
| 1386 | 1435 |
| 1387 channel = va_arg(vp, SilcChannelEntry); | 1436 channel = va_arg(ap, SilcChannelEntry); |
| 1388 | 1437 |
| 1389 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, | 1438 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, |
| 1390 channel->channel_name, sg->account); | 1439 channel->channel_name, sg->account); |
| 1391 if (!convo) { | 1440 if (!convo) { |
| 1392 purple_debug_error("silc", "Got a topic for %s, which doesn't exist\n", | 1441 purple_debug_error("silc", "Got a topic for %s, which doesn't exist\n", |
| 1393 channel->channel_name); | 1442 channel->channel_name); |
| 1394 break; | 1443 break; |
| 1395 } | 1444 } |
| 1396 | 1445 |
| 1397 /* Set topic */ | 1446 /* Set topic */ |
| 1398 if (channel->topic) | 1447 if (channel->topic) |
| 1400 } | 1449 } |
| 1401 break; | 1450 break; |
| 1402 | 1451 |
| 1403 case SILC_COMMAND_NICK: | 1452 case SILC_COMMAND_NICK: |
| 1404 { | 1453 { |
| 1405 /* I don't think we should need to do this because the server should | |
| 1406 * be sending a SILC_NOTIFY_TYPE_NICK_CHANGE when we change our own | |
| 1407 * nick, but it isn't, so we deal with it here instead. Stu. */ | |
| 1408 SilcClientEntry local_entry; | 1454 SilcClientEntry local_entry; |
| 1409 SilcHashTableList htl; | 1455 SilcHashTableList htl; |
| 1410 SilcChannelUser chu; | 1456 SilcChannelUser chu; |
| 1411 const char *oldnick; | 1457 const char *oldnick, *newnick; |
| 1412 | 1458 |
| 1413 if (!success) { | 1459 if (status != SILC_STATUS_OK) { |
| 1414 purple_notify_error(gc, _("Nick"), _("Failed to change nickname"), | 1460 purple_notify_error(gc, _("Nick"), _("Failed to change nickname"), |
| 1415 silc_get_status_message(status)); | 1461 silc_get_status_message(error)); |
| 1416 return; | 1462 return; |
| 1417 } | 1463 } |
| 1418 | 1464 |
| 1419 local_entry = va_arg(vp, SilcClientEntry); | 1465 local_entry = va_arg(ap, SilcClientEntry); |
| 1466 newnick = va_arg(ap, char *); | |
| 1420 | 1467 |
| 1421 /* Change nick on all channels */ | 1468 /* Change nick on all channels */ |
| 1422 silc_hash_table_list(local_entry->channels, &htl); | 1469 silc_hash_table_list(local_entry->channels, &htl); |
| 1423 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { | 1470 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { |
| 1424 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, | 1471 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, |
| 1425 chu->channel->channel_name, sg->account); | 1472 chu->channel->channel_name, sg->account); |
| 1426 if (!convo) | 1473 if (!convo) |
| 1427 continue; | 1474 continue; |
| 1428 oldnick = purple_conv_chat_get_nick(PURPLE_CONV_CHAT(convo)); | 1475 oldnick = purple_conv_chat_get_nick(PURPLE_CONV_CHAT(convo)); |
| 1429 if (strcmp(oldnick, purple_normalize(purple_conversation_get_account(convo), local_entry->nickname))) { | 1476 if (strcmp(oldnick, purple_normalize(purple_conversation_get_account(convo), newnick))) { |
| 1430 purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo), | 1477 purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo), |
| 1431 oldnick, local_entry->nickname); | 1478 oldnick, newnick); |
| 1432 purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), local_entry->nickname); | 1479 purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), newnick); |
| 1433 } | 1480 } |
| 1434 } | 1481 } |
| 1435 silc_hash_table_list_reset(&htl); | 1482 silc_hash_table_list_reset(&htl); |
| 1436 | 1483 |
| 1437 purple_connection_set_display_name(gc, local_entry->nickname); | 1484 purple_connection_set_display_name(gc, newnick); |
| 1438 } | 1485 } |
| 1439 break; | 1486 break; |
| 1440 | 1487 |
| 1441 case SILC_COMMAND_LIST: | 1488 case SILC_COMMAND_LIST: |
| 1442 { | 1489 { |
| 1445 PurpleRoomlistRoom *room; | 1492 PurpleRoomlistRoom *room; |
| 1446 | 1493 |
| 1447 if (sg->roomlist_canceled) | 1494 if (sg->roomlist_canceled) |
| 1448 break; | 1495 break; |
| 1449 | 1496 |
| 1450 if (!success) { | 1497 if (error != SILC_STATUS_OK) { |
| 1451 purple_notify_error(gc, _("Error"), _("Error retrieving room list"), | 1498 purple_notify_error(gc, _("Error"), _("Error retrieving room list"), |
| 1452 silc_get_status_message(status)); | 1499 silc_get_status_message(error)); |
| 1453 purple_roomlist_set_in_progress(sg->roomlist, FALSE); | 1500 purple_roomlist_set_in_progress(sg->roomlist, FALSE); |
| 1454 purple_roomlist_unref(sg->roomlist); | 1501 purple_roomlist_unref(sg->roomlist); |
| 1455 sg->roomlist = NULL; | 1502 sg->roomlist = NULL; |
| 1456 return; | 1503 return; |
| 1457 } | 1504 } |
| 1458 | 1505 |
| 1459 (void)va_arg(vp, SilcChannelEntry); | 1506 (void)va_arg(ap, SilcChannelEntry); |
| 1460 name = va_arg(vp, char *); | 1507 name = va_arg(ap, char *); |
| 1461 if (!name) { | 1508 if (!name) { |
| 1462 purple_notify_error(gc, _("Roomlist"), _("Cannot get room list"), | 1509 purple_notify_error(gc, _("Roomlist"), _("Cannot get room list"), |
| 1463 silc_get_status_message(status)); | 1510 _("Network is empty")); |
| 1464 purple_roomlist_set_in_progress(sg->roomlist, FALSE); | 1511 purple_roomlist_set_in_progress(sg->roomlist, FALSE); |
| 1465 purple_roomlist_unref(sg->roomlist); | 1512 purple_roomlist_unref(sg->roomlist); |
| 1466 sg->roomlist = NULL; | 1513 sg->roomlist = NULL; |
| 1467 return; | 1514 return; |
| 1468 } | 1515 } |
| 1469 topic = va_arg(vp, char *); | 1516 topic = va_arg(ap, char *); |
| 1470 usercount = va_arg(vp, int); | 1517 usercount = va_arg(ap, int); |
| 1471 | 1518 |
| 1472 room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, name, NULL); | 1519 room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, name, NULL); |
| 1473 purple_roomlist_room_add_field(sg->roomlist, room, name); | 1520 purple_roomlist_room_add_field(sg->roomlist, room, name); |
| 1474 purple_roomlist_room_add_field(sg->roomlist, room, | 1521 purple_roomlist_room_add_field(sg->roomlist, room, |
| 1475 SILC_32_TO_PTR(usercount)); | 1522 SILC_32_TO_PTR(usercount)); |
| 1476 purple_roomlist_room_add_field(sg->roomlist, room, | 1523 purple_roomlist_room_add_field(sg->roomlist, room, |
| 1477 topic ? topic : ""); | 1524 topic ? topic : ""); |
| 1478 purple_roomlist_room_add(sg->roomlist, room); | 1525 purple_roomlist_room_add(sg->roomlist, room); |
| 1479 | 1526 |
| 1480 if (status == SILC_STATUS_LIST_END || | 1527 if (status == SILC_STATUS_LIST_END || |
| 1481 status == SILC_STATUS_OK) { | 1528 status == SILC_STATUS_OK) { |
| 1482 purple_roomlist_set_in_progress(sg->roomlist, FALSE); | 1529 purple_roomlist_set_in_progress(sg->roomlist, FALSE); |
| 1488 | 1535 |
| 1489 case SILC_COMMAND_GETKEY: | 1536 case SILC_COMMAND_GETKEY: |
| 1490 { | 1537 { |
| 1491 SilcPublicKey public_key; | 1538 SilcPublicKey public_key; |
| 1492 | 1539 |
| 1493 if (!success) { | 1540 if (status != SILC_STATUS_OK) { |
| 1494 purple_notify_error(gc, _("Get Public Key"), | 1541 purple_notify_error(gc, _("Get Public Key"), |
| 1495 _("Cannot fetch the public key"), | 1542 _("Cannot fetch the public key"), |
| 1496 silc_get_status_message(status)); | 1543 silc_get_status_message(error)); |
| 1497 return; | 1544 return; |
| 1498 } | 1545 } |
| 1499 | 1546 |
| 1500 (void)va_arg(vp, SilcUInt32); | 1547 (void)va_arg(ap, SilcUInt32); |
| 1501 (void)va_arg(vp, void *); | 1548 (void)va_arg(ap, void *); |
| 1502 public_key = va_arg(vp, SilcPublicKey); | 1549 public_key = va_arg(ap, SilcPublicKey); |
| 1503 | 1550 |
| 1504 if (!public_key) | 1551 if (!public_key) |
| 1505 purple_notify_error(gc, _("Get Public Key"), | 1552 purple_notify_error(gc, _("Get Public Key"), |
| 1506 _("Cannot fetch the public key"), | 1553 _("Cannot fetch the public key"), |
| 1507 _("No public key was received")); | 1554 _("No public key was received")); |
| 1508 } | 1555 } |
| 1509 break; | 1556 break; |
| 1510 | 1557 |
| 1511 case SILC_COMMAND_INFO: | 1558 case SILC_COMMAND_INFO: |
| 1512 { | 1559 { |
| 1513 | 1560 |
| 1514 char *server_name; | 1561 char *server_name; |
| 1515 char *server_info; | 1562 char *server_info; |
| 1516 char tmp[256]; | 1563 char tmp[256]; |
| 1517 | 1564 |
| 1518 if (!success) { | 1565 if (status != SILC_STATUS_OK) { |
| 1519 purple_notify_error(gc, _("Server Information"), | 1566 purple_notify_error(gc, _("Server Information"), |
| 1520 _("Cannot get server information"), | 1567 _("Cannot get server information"), |
| 1521 silc_get_status_message(status)); | 1568 silc_get_status_message(error)); |
| 1522 return; | 1569 return; |
| 1523 } | 1570 } |
| 1524 | 1571 |
| 1525 (void)va_arg(vp, SilcServerEntry); | 1572 (void)va_arg(ap, SilcServerEntry); |
| 1526 server_name = va_arg(vp, char *); | 1573 server_name = va_arg(ap, char *); |
| 1527 server_info = va_arg(vp, char *); | 1574 server_info = va_arg(ap, char *); |
| 1528 | 1575 |
| 1529 if (server_name && server_info) { | 1576 if (server_name && server_info) { |
| 1530 g_snprintf(tmp, sizeof(tmp), "Server: %s\n%s", | 1577 g_snprintf(tmp, sizeof(tmp), "Server: %s\n%s", |
| 1531 server_name, server_info); | 1578 server_name, server_info); |
| 1532 purple_notify_info(gc, NULL, _("Server Information"), tmp); | 1579 purple_notify_info(gc, NULL, _("Server Information"), tmp); |
| 1534 } | 1581 } |
| 1535 break; | 1582 break; |
| 1536 | 1583 |
| 1537 case SILC_COMMAND_STATS: | 1584 case SILC_COMMAND_STATS: |
| 1538 { | 1585 { |
| 1539 SilcUInt32 starttime, uptime, my_clients, my_channels, my_server_ops, | 1586 SilcClientStats *stats; |
| 1540 my_router_ops, cell_clients, cell_channels, cell_servers, | |
| 1541 clients, channels, servers, routers, server_ops, router_ops; | |
| 1542 SilcUInt32 buffer_length; | |
| 1543 SilcBufferStruct buf; | |
| 1544 | |
| 1545 unsigned char *server_stats; | |
| 1546 char *msg; | 1587 char *msg; |
| 1547 | 1588 |
| 1548 if (!success) { | 1589 if (status != SILC_STATUS_OK) { |
| 1549 purple_notify_error(gc, _("Server Statistics"), | 1590 purple_notify_error(gc, _("Server Statistics"), |
| 1550 _("Cannot get server statistics"), | 1591 _("Cannot get server statistics"), |
| 1551 silc_get_status_message(status)); | 1592 silc_get_status_message(error)); |
| 1552 return; | 1593 return; |
| 1553 } | 1594 } |
| 1554 | 1595 |
| 1555 server_stats = va_arg(vp, unsigned char *); | 1596 stats = va_arg(ap, SilcClientStats *); |
| 1556 buffer_length = va_arg(vp, SilcUInt32); | |
| 1557 if (!server_stats || !buffer_length) { | |
| 1558 purple_notify_error(gc, _("Server Statistics"), | |
| 1559 _("No server statistics available"), NULL); | |
| 1560 break; | |
| 1561 } | |
| 1562 silc_buffer_set(&buf, server_stats, buffer_length); | |
| 1563 silc_buffer_unformat(&buf, | |
| 1564 SILC_STR_UI_INT(&starttime), | |
| 1565 SILC_STR_UI_INT(&uptime), | |
| 1566 SILC_STR_UI_INT(&my_clients), | |
| 1567 SILC_STR_UI_INT(&my_channels), | |
| 1568 SILC_STR_UI_INT(&my_server_ops), | |
| 1569 SILC_STR_UI_INT(&my_router_ops), | |
| 1570 SILC_STR_UI_INT(&cell_clients), | |
| 1571 SILC_STR_UI_INT(&cell_channels), | |
| 1572 SILC_STR_UI_INT(&cell_servers), | |
| 1573 SILC_STR_UI_INT(&clients), | |
| 1574 SILC_STR_UI_INT(&channels), | |
| 1575 SILC_STR_UI_INT(&servers), | |
| 1576 SILC_STR_UI_INT(&routers), | |
| 1577 SILC_STR_UI_INT(&server_ops), | |
| 1578 SILC_STR_UI_INT(&router_ops), | |
| 1579 SILC_STR_END); | |
| 1580 | 1597 |
| 1581 msg = g_strdup_printf(_("Local server start time: %s\n" | 1598 msg = g_strdup_printf(_("Local server start time: %s\n" |
| 1582 "Local server uptime: %s\n" | 1599 "Local server uptime: %s\n" |
| 1583 "Local server clients: %d\n" | 1600 "Local server clients: %d\n" |
| 1584 "Local server channels: %d\n" | 1601 "Local server channels: %d\n" |
| 1585 "Local server operators: %d\n" | 1602 "Local server operators: %d\n" |
| 1586 "Local router operators: %d\n" | 1603 "Local router operators: %d\n" |
| 1587 "Local cell clients: %d\n" | 1604 "Local cell clients: %d\n" |
| 1588 "Local cell channels: %d\n" | 1605 "Local cell channels: %d\n" |
| 1589 "Local cell servers: %d\n" | 1606 "Local cell servers: %d\n" |
| 1590 "Total clients: %d\n" | 1607 "Total clients: %d\n" |
| 1591 "Total channels: %d\n" | 1608 "Total channels: %d\n" |
| 1592 "Total servers: %d\n" | 1609 "Total servers: %d\n" |
| 1593 "Total routers: %d\n" | 1610 "Total routers: %d\n" |
| 1594 "Total server operators: %d\n" | 1611 "Total server operators: %d\n" |
| 1595 "Total router operators: %d\n"), | 1612 "Total router operators: %d\n"), |
| 1596 silc_get_time(starttime), | 1613 silc_time_string(stats->starttime), |
| 1597 purple_str_seconds_to_string((int)uptime), | 1614 purple_str_seconds_to_string((int)stats->uptime), |
| 1598 (int)my_clients, (int)my_channels, (int)my_server_ops, (int)my_router_ops, | 1615 (int)stats->my_clients, |
| 1599 (int)cell_clients, (int)cell_channels, (int)cell_servers, | 1616 (int)stats->my_channels, |
| 1600 (int)clients, (int)channels, (int)servers, (int)routers, | 1617 (int)stats->my_server_ops, |
| 1601 (int)server_ops, (int)router_ops); | 1618 (int)stats->my_router_ops, |
| 1619 (int)stats->cell_clients, | |
| 1620 (int)stats->cell_channels, | |
| 1621 (int)stats->cell_servers, | |
| 1622 (int)stats->clients, | |
| 1623 (int)stats->channels, | |
| 1624 (int)stats->servers, | |
| 1625 (int)stats->routers, | |
| 1626 (int)stats->server_ops, | |
| 1627 (int)stats->router_ops); | |
| 1602 | 1628 |
| 1603 purple_notify_info(gc, NULL, | 1629 purple_notify_info(gc, NULL, |
| 1604 _("Network Statistics"), msg); | 1630 _("Network Statistics"), msg); |
| 1605 g_free(msg); | 1631 g_free(msg); |
| 1606 } | 1632 } |
| 1607 break; | 1633 break; |
| 1608 | 1634 |
| 1609 case SILC_COMMAND_PING: | 1635 case SILC_COMMAND_PING: |
| 1610 { | 1636 { |
| 1611 if (!success) { | 1637 if (status != SILC_STATUS_OK) { |
| 1612 purple_notify_error(gc, _("Ping"), _("Ping failed"), | 1638 purple_notify_error(gc, _("Ping"), _("Ping failed"), |
| 1613 silc_get_status_message(status)); | 1639 silc_get_status_message(error)); |
| 1614 return; | 1640 return; |
| 1615 } | 1641 } |
| 1616 | 1642 |
| 1617 purple_notify_info(gc, _("Ping"), _("Ping reply received from server"), | 1643 purple_notify_info(gc, _("Ping"), _("Ping reply received from server"), |
| 1618 NULL); | 1644 NULL); |
| 1619 } | 1645 } |
| 1620 break; | 1646 break; |
| 1621 | 1647 |
| 1622 case SILC_COMMAND_KILL: | 1648 case SILC_COMMAND_KILL: |
| 1623 if (!success) { | 1649 if (status != SILC_STATUS_OK) { |
| 1624 purple_notify_error(gc, _("Kill User"), | 1650 purple_notify_error(gc, _("Kill User"), |
| 1625 _("Could not kill user"), | 1651 _("Could not kill user"), |
| 1626 silc_get_status_message(status)); | 1652 silc_get_status_message(error)); |
| 1627 return; | 1653 return; |
| 1628 } | 1654 } |
| 1629 break; | 1655 break; |
| 1630 | 1656 |
| 1631 case SILC_COMMAND_CMODE: | 1657 case SILC_COMMAND_CMODE: |
| 1632 { | 1658 { |
| 1633 SilcChannelEntry channel_entry; | 1659 SilcChannelEntry channel_entry; |
| 1634 SilcBuffer channel_pubkeys; | 1660 SilcDList channel_pubkeys, list; |
| 1635 | 1661 SilcArgumentDecodedList e; |
| 1636 if (!success) | 1662 |
| 1663 if (status != SILC_STATUS_OK) | |
| 1637 return; | 1664 return; |
| 1638 | 1665 |
| 1639 channel_entry = va_arg(vp, SilcChannelEntry); | 1666 channel_entry = va_arg(ap, SilcChannelEntry); |
| 1640 (void)va_arg(vp, SilcUInt32); | 1667 (void)va_arg(ap, SilcUInt32); |
| 1641 (void)va_arg(vp, SilcPublicKey); | 1668 (void)va_arg(ap, SilcPublicKey); |
| 1642 channel_pubkeys = va_arg(vp, SilcBuffer); | 1669 channel_pubkeys = va_arg(ap, SilcDList); |
| 1643 | 1670 |
| 1644 if (sg->chpk) | 1671 if (!sg->chpk) |
| 1645 silcpurple_chat_chauth_show(sg, channel_entry, channel_pubkeys); | 1672 break; |
| 1673 | |
| 1674 list = silc_dlist_init(); | |
| 1675 | |
| 1676 if (channel_pubkeys) { | |
| 1677 silc_dlist_start(channel_pubkeys); | |
| 1678 while ((e = silc_dlist_get(channel_pubkeys))) { | |
| 1679 if (e->arg_type == 0x00 || | |
| 1680 e->arg_type == 0x03) | |
| 1681 silc_dlist_add(list, silc_pkcs_public_key_copy(e->argument)); | |
| 1682 } | |
| 1683 } | |
| 1684 silcpurple_chat_chauth_show(sg, channel_entry, list); | |
| 1685 } | |
| 1686 break; | |
| 1687 | |
| 1688 case SILC_COMMAND_WATCH: | |
| 1689 if (status != SILC_STATUS_OK) { | |
| 1690 purple_notify_error(gc, _("WATCH"), _("Cannot watch user"), | |
| 1691 silc_get_status_message(error)); | |
| 1692 return; | |
| 1646 } | 1693 } |
| 1647 break; | 1694 break; |
| 1648 | 1695 |
| 1649 default: | 1696 default: |
| 1650 if (success) | 1697 if (status == SILC_STATUS_OK) |
| 1651 purple_debug_info("silc", "Unhandled command: %d (succeeded)\n", command); | 1698 purple_debug_info("silc", "Unhandled command: %d (succeeded)\n", command); |
| 1652 else | 1699 else |
| 1653 purple_debug_info("silc", "Unhandled command: %d (failed: %s)\n", command, | 1700 purple_debug_info("silc", "Unhandled command: %d (failed: %s)\n", command, |
| 1654 silc_get_status_message(status)); | 1701 silc_get_status_message(error)); |
| 1655 break; | 1702 break; |
| 1656 } | 1703 } |
| 1657 | |
| 1658 va_end(vp); | |
| 1659 } | 1704 } |
| 1660 | 1705 |
| 1661 | 1706 /* Generic command reply callback for silc_client_command_send. Simply |
| 1662 /* Called to indicate that connection was either successfully established | 1707 calls the default command_reply client operation callback */ |
| 1663 or connecting failed. This is also the first time application receives | 1708 |
| 1664 the SilcClientConnection object which it should save somewhere. | 1709 SilcBool silcpurple_command_reply(SilcClient client, SilcClientConnection conn, |
| 1665 If the `success' is FALSE the application must always call the function | 1710 SilcCommand command, SilcStatus status, |
| 1666 silc_client_close_connection. */ | 1711 SilcStatus error, void *context, va_list ap) |
| 1712 { | |
| 1713 silc_command_reply(client, conn, command, status, error, ap); | |
| 1714 return TRUE; | |
| 1715 } | |
| 1716 | |
| 1717 | |
| 1718 typedef struct { | |
| 1719 union { | |
| 1720 SilcAskPassphrase ask_pass; | |
| 1721 SilcGetAuthMeth get_auth; | |
| 1722 } u; | |
| 1723 void *context; | |
| 1724 } *SilcPurpleAskPassphrase; | |
| 1667 | 1725 |
| 1668 static void | 1726 static void |
| 1669 silc_connected(SilcClient client, SilcClientConnection conn, | 1727 silc_ask_auth_password_cb(const unsigned char *passphrase, |
| 1670 SilcClientConnectionStatus status) | 1728 SilcUInt32 passphrase_len, void *context) |
| 1671 { | 1729 { |
| 1672 PurpleConnection *gc = client->application; | 1730 SilcPurpleAskPassphrase internal = context; |
| 1673 SilcPurple sg; | 1731 |
| 1674 gboolean reject_watch, block_invites, block_ims; | 1732 if (!passphrase || !(*passphrase)) |
| 1675 | 1733 internal->u.get_auth(SILC_AUTH_NONE, NULL, 0, internal->context); |
| 1676 if (gc == NULL) { | |
| 1677 silc_client_close_connection(client, conn); | |
| 1678 return; | |
| 1679 } | |
| 1680 sg = gc->proto_data; | |
| 1681 | |
| 1682 switch (status) { | |
| 1683 case SILC_CLIENT_CONN_SUCCESS: | |
| 1684 case SILC_CLIENT_CONN_SUCCESS_RESUME: | |
| 1685 purple_connection_set_state(gc, PURPLE_CONNECTED); | |
| 1686 | |
| 1687 /* Send the server our buddy list */ | |
| 1688 silcpurple_send_buddylist(gc); | |
| 1689 | |
| 1690 g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); | |
| 1691 | |
| 1692 /* Send any UMODEs configured for account */ | |
| 1693 reject_watch = purple_account_get_bool(sg->account, "reject-watch", FALSE); | |
| 1694 block_invites = purple_account_get_bool(sg->account, "block-invites", FALSE); | |
| 1695 block_ims = purple_account_get_bool(sg->account, "block-ims", FALSE); | |
| 1696 if (reject_watch || block_invites || block_ims) { | |
| 1697 char m[5]; | |
| 1698 g_snprintf(m, sizeof(m), "+%s%s%s", | |
| 1699 reject_watch ? "w" : "", | |
| 1700 block_invites ? "I" : "", | |
| 1701 block_ims ? "P" : ""); | |
| 1702 silc_client_command_call(sg->client, sg->conn, NULL, | |
| 1703 "UMODE", m, NULL); | |
| 1704 } | |
| 1705 | |
| 1706 return; | |
| 1707 break; | |
| 1708 case SILC_CLIENT_CONN_ERROR: | |
| 1709 purple_connection_error(gc, _("Error during connecting to SILC Server")); | |
| 1710 g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); | |
| 1711 break; | |
| 1712 | |
| 1713 case SILC_CLIENT_CONN_ERROR_KE: | |
| 1714 purple_connection_error(gc, _("Key Exchange failed")); | |
| 1715 break; | |
| 1716 | |
| 1717 case SILC_CLIENT_CONN_ERROR_AUTH: | |
| 1718 purple_connection_error(gc, _("Authentication failed")); | |
| 1719 break; | |
| 1720 | |
| 1721 case SILC_CLIENT_CONN_ERROR_RESUME: | |
| 1722 purple_connection_error(gc, | |
| 1723 _("Resuming detached session failed. " | |
| 1724 "Press Reconnect to create new connection.")); | |
| 1725 g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); | |
| 1726 break; | |
| 1727 | |
| 1728 case SILC_CLIENT_CONN_ERROR_TIMEOUT: | |
| 1729 purple_connection_error(gc, _("Connection Timeout")); | |
| 1730 break; | |
| 1731 } | |
| 1732 | |
| 1733 /* Error */ | |
| 1734 sg->conn = NULL; | |
| 1735 silc_client_close_connection(client, conn); | |
| 1736 } | |
| 1737 | |
| 1738 | |
| 1739 /* Called to indicate that connection was disconnected to the server. | |
| 1740 The `status' may tell the reason of the disconnection, and if the | |
| 1741 `message' is non-NULL it may include the disconnection message | |
| 1742 received from server. */ | |
| 1743 | |
| 1744 static void | |
| 1745 silc_disconnected(SilcClient client, SilcClientConnection conn, | |
| 1746 SilcStatus status, const char *message) | |
| 1747 { | |
| 1748 PurpleConnection *gc = client->application; | |
| 1749 SilcPurple sg = gc->proto_data; | |
| 1750 | |
| 1751 if (sg->resuming && !sg->detaching) | |
| 1752 g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); | |
| 1753 | |
| 1754 sg->conn = NULL; | |
| 1755 | |
| 1756 /* Close the connection */ | |
| 1757 if (!sg->detaching) | |
| 1758 purple_connection_error(gc, _("Disconnected by server")); | |
| 1759 else | 1734 else |
| 1760 /* TODO: Does this work correctly? Maybe we need to set wants_to_die? */ | 1735 internal->u.get_auth(SILC_AUTH_PASSWORD, |
| 1761 purple_account_disconnect(purple_connection_get_account(gc)); | 1736 (unsigned char *)passphrase, |
| 1762 } | 1737 passphrase_len, internal->context); |
| 1763 | |
| 1764 | |
| 1765 typedef struct { | |
| 1766 SilcGetAuthMeth completion; | |
| 1767 void *context; | |
| 1768 } *SilcPurpleGetAuthMethod; | |
| 1769 | |
| 1770 /* Callback called when we've received the authentication method information | |
| 1771 from the server after we've requested it. */ | |
| 1772 | |
| 1773 static void silc_get_auth_method_callback(SilcClient client, | |
| 1774 SilcClientConnection conn, | |
| 1775 SilcAuthMethod auth_meth, | |
| 1776 void *context) | |
| 1777 { | |
| 1778 SilcPurpleGetAuthMethod internal = context; | |
| 1779 | |
| 1780 switch (auth_meth) { | |
| 1781 case SILC_AUTH_NONE: | |
| 1782 /* No authentication required. */ | |
| 1783 (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); | |
| 1784 break; | |
| 1785 | |
| 1786 case SILC_AUTH_PASSWORD: | |
| 1787 /* By returning NULL here the library will ask the passphrase from us | |
| 1788 by calling the silc_ask_passphrase. */ | |
| 1789 (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); | |
| 1790 break; | |
| 1791 | |
| 1792 case SILC_AUTH_PUBLIC_KEY: | |
| 1793 /* Do not get the authentication data now, the library will generate | |
| 1794 it using our default key, if we do not provide it here. */ | |
| 1795 (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); | |
| 1796 break; | |
| 1797 } | |
| 1798 | |
| 1799 silc_free(internal); | 1738 silc_free(internal); |
| 1800 } | 1739 } |
| 1801 | 1740 |
| 1802 /* Find authentication method and authentication data by hostname and | 1741 /* Find authentication method and authentication data by hostname and |
| 1803 port. The hostname may be IP address as well. When the authentication | 1742 port. The hostname may be IP address as well. The `auth_method' is |
| 1804 method has been resolved the `completion' callback with the found | 1743 the authentication method the remote connection requires. It is |
| 1805 authentication method and authentication data is called. The `conn' | 1744 however possible that remote accepts also some other authentication |
| 1806 may be NULL. */ | 1745 method. Application should use the method that may have been |
| 1746 configured for this connection. If none has been configured it should | |
| 1747 use the required `auth_method'. If the `auth_method' is | |
| 1748 SILC_AUTH_NONE, server does not require any authentication or the | |
| 1749 required authentication method is not known. The `completion' | |
| 1750 callback must be called to deliver the chosen authentication method | |
| 1751 and data. The `conn' may be NULL. */ | |
| 1807 | 1752 |
| 1808 static void | 1753 static void |
| 1809 silc_get_auth_method(SilcClient client, SilcClientConnection conn, | 1754 silc_get_auth_method(SilcClient client, SilcClientConnection conn, |
| 1810 char *hostname, SilcUInt16 port, | 1755 char *hostname, SilcUInt16 port, |
| 1756 SilcAuthMethod auth_method, | |
| 1811 SilcGetAuthMeth completion, void *context) | 1757 SilcGetAuthMeth completion, void *context) |
| 1812 { | 1758 { |
| 1813 PurpleConnection *gc = client->application; | 1759 PurpleConnection *gc = client->application; |
| 1814 SilcPurple sg = gc->proto_data; | 1760 SilcPurple sg = gc->proto_data; |
| 1815 SilcPurpleGetAuthMethod internal; | 1761 SilcPurpleAskPassphrase internal; |
| 1816 const char *password; | 1762 const char *password; |
| 1817 | 1763 |
| 1818 /* Progress */ | 1764 /* Progress */ |
| 1819 if (sg->resuming) | 1765 if (sg->resuming) |
| 1820 purple_connection_update_progress(gc, _("Resuming session"), 4, 5); | 1766 purple_connection_update_progress(gc, _("Resuming session"), 4, 5); |
| 1821 else | 1767 else |
| 1822 purple_connection_update_progress(gc, _("Authenticating connection"), 4, 5); | 1768 purple_connection_update_progress(gc, _("Authenticating connection"), 4, 5); |
| 1823 | 1769 |
| 1824 /* Check configuration if we have this connection configured. If we | 1770 /* Check configuration if we have this connection configured. */ |
| 1825 have then return that data immediately, as it's faster way. */ | 1771 if (auth_method == SILC_AUTH_PUBLIC_KEY && |
| 1826 if (purple_account_get_bool(sg->account, "pubkey-auth", FALSE)) { | 1772 purple_account_get_bool(sg->account, "pubkey-auth", FALSE)) { |
| 1827 completion(TRUE, SILC_AUTH_PUBLIC_KEY, NULL, 0, context); | 1773 completion(SILC_AUTH_PUBLIC_KEY, NULL, 0, context); |
| 1828 return; | 1774 return; |
| 1829 } | 1775 } |
| 1830 password = purple_connection_get_password(gc); | 1776 if (auth_method == SILC_AUTH_PASSWORD) { |
| 1831 if (password && *password) { | 1777 password = purple_connection_get_password(gc); |
| 1832 completion(TRUE, SILC_AUTH_PASSWORD, (unsigned char *)password, strlen(password), context); | 1778 if (password && *password) { |
| 1779 completion(SILC_AUTH_PASSWORD, (unsigned char *)password, strlen(password), context); | |
| 1780 return; | |
| 1781 } | |
| 1782 | |
| 1783 /* Ask password from user */ | |
| 1784 internal = silc_calloc(1, sizeof(*internal)); | |
| 1785 if (!internal) | |
| 1786 return; | |
| 1787 internal->u.get_auth = completion; | |
| 1788 internal->context = context; | |
| 1789 silc_ask_passphrase(client, conn, silc_ask_auth_password_cb, | |
| 1790 internal); | |
| 1833 return; | 1791 return; |
| 1834 } | 1792 } |
| 1835 | 1793 |
| 1836 /* Resolve the authentication method from server, as we may not know it. */ | 1794 completion(SILC_AUTH_NONE, NULL, 0, context); |
| 1837 internal = silc_calloc(1, sizeof(*internal)); | |
| 1838 if (!internal) | |
| 1839 return; | |
| 1840 internal->completion = completion; | |
| 1841 internal->context = context; | |
| 1842 silc_client_request_authentication_method(client, conn, | |
| 1843 silc_get_auth_method_callback, | |
| 1844 internal); | |
| 1845 } | 1795 } |
| 1846 | 1796 |
| 1847 | 1797 |
| 1848 /* Verifies received public key. The `conn_type' indicates which entity | 1798 /* Called to verify received public key. The `conn_type' indicates which |
| 1849 (server, client etc.) has sent the public key. If user decides to trust | 1799 entity (server or client) has sent the public key. If user decides to |
| 1850 the application may save the key as trusted public key for later | 1800 trust the key the application may save the key as trusted public key for |
| 1851 use. The `completion' must be called after the public key has been | 1801 later use. The `completion' must be called after the public key has |
| 1852 verified. */ | 1802 been verified. */ |
| 1853 | 1803 |
| 1854 static void | 1804 static void |
| 1855 silc_verify_public_key(SilcClient client, SilcClientConnection conn, | 1805 silc_verify_public_key(SilcClient client, SilcClientConnection conn, |
| 1856 SilcSocketType conn_type, unsigned char *pk, | 1806 SilcConnectionType conn_type, |
| 1857 SilcUInt32 pk_len, SilcSKEPKType pk_type, | 1807 SilcPublicKey public_key, |
| 1858 SilcVerifyPublicKey completion, void *context) | 1808 SilcVerifyPublicKey completion, void *context) |
| 1859 { | 1809 { |
| 1860 PurpleConnection *gc = client->application; | 1810 PurpleConnection *gc = client->application; |
| 1861 SilcPurple sg = gc->proto_data; | 1811 SilcPurple sg = gc->proto_data; |
| 1862 | 1812 |
| 1863 if (!sg->conn && (conn_type == SILC_SOCKET_TYPE_SERVER || | 1813 if (!sg->conn && (conn_type == SILC_CONN_SERVER || |
| 1864 conn_type == SILC_SOCKET_TYPE_ROUTER)) { | 1814 conn_type == SILC_CONN_ROUTER)) { |
| 1865 /* Progress */ | 1815 /* Progress */ |
| 1866 if (sg->resuming) | 1816 if (sg->resuming) |
| 1867 purple_connection_update_progress(gc, _("Resuming session"), 3, 5); | 1817 purple_connection_update_progress(gc, _("Resuming session"), 3, 5); |
| 1868 else | 1818 else |
| 1869 purple_connection_update_progress(gc, _("Verifying server public key"), | 1819 purple_connection_update_progress(gc, _("Verifying server public key"), |
| 1870 3, 5); | 1820 3, 5); |
| 1871 } | 1821 } |
| 1872 | 1822 |
| 1873 /* Verify public key */ | 1823 /* Verify public key */ |
| 1874 silcpurple_verify_public_key(client, conn, NULL, conn_type, pk, | 1824 silcpurple_verify_public_key(client, conn, NULL, conn_type, |
| 1875 pk_len, pk_type, completion, context); | 1825 public_key, completion, context); |
| 1876 } | 1826 } |
| 1877 | |
| 1878 typedef struct { | |
| 1879 SilcAskPassphrase completion; | |
| 1880 void *context; | |
| 1881 } *SilcPurpleAskPassphrase; | |
| 1882 | 1827 |
| 1883 static void | 1828 static void |
| 1884 silc_ask_passphrase_cb(SilcPurpleAskPassphrase internal, const char *passphrase) | 1829 silc_ask_passphrase_cb(SilcPurpleAskPassphrase internal, const char *passphrase) |
| 1885 { | 1830 { |
| 1886 if (!passphrase || !(*passphrase)) | 1831 if (!passphrase || !(*passphrase)) |
| 1887 internal->completion(NULL, 0, internal->context); | 1832 internal->u.ask_pass(NULL, 0, internal->context); |
| 1888 else | 1833 else |
| 1889 internal->completion((unsigned char *)passphrase, | 1834 internal->u.ask_pass((unsigned char *)passphrase, |
| 1890 strlen(passphrase), internal->context); | 1835 strlen(passphrase), internal->context); |
| 1891 silc_free(internal); | 1836 silc_free(internal); |
| 1892 } | 1837 } |
| 1893 | 1838 |
| 1894 /* Ask (interact, that is) a passphrase from user. The passphrase is | 1839 /* Ask (interact, that is) a passphrase from user. The passphrase is |
| 1903 PurpleConnection *gc = client->application; | 1848 PurpleConnection *gc = client->application; |
| 1904 SilcPurpleAskPassphrase internal = silc_calloc(1, sizeof(*internal)); | 1849 SilcPurpleAskPassphrase internal = silc_calloc(1, sizeof(*internal)); |
| 1905 | 1850 |
| 1906 if (!internal) | 1851 if (!internal) |
| 1907 return; | 1852 return; |
| 1908 internal->completion = completion; | 1853 internal->u.ask_pass = completion; |
| 1909 internal->context = context; | 1854 internal->context = context; |
| 1910 purple_request_input(gc, _("Passphrase"), NULL, | 1855 purple_request_input(gc, _("Passphrase"), NULL, |
| 1911 _("Passphrase required"), NULL, FALSE, TRUE, NULL, | 1856 _("Passphrase required"), NULL, FALSE, TRUE, NULL, |
| 1912 _("OK"), G_CALLBACK(silc_ask_passphrase_cb), | 1857 _("OK"), G_CALLBACK(silc_ask_passphrase_cb), |
| 1913 _("Cancel"), G_CALLBACK(silc_ask_passphrase_cb), | 1858 _("Cancel"), G_CALLBACK(silc_ask_passphrase_cb), |
| 1914 purple_connection_get_account(gc), NULL, NULL, internal); | 1859 purple_connection_get_account(gc), NULL, NULL, internal); |
| 1915 } | 1860 } |
| 1916 | 1861 |
| 1917 | 1862 |
| 1918 /* Notifies application that failure packet was received. This is called | 1863 /* Called to indicate that incoming key agreement request has been |
| 1919 if there is some protocol active in the client. The `protocol' is the | 1864 received. If the application wants to perform key agreement it may |
| 1920 protocol context. The `failure' is opaque pointer to the failure | 1865 call silc_client_perform_key_agreement to initiate key agreement or |
| 1921 indication. Note, that the `failure' is protocol dependant and | 1866 silc_client_send_key_agreement to provide connection point to the |
| 1922 application must explicitly cast it to correct type. Usually `failure' | 1867 remote client in case the `hostname' is NULL. If key agreement is |
| 1923 is 32 bit failure type (see protocol specs for all protocol failure | 1868 not desired this request can be ignored. The `protocol' is either |
| 1924 types). */ | 1869 value 0 for TCP or value 1 for UDP. */ |
| 1925 | 1870 |
| 1926 static void | 1871 static void |
| 1927 silc_failure(SilcClient client, SilcClientConnection conn, | 1872 silc_key_agreement(SilcClient client, SilcClientConnection conn, |
| 1928 SilcProtocol protocol, void *failure) | 1873 SilcClientEntry client_entry, |
| 1874 const char *hostname, SilcUInt16 protocol, | |
| 1875 SilcUInt16 port) | |
| 1929 { | 1876 { |
| 1930 PurpleConnection *gc = client->application; | 1877 silcpurple_buddy_keyagr_request(client, conn, client_entry, |
| 1931 char buf[128]; | 1878 hostname, port, protocol); |
| 1932 | |
| 1933 memset(buf, 0, sizeof(buf)); | |
| 1934 | |
| 1935 if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) { | |
| 1936 SilcSKEStatus status = (SilcSKEStatus)SILC_PTR_TO_32(failure); | |
| 1937 | |
| 1938 if (status == SILC_SKE_STATUS_BAD_VERSION) | |
| 1939 g_snprintf(buf, sizeof(buf), | |
| 1940 _("Failure: Version mismatch, upgrade your client")); | |
| 1941 if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) | |
| 1942 g_snprintf(buf, sizeof(buf), | |
| 1943 _("Failure: Remote does not trust/support your public key")); | |
| 1944 if (status == SILC_SKE_STATUS_UNKNOWN_GROUP) | |
| 1945 g_snprintf(buf, sizeof(buf), | |
| 1946 _("Failure: Remote does not support proposed KE group")); | |
| 1947 if (status == SILC_SKE_STATUS_UNKNOWN_CIPHER) | |
| 1948 g_snprintf(buf, sizeof(buf), | |
| 1949 _("Failure: Remote does not support proposed cipher")); | |
| 1950 if (status == SILC_SKE_STATUS_UNKNOWN_PKCS) | |
| 1951 g_snprintf(buf, sizeof(buf), | |
| 1952 _("Failure: Remote does not support proposed PKCS")); | |
| 1953 if (status == SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION) | |
| 1954 g_snprintf(buf, sizeof(buf), | |
| 1955 _("Failure: Remote does not support proposed hash function")); | |
| 1956 if (status == SILC_SKE_STATUS_UNKNOWN_HMAC) | |
| 1957 g_snprintf(buf, sizeof(buf), | |
| 1958 _("Failure: Remote does not support proposed HMAC")); | |
| 1959 if (status == SILC_SKE_STATUS_INCORRECT_SIGNATURE) | |
| 1960 g_snprintf(buf, sizeof(buf), _("Failure: Incorrect signature")); | |
| 1961 if (status == SILC_SKE_STATUS_INVALID_COOKIE) | |
| 1962 g_snprintf(buf, sizeof(buf), _("Failure: Invalid cookie")); | |
| 1963 | |
| 1964 /* Show the error on the progress bar. A more generic error message | |
| 1965 is going to be showed to user after this in the silc_connected. */ | |
| 1966 purple_connection_update_progress(gc, buf, 2, 5); | |
| 1967 } | |
| 1968 | |
| 1969 if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) { | |
| 1970 SilcUInt32 err = SILC_PTR_TO_32(failure); | |
| 1971 | |
| 1972 if (err == SILC_AUTH_FAILED) | |
| 1973 g_snprintf(buf, sizeof(buf), _("Failure: Authentication failed")); | |
| 1974 | |
| 1975 /* Show the error on the progress bar. A more generic error message | |
| 1976 is going to be showed to user after this in the silc_connected. */ | |
| 1977 purple_connection_update_progress(gc, buf, 4, 5); | |
| 1978 } | |
| 1979 } | |
| 1980 | |
| 1981 /* Asks whether the user would like to perform the key agreement protocol. | |
| 1982 This is called after we have received an key agreement packet or an | |
| 1983 reply to our key agreement packet. This returns TRUE if the user wants | |
| 1984 the library to perform the key agreement protocol and FALSE if it is not | |
| 1985 desired (application may start it later by calling the function | |
| 1986 silc_client_perform_key_agreement). If TRUE is returned also the | |
| 1987 `completion' and `context' arguments must be set by the application. */ | |
| 1988 | |
| 1989 static bool | |
| 1990 silc_key_agreement(SilcClient client, SilcClientConnection conn, | |
| 1991 SilcClientEntry client_entry, const char *hostname, | |
| 1992 SilcUInt16 port, SilcKeyAgreementCallback *completion, | |
| 1993 void **context) | |
| 1994 { | |
| 1995 silcpurple_buddy_keyagr_request(client, conn, client_entry, hostname, port); | |
| 1996 *completion = NULL; | |
| 1997 *context = NULL; | |
| 1998 return FALSE; | |
| 1999 } | 1879 } |
| 2000 | 1880 |
| 2001 | 1881 |
| 2002 /* Notifies application that file transfer protocol session is being | 1882 /* Notifies application that file transfer protocol session is being |
| 2003 requested by the remote client indicated by the `client_entry' from | 1883 requested by the remote client indicated by the `client_entry' from |
| 2010 silc_ftp(SilcClient client, SilcClientConnection conn, | 1890 silc_ftp(SilcClient client, SilcClientConnection conn, |
| 2011 SilcClientEntry client_entry, SilcUInt32 session_id, | 1891 SilcClientEntry client_entry, SilcUInt32 session_id, |
| 2012 const char *hostname, SilcUInt16 port) | 1892 const char *hostname, SilcUInt16 port) |
| 2013 { | 1893 { |
| 2014 silcpurple_ftp_request(client, conn, client_entry, session_id, | 1894 silcpurple_ftp_request(client, conn, client_entry, session_id, |
| 2015 hostname, port); | 1895 hostname, port); |
| 2016 } | |
| 2017 | |
| 2018 | |
| 2019 /* Delivers SILC session detachment data indicated by `detach_data' to the | |
| 2020 application. If application has issued SILC_COMMAND_DETACH command | |
| 2021 the client session in the SILC network is not quit. The client remains | |
| 2022 in the network but is detached. The detachment data may be used later | |
| 2023 to resume the session in the SILC Network. The appliation is | |
| 2024 responsible of saving the `detach_data', to for example in a file. | |
| 2025 | |
| 2026 The detachment data can be given as argument to the functions | |
| 2027 silc_client_connect_to_server, or silc_client_add_connection when | |
| 2028 creating connection to remote server, inside SilcClientConnectionParams | |
| 2029 structure. If it is provided the client library will attempt to resume | |
| 2030 the session in the network. After the connection is created | |
| 2031 successfully, the application is responsible of setting the user | |
| 2032 interface for user into the same state it was before detaching (showing | |
| 2033 same channels, channel modes, etc). It can do this by fetching the | |
| 2034 information (like joined channels) from the client library. */ | |
| 2035 | |
| 2036 static void | |
| 2037 silc_detach(SilcClient client, SilcClientConnection conn, | |
| 2038 const unsigned char *detach_data, SilcUInt32 detach_data_len) | |
| 2039 { | |
| 2040 PurpleConnection *gc = client->application; | |
| 2041 SilcPurple sg = gc->proto_data; | |
| 2042 const char *file; | |
| 2043 | |
| 2044 /* Save the detachment data to file. */ | |
| 2045 file = silcpurple_session_file(purple_account_get_username(sg->account)); | |
| 2046 g_unlink(file); | |
| 2047 silc_file_writefile(file, (char *)detach_data, detach_data_len); | |
| 2048 } | 1896 } |
| 2049 | 1897 |
| 2050 SilcClientOperations ops = { | 1898 SilcClientOperations ops = { |
| 2051 silc_say, | 1899 silc_say, |
| 2052 silc_channel_message, | 1900 silc_channel_message, |
| 2053 silc_private_message, | 1901 silc_private_message, |
| 2054 silc_notify, | 1902 silc_notify, |
| 2055 silc_command, | 1903 silc_command, |
| 2056 silc_command_reply, | 1904 silc_command_reply, |
| 2057 silc_connected, | |
| 2058 silc_disconnected, | |
| 2059 silc_get_auth_method, | 1905 silc_get_auth_method, |
| 2060 silc_verify_public_key, | 1906 silc_verify_public_key, |
| 2061 silc_ask_passphrase, | 1907 silc_ask_passphrase, |
| 2062 silc_failure, | |
| 2063 silc_key_agreement, | 1908 silc_key_agreement, |
| 2064 silc_ftp, | 1909 silc_ftp |
| 2065 silc_detach | |
| 2066 }; | 1910 }; |