📄 buddy.c
字号:
/* Find client entry */ clients = silc_client_get_clients_local(sg->client, sg->conn, name, FALSE); if (!clients) { silc_client_get_clients(sg->client, sg->conn, name, NULL, silcpurple_buddy_privkey_resolved, g_strdup(name)); return; } silc_dlist_start(clients); client_entry = silc_dlist_get(clients); p = silc_calloc(1, sizeof(*p)); if (!p) return; p->client = sg->client; p->conn = sg->conn; p->client_id = client_entry->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_client_list_free(sg->client, sg->conn, clients);}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 SilcBoolsilcpurple_buddy_getkey_cb(SilcClient client, SilcClientConnection conn, SilcCommand command, SilcStatus status, SilcStatus error, void *context, va_list ap){ SilcClientEntry client_entry; SilcPurpleBuddyGetkey g = context; if (status != SILC_STATUS_OK) { 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 FALSE; } /* 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 FALSE; } if (!client_entry->public_key) { silc_free(g); return FALSE; } /* Now verify the public key */ silcpurple_verify_public_key(g->client, g->conn, client_entry->nickname, SILC_CONN_CLIENT, client_entry->public_key, NULL, NULL); silc_free(g); return TRUE;}static voidsilcpurple_buddy_getkey_resolved(SilcClient client, SilcClientConnection conn, SilcStatus status, SilcDList clients, 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 client_entry; SilcDList clients; SilcPurpleBuddyGetkey g; SilcUInt16 cmd_ident; if (!name) return; /* Find client entry */ clients = silc_client_get_clients_local(client, conn, name, FALSE); if (!clients) { silc_client_get_clients(client, conn, name, NULL, silcpurple_buddy_getkey_resolved, g_strdup(name)); return; } silc_dlist_start(clients); client_entry = silc_dlist_get(clients); /* Call GETKEY */ g = silc_calloc(1, sizeof(*g)); if (!g) return; g->client = client; g->conn = conn; g->client_id = client_entry->id; cmd_ident = silc_client_command_call(client, conn, NULL, "GETKEY", client_entry->nickname, NULL); silc_client_command_pending(conn, SILC_COMMAND_GETKEY, cmd_ident, silcpurple_buddy_getkey_cb, g); silc_client_list_free(client, conn, clients);}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)) { 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; SilcPublicKey public_key; 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, SilcStatus status, SilcDList clients, 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(SilcBool success, void *context){ SilcPurpleBuddyRes r = context; PurpleBuddy *b = r->b; SilcClientEntry client_entry; SilcAttributePayload attr; SilcAttribute attribute; SilcVCardStruct vcard; SilcMime message = NULL, extension = NULL; SilcMime usericon = NULL; SilcAttributeObjPk serverpk, usersign, serversign; gboolean usign_success = TRUE, ssign_success = TRUE; char filename[512], filename2[512], *fingerprint = NULL, *tmp; SilcUInt32 len; SilcHash hash; int i; if (!success) { /* The user did not trust the public key. */ silcpurple_add_buddy_pk_no(r); silc_free(r->offline_pk); if (r->public_key) silc_pkcs_public_key_free(r->public_key); 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); if (r->public_key) silc_pkcs_public_key_free(r->public_key); 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->offline_pk); silc_pkcs_public_key_free(r->public_key); if (r->public_key) silc_pkcs_public_key_free(r->public_key); silc_free(r); return; } memset(&vcard, 0, sizeof(vcard)); 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: message = silc_mime_alloc(); if (!silc_attribute_get_object(attr, (void *)message, sizeof(*message))) continue; break; case SILC_ATTRIBUTE_EXTENSION: extension = silc_mime_alloc(); if (!silc_attribute_get_object(attr, (void *)extension, sizeof(*extension))) continue; break; case SILC_ATTRIBUTE_USER_ICON: usericon = silc_mime_alloc(); if (!silc_attribute_get_object(attr, (void *)usericon, sizeof(*usericon))) continue; break; 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; default: break; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -