📄 buddy.c
字号:
silcpurple_buddy_privkey(PurpleConnection *gc, const char *name){ SilcPurple sg = gc->proto_data; char *nickname; SilcPurplePrivkey p; SilcClientEntry *clients; SilcUInt32 clients_count; if (!name) return; if (!silc_parse_userfqdn(name, &nickname, NULL)) return; /* Find client entry */ clients = silc_client_get_clients_local(sg->client, sg->conn, nickname, name, &clients_count); if (!clients) { silc_client_get_clients(sg->client, sg->conn, nickname, NULL, silcpurple_buddy_privkey_resolved, g_strdup(name)); silc_free(nickname); return; } p = silc_calloc(1, sizeof(*p)); if (!p) return; p->client = sg->client; p->conn = sg->conn; p->client_id = *clients[0]->id; purple_request_input(gc, _("IM With Password"), NULL, _("Set IM Password"), NULL, FALSE, TRUE, NULL, _("OK"), G_CALLBACK(silcpurple_buddy_privkey_cb), _("Cancel"), G_CALLBACK(silcpurple_buddy_privkey_cb), gc->account, NULL, NULL, p); silc_free(clients); silc_free(nickname);}static voidsilcpurple_buddy_privkey_menu(PurpleBlistNode *node, gpointer data){ PurpleBuddy *buddy; PurpleConnection *gc; g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(buddy->account); silcpurple_buddy_privkey(gc, buddy->name);}/**************************** Get Public Key *********************************/typedef struct { SilcClient client; SilcClientConnection conn; SilcClientID client_id;} *SilcPurpleBuddyGetkey;static voidsilcpurple_buddy_getkey(PurpleConnection *gc, const char *name);static voidsilcpurple_buddy_getkey_cb(SilcPurpleBuddyGetkey g, SilcClientCommandReplyContext cmd){ SilcClientEntry client_entry; unsigned char *pk; SilcUInt32 pk_len; /* Get the client entry. */ client_entry = silc_client_get_client_by_id(g->client, g->conn, &g->client_id); if (!client_entry) { purple_notify_error(g->client->application, _("Get Public Key"), _("The remote user is not present in the network any more"), NULL); silc_free(g); return; } if (!client_entry->public_key) { silc_free(g); return; } /* Now verify the public key */ pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); silcpurple_verify_public_key(g->client, g->conn, client_entry->nickname, SILC_SOCKET_TYPE_CLIENT, pk, pk_len, SILC_SKE_PK_TYPE_SILC, NULL, NULL); silc_free(pk); silc_free(g);}static voidsilcpurple_buddy_getkey_resolved(SilcClient client, SilcClientConnection conn, SilcClientEntry *clients, SilcUInt32 clients_count, void *context){ char tmp[256]; if (!clients) { g_snprintf(tmp, sizeof(tmp), _("User %s is not present in the network"), (const char *)context); purple_notify_error(client->application, _("Get Public Key"), _("Cannot fetch the public key"), tmp); g_free(context); return; } silcpurple_buddy_getkey(client->application, context); silc_free(context);}static voidsilcpurple_buddy_getkey(PurpleConnection *gc, const char *name){ SilcPurple sg = gc->proto_data; SilcClient client = sg->client; SilcClientConnection conn = sg->conn; SilcClientEntry *clients; SilcUInt32 clients_count; SilcPurpleBuddyGetkey g; char *nickname; if (!name) return; if (!silc_parse_userfqdn(name, &nickname, NULL)) return; /* Find client entry */ clients = silc_client_get_clients_local(client, conn, nickname, name, &clients_count); if (!clients) { silc_client_get_clients(client, conn, nickname, NULL, silcpurple_buddy_getkey_resolved, g_strdup(name)); silc_free(nickname); return; } /* Call GETKEY */ g = silc_calloc(1, sizeof(*g)); if (!g) return; g->client = client; g->conn = conn; g->client_id = *clients[0]->id; silc_client_command_call(client, conn, NULL, "GETKEY", clients[0]->nickname, NULL); silc_client_command_pending(conn, SILC_COMMAND_GETKEY, conn->cmd_ident, (SilcCommandCb)silcpurple_buddy_getkey_cb, g); silc_free(clients); silc_free(nickname);}static voidsilcpurple_buddy_getkey_menu(PurpleBlistNode *node, gpointer data){ PurpleBuddy *buddy; PurpleConnection *gc; g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(buddy->account); silcpurple_buddy_getkey(gc, buddy->name);}static voidsilcpurple_buddy_showkey(PurpleBlistNode *node, gpointer data){ PurpleBuddy *b; PurpleConnection *gc; SilcPurple sg; SilcPublicKey public_key; const char *pkfile; g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); b = (PurpleBuddy *) node; gc = purple_account_get_connection(b->account); sg = gc->proto_data; pkfile = purple_blist_node_get_string(node, "public-key"); if (!silc_pkcs_load_public_key(pkfile, &public_key, SILC_PKCS_FILE_PEM) && !silc_pkcs_load_public_key(pkfile, &public_key, SILC_PKCS_FILE_BIN)) { purple_notify_error(gc, _("Show Public Key"), _("Could not load public key"), NULL); return; } silcpurple_show_public_key(sg, b->name, public_key, NULL, NULL); silc_pkcs_public_key_free(public_key);}/**************************** Buddy routines *********************************//* The buddies are implemented by using the WHOIS and WATCH commands that can be used to search users by their public key. Since nicknames aren't unique in SILC we cannot trust the buddy list using their nickname. We associate public keys to buddies and use those to search and watch in the network. The problem is that Purple does not return PurpleBuddy contexts to the callbacks but the buddy names. Naturally, this is not going to work with SILC. But, for now, we have to do what we can... */typedef struct { SilcClient client; SilcClientConnection conn; SilcClientID client_id; PurpleBuddy *b; unsigned char *offline_pk; SilcUInt32 offline_pk_len; unsigned int offline : 1; unsigned int pubkey_search : 1; unsigned int init : 1;} *SilcPurpleBuddyRes;static voidsilcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id);static voidsilcpurple_add_buddy_resolved(SilcClient client, SilcClientConnection conn, SilcClientEntry *clients, SilcUInt32 clients_count, void *context);void silcpurple_get_info(PurpleConnection *gc, const char *who){ SilcPurple sg = gc->proto_data; SilcClient client = sg->client; SilcClientConnection conn = sg->conn; SilcClientEntry client_entry; PurpleBuddy *b; const char *filename, *nick = who; char tmp[256]; if (!who) return; if (strlen(who) > 1 && who[0] == '@') nick = who + 1; if (strlen(who) > 1 && who[0] == '*') nick = who + 1; if (strlen(who) > 2 && who[0] == '*' && who[1] == '@') nick = who + 2; b = purple_find_buddy(gc->account, nick); if (b) { /* See if we have this buddy's public key. If we do use that to search the details. */ filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key"); if (filename) { /* Call WHOIS. The user info is displayed in the WHOIS command reply. */ silc_client_command_call(client, conn, NULL, "WHOIS", "-details", "-pubkey", filename, NULL); return; } if (!b->proto_data) { g_snprintf(tmp, sizeof(tmp), _("User %s is not present in the network"), b->name); purple_notify_error(gc, _("User Information"), _("Cannot get user information"), tmp); return; } client_entry = silc_client_get_client_by_id(client, conn, b->proto_data); if (client_entry) { /* Call WHOIS. The user info is displayed in the WHOIS command reply. */ silc_client_command_call(client, conn, NULL, "WHOIS", client_entry->nickname, "-details", NULL); } } else { /* Call WHOIS just with nickname. */ silc_client_command_call(client, conn, NULL, "WHOIS", nick, NULL); }}static voidsilcpurple_add_buddy_pk_no(SilcPurpleBuddyRes r){ char tmp[512]; g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not trusted"), r->b->name); purple_notify_error(r->client->application, _("Add Buddy"), tmp, _("You cannot receive buddy notifications until you " "import his/her public key. You can use the Get Public Key " "command to get the public key.")); purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);}static voidsilcpurple_add_buddy_save(bool success, void *context){ SilcPurpleBuddyRes r = context; PurpleBuddy *b = r->b; SilcClient client = r->client; SilcClientEntry client_entry; SilcAttributePayload attr; SilcAttribute attribute; SilcVCardStruct vcard; SilcAttributeObjMime message, extension;#ifdef SILC_ATTRIBUTE_USER_ICON SilcAttributeObjMime usericon;#endif SilcAttributeObjPk serverpk, usersign, serversign; gboolean usign_success = TRUE, ssign_success = TRUE; char filename[512], filename2[512], *fingerprint = NULL, *tmp; SilcUInt32 len; int i; if (!success) { /* The user did not trust the public key. */ silcpurple_add_buddy_pk_no(r); silc_free(r); return; } if (r->offline) { /* User is offline. Associate the imported public key with this user. */ fingerprint = silc_hash_fingerprint(NULL, r->offline_pk, r->offline_pk_len); for (i = 0; i < strlen(fingerprint); i++) if (fingerprint[i] == ' ') fingerprint[i] = '_'; g_snprintf(filename, sizeof(filename) - 1, "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub", silcpurple_silcdir(), fingerprint); purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename); purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); silc_free(fingerprint); silc_free(r->offline_pk); silc_free(r); return; } /* Get the client entry. */ client_entry = silc_client_get_client_by_id(r->client, r->conn, &r->client_id); if (!client_entry) { silc_free(r); return; } memset(&vcard, 0, sizeof(vcard)); memset(&message, 0, sizeof(message)); memset(&extension, 0, sizeof(extension));#ifdef SILC_ATTRIBUTE_USER_ICON memset(&usericon, 0, sizeof(usericon));#endif memset(&serverpk, 0, sizeof(serverpk)); memset(&usersign, 0, sizeof(usersign)); memset(&serversign, 0, sizeof(serversign)); /* Now that we have the public key and we trust it now we save the attributes of the buddy and update its status. */ if (client_entry->attrs) { silc_dlist_start(client_entry->attrs); while ((attr = silc_dlist_get(client_entry->attrs)) != SILC_LIST_END) { attribute = silc_attribute_get_attribute(attr); switch (attribute) { case SILC_ATTRIBUTE_USER_INFO: if (!silc_attribute_get_object(attr, (void *)&vcard, sizeof(vcard))) continue; break; case SILC_ATTRIBUTE_STATUS_MESSAGE: if (!silc_attribute_get_object(attr, (void *)&message, sizeof(message))) continue; break; case SILC_ATTRIBUTE_EXTENSION: if (!silc_attribute_get_object(attr, (void *)&extension, sizeof(extension))) continue; break;#ifdef SILC_ATTRIBUTE_USER_ICON case SILC_ATTRIBUTE_USER_ICON: if (!silc_attribute_get_object(attr, (void *)&usericon, sizeof(usericon))) continue; break;#endif case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY: if (serverpk.type) continue; if (!silc_attribute_get_object(attr, (void *)&serverpk, sizeof(serverpk))) continue; break; case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE: if (usersign.data) continue; if (!silc_attribute_get_object(attr, (void *)&usersign, sizeof(usersign))) continue; break; case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE: if (serversign.data) continue; if (!silc_attribute_get_object(attr, (void *)&serversign, sizeof(serversign))) continue; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -