📄 ops.c
字号:
/* silcpurple_ops.c Author: Pekka Riikonen <priikone@silcnet.org> Copyright (C) 2004 - 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.*/#include "silc.h"#include "silcclient.h"#include "silcpurple.h"#include "imgstore.h"#include "wb.h"static voidsilc_channel_message(SilcClient client, SilcClientConnection conn, SilcClientEntry sender, SilcChannelEntry channel, SilcMessagePayload payload, SilcChannelPrivateKey key, SilcMessageFlags flags, const unsigned char *message, SilcUInt32 message_len);static voidsilc_private_message(SilcClient client, SilcClientConnection conn, SilcClientEntry sender, SilcMessagePayload payload, SilcMessageFlags flags, const unsigned char *message, SilcUInt32 message_len);static voidsilc_ask_passphrase(SilcClient client, SilcClientConnection conn, SilcAskPassphrase completion, void *context);/* Message sent to the application by library. `conn' associates the message to a specific connection. `conn', however, may be NULL. The `type' indicates the type of the message sent by the library. The application can for example filter the message according the type. */void silc_say(SilcClient client, SilcClientConnection conn, SilcClientMessageType type, char *msg, ...){ if (type == SILC_CLIENT_MESSAGE_ERROR) { char tmp[256]; va_list va; va_start(va, msg); silc_vsnprintf(tmp, sizeof(tmp), msg, va); purple_notify_error(NULL, _("Error"), _("Error occurred"), tmp); va_end(va); return; }}/* Processes incoming MIME message. Can be private message or channel message. Returns TRUE if the message `mime' was displayed. */static SilcBoolsilcpurple_mime_message(SilcClient client, SilcClientConnection conn, SilcClientEntry sender, SilcChannelEntry channel, SilcMessagePayload payload, SilcChannelPrivateKey key, SilcMessageFlags flags, SilcMime mime, gboolean recursive){ PurpleConnection *gc = client->application; SilcPurple sg = gc->proto_data; const char *type; const unsigned char *data; SilcUInt32 data_len; PurpleMessageFlags cflags = 0; PurpleConversation *convo = NULL; SilcBool ret = FALSE; if (!mime) return FALSE; /* Check for fragmented MIME message */ if (silc_mime_is_partial(mime)) { if (!sg->mimeass) sg->mimeass = silc_mime_assembler_alloc(); /* Defragment */ mime = silc_mime_assemble(sg->mimeass, mime); if (!mime) /* More fragments to come */ return FALSE; /* Process the complete message */ return silcpurple_mime_message(client, conn, sender, channel, payload, key, flags, mime, FALSE); } /* Check for multipart message */ if (silc_mime_is_multipart(mime)) { SilcMime p; const char *mtype; SilcDList parts = silc_mime_get_multiparts(mime, &mtype); SilcBool ret; if (!strcmp(mtype, "mixed")) { /* Contains multiple messages */ silc_dlist_start(parts); while ((p = silc_dlist_get(parts)) != SILC_LIST_END) { /* Recursively process parts */ ret = silcpurple_mime_message(client, conn, sender, channel, payload, key, flags, p, TRUE); } } if (!strcmp(mtype, "alternative")) { /* Same message in alternative formats. Kopete sends these. Go in order from last to first. */ silc_dlist_end(parts); while ((p = silc_dlist_get(parts)) != SILC_LIST_END) { /* Go through the alternatives and display the first one we support. */ if (silcpurple_mime_message(client, conn, sender, channel, payload, key, flags, p, TRUE)) { ret = TRUE; break; } } } goto out; } /* Get content type and MIME data */ type = silc_mime_get_field(mime, "Content-Type"); if (!type) goto out; data = silc_mime_get_data(mime, &data_len); if (!data) goto out; /* Process according to content type */ /* Plain text */ if (strstr(type, "text/plain")) { /* Default is UTF-8, don't check for other charsets */ if (!strstr(type, "utf-8")) goto out; if (channel) silc_channel_message(client, conn, sender, channel, payload, key, SILC_MESSAGE_FLAG_UTF8, data, data_len); else silc_private_message(client, conn, sender, payload, SILC_MESSAGE_FLAG_UTF8, data, data_len); ret = TRUE; goto out; } /* Image */ if (strstr(type, "image/png") || strstr(type, "image/jpeg") || strstr(type, "image/gif") || strstr(type, "image/tiff")) { char tmp[32]; int imgid; /* Get channel convo (if message is for channel) */ if (key && channel) { GList *l; SilcPurplePrvgrp prv; for (l = sg->grps; l; l = l->next) if (((SilcPurplePrvgrp)l->data)->key == key) { prv = l->data; convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, prv->channel, sg->account); break; } } if (channel && !convo) convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, channel->channel_name, sg->account); if (channel && !convo) goto out; imgid = purple_imgstore_add_with_id(g_memdup(data, data_len), data_len, ""); if (imgid) { cflags |= PURPLE_MESSAGE_IMAGES | PURPLE_MESSAGE_RECV; g_snprintf(tmp, sizeof(tmp), "<IMG ID=\"%d\">", imgid); if (channel) serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), sender->nickname ? sender->nickname : "<unknown>", cflags, tmp, time(NULL)); else serv_got_im(gc, sender->nickname ? sender->nickname : "<unknown>", tmp, cflags, time(NULL)); purple_imgstore_unref_by_id(imgid); cflags = 0; ret = TRUE; } goto out; } /* Whiteboard message */ if (strstr(type, "application/x-wb") && !purple_account_get_bool(sg->account, "block-wb", FALSE)) { if (channel) silcpurple_wb_receive_ch(client, conn, sender, channel, payload, flags, data, data_len); else silcpurple_wb_receive(client, conn, sender, payload, flags, data, data_len); ret = TRUE; goto out; } out: if (!recursive) silc_mime_free(mime); return ret;}/* Message for a channel. The `sender' is the sender of the message The `channel' is the channel. The `message' is the message. Note that `message' maybe NULL. The `flags' indicates message flags and it is used to determine how the message can be interpreted (like it may tell the message is multimedia message). */static voidsilc_channel_message(SilcClient client, SilcClientConnection conn, SilcClientEntry sender, SilcChannelEntry channel, SilcMessagePayload payload, SilcChannelPrivateKey key, SilcMessageFlags flags, const unsigned char *message, SilcUInt32 message_len){ PurpleConnection *gc = client->application; SilcPurple sg = gc->proto_data; PurpleConversation *convo = NULL; char *msg, *tmp; if (!message) return; if (key) { GList *l; SilcPurplePrvgrp prv; for (l = sg->grps; l; l = l->next) if (((SilcPurplePrvgrp)l->data)->key == key) { prv = l->data; convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, prv->channel, sg->account); break; } } if (!convo) convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, channel->channel_name, sg->account); if (!convo) return; if (flags & SILC_MESSAGE_FLAG_SIGNED && purple_account_get_bool(sg->account, "sign-verify", FALSE)) { /* XXX */ } if (flags & SILC_MESSAGE_FLAG_DATA) { /* Process MIME message */ SilcMime mime; mime = silc_mime_decode(NULL, message, message_len); silcpurple_mime_message(client, conn, sender, channel, payload, key, flags, mime, FALSE); return; } if (flags & SILC_MESSAGE_FLAG_ACTION) { msg = g_strdup_printf("/me %s", (const char *)message); if (!msg) return; tmp = g_markup_escape_text(msg, -1); /* Send to Purple */ serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), sender->nickname, 0, tmp, time(NULL)); g_free(tmp); g_free(msg); return; } if (flags & SILC_MESSAGE_FLAG_NOTICE) { msg = g_strdup_printf("(notice) <I>%s</I> %s", sender->nickname, (const char *)message); if (!msg) return; /* Send to Purple */ purple_conversation_write(convo, NULL, (const char *)msg, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(msg); return; } if (flags & SILC_MESSAGE_FLAG_UTF8) { tmp = g_markup_escape_text((const char *)message, -1); /* Send to Purple */ serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), sender->nickname, 0, tmp, time(NULL)); g_free(tmp); }}/* Private message to the client. The `sender' is the sender of the message. The message is `message'and maybe NULL. The `flags' indicates message flags and it is used to determine how the message can be interpreted (like it may tell the message is multimedia message). */static voidsilc_private_message(SilcClient client, SilcClientConnection conn, SilcClientEntry sender, SilcMessagePayload payload, SilcMessageFlags flags, const unsigned char *message, SilcUInt32 message_len){ PurpleConnection *gc = client->application; SilcPurple sg = gc->proto_data; PurpleConversation *convo = NULL; char *msg, *tmp; if (!message) return; if (sender->nickname) /* XXX - Should this be PURPLE_CONV_TYPE_IM? */ convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, sender->nickname, sg->account); if (flags & SILC_MESSAGE_FLAG_SIGNED && purple_account_get_bool(sg->account, "sign-verify", FALSE)) { /* XXX */ } if (flags & SILC_MESSAGE_FLAG_DATA) { /* Process MIME message */ SilcMime mime; mime = silc_mime_decode(NULL, message, message_len); silcpurple_mime_message(client, conn, sender, NULL, payload, NULL, flags, mime, FALSE); return; } if (flags & SILC_MESSAGE_FLAG_ACTION && convo) { msg = g_strdup_printf("/me %s", (const char *)message); if (!msg) return; /* Send to Purple */ tmp = g_markup_escape_text(msg, -1); serv_got_im(gc, sender->nickname, tmp, 0, time(NULL)); g_free(msg); g_free(tmp); return; } if (flags & SILC_MESSAGE_FLAG_NOTICE && convo) { msg = g_strdup_printf("(notice) <I>%s</I> %s", sender->nickname, (const char *)message); if (!msg) return; /* Send to Purple */ purple_conversation_write(convo, NULL, (const char *)msg, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(msg); return; } if (flags & SILC_MESSAGE_FLAG_UTF8) { tmp = g_markup_escape_text((const char *)message, -1); /* Send to Purple */ serv_got_im(gc, sender->nickname, tmp, 0, time(NULL)); g_free(tmp); }}/* Notify message to the client. The notify arguments are sent in the same order as servers sends them. The arguments are same as received from the server except for ID's. If ID is received application receives the corresponding entry to the ID. For example, if Client ID is received application receives SilcClientEntry. Also, if the notify type is for channel the channel entry is sent to application (even if server does not send it because client library gets the channel entry from the Channel ID in the packet's header). */static voidsilc_notify(SilcClient client, SilcClientConnection conn, SilcNotifyType type, ...){ va_list va; PurpleConnection *gc = client->application; SilcPurple sg = gc->proto_data; PurpleConversation *convo; SilcClientEntry client_entry, client_entry2; SilcChannelEntry channel; SilcServerEntry server_entry; SilcIdType idtype; void *entry; SilcUInt32 mode; SilcHashTableList htl; SilcChannelUser chu; char buf[512], buf2[512], *tmp, *name; SilcNotifyType notify; PurpleBuddy *b; SilcDList list; int i; va_start(va, type); memset(buf, 0, sizeof(buf)); switch (type) { case SILC_NOTIFY_TYPE_NONE: break; case SILC_NOTIFY_TYPE_INVITE: { GHashTable *components; (void)va_arg(va, SilcChannelEntry); name = va_arg(va, char *); client_entry = va_arg(va, SilcClientEntry); components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); g_hash_table_insert(components, strdup("channel"), strdup(name)); serv_got_chat_invite(gc, name, client_entry->nickname, NULL, components); } break; case SILC_NOTIFY_TYPE_JOIN: client_entry = va_arg(va, SilcClientEntry); channel = va_arg(va, SilcChannelEntry); /* If we joined channel, do nothing */ if (client_entry == conn->local_entry) break; convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, channel->channel_name, sg->account); if (!convo) break; /* Join user to channel */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -