📄 ops.c
字号:
if (channel->topic) purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, channel->topic); } break; case SILC_COMMAND_NICK: { SilcClientEntry local_entry; SilcHashTableList htl; SilcChannelUser chu; const char *oldnick, *newnick; if (status != SILC_STATUS_OK) { purple_notify_error(gc, _("Nick"), _("Failed to change nickname"), silc_get_status_message(error)); return; } local_entry = va_arg(ap, SilcClientEntry); newnick = va_arg(ap, char *); /* Change nick on all channels */ silc_hash_table_list(local_entry->channels, &htl); while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, chu->channel->channel_name, sg->account); if (!convo) continue; oldnick = purple_conv_chat_get_nick(PURPLE_CONV_CHAT(convo)); if (strcmp(oldnick, purple_normalize(purple_conversation_get_account(convo), newnick))) { purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo), oldnick, newnick); purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), newnick); } } silc_hash_table_list_reset(&htl); purple_connection_set_display_name(gc, newnick); } break; case SILC_COMMAND_LIST: { char *topic, *name; int usercount; PurpleRoomlistRoom *room; if (sg->roomlist_canceled) break; if (error != SILC_STATUS_OK) { purple_notify_error(gc, _("Error"), _("Error retrieving room list"), silc_get_status_message(error)); purple_roomlist_set_in_progress(sg->roomlist, FALSE); purple_roomlist_unref(sg->roomlist); sg->roomlist = NULL; return; } (void)va_arg(ap, SilcChannelEntry); name = va_arg(ap, char *); if (!name) { purple_notify_error(gc, _("Roomlist"), _("Cannot get room list"), _("Network is empty")); purple_roomlist_set_in_progress(sg->roomlist, FALSE); purple_roomlist_unref(sg->roomlist); sg->roomlist = NULL; return; } topic = va_arg(ap, char *); usercount = va_arg(ap, int); room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, name, NULL); purple_roomlist_room_add_field(sg->roomlist, room, name); purple_roomlist_room_add_field(sg->roomlist, room, SILC_32_TO_PTR(usercount)); purple_roomlist_room_add_field(sg->roomlist, room, topic ? topic : ""); purple_roomlist_room_add(sg->roomlist, room); if (status == SILC_STATUS_LIST_END || status == SILC_STATUS_OK) { purple_roomlist_set_in_progress(sg->roomlist, FALSE); purple_roomlist_unref(sg->roomlist); sg->roomlist = NULL; } } break; case SILC_COMMAND_GETKEY: { SilcPublicKey public_key; if (status != SILC_STATUS_OK) { purple_notify_error(gc, _("Get Public Key"), _("Cannot fetch the public key"), silc_get_status_message(error)); return; } (void)va_arg(ap, SilcUInt32); (void)va_arg(ap, void *); public_key = va_arg(ap, SilcPublicKey); if (!public_key) purple_notify_error(gc, _("Get Public Key"), _("Cannot fetch the public key"), _("No public key was received")); } break; case SILC_COMMAND_INFO: { char *server_name; char *server_info; char tmp[256]; if (status != SILC_STATUS_OK) { purple_notify_error(gc, _("Server Information"), _("Cannot get server information"), silc_get_status_message(error)); return; } (void)va_arg(ap, SilcServerEntry); server_name = va_arg(ap, char *); server_info = va_arg(ap, char *); if (server_name && server_info) { g_snprintf(tmp, sizeof(tmp), "Server: %s\n%s", server_name, server_info); purple_notify_info(gc, NULL, _("Server Information"), tmp); } } break; case SILC_COMMAND_STATS: { SilcClientStats *stats; char *msg; if (status != SILC_STATUS_OK) { purple_notify_error(gc, _("Server Statistics"), _("Cannot get server statistics"), silc_get_status_message(error)); return; } stats = va_arg(ap, SilcClientStats *); msg = g_strdup_printf(_("Local server start time: %s\n" "Local server uptime: %s\n" "Local server clients: %d\n" "Local server channels: %d\n" "Local server operators: %d\n" "Local router operators: %d\n" "Local cell clients: %d\n" "Local cell channels: %d\n" "Local cell servers: %d\n" "Total clients: %d\n" "Total channels: %d\n" "Total servers: %d\n" "Total routers: %d\n" "Total server operators: %d\n" "Total router operators: %d\n"), silc_time_string(stats->starttime), purple_str_seconds_to_string((int)stats->uptime), (int)stats->my_clients, (int)stats->my_channels, (int)stats->my_server_ops, (int)stats->my_router_ops, (int)stats->cell_clients, (int)stats->cell_channels, (int)stats->cell_servers, (int)stats->clients, (int)stats->channels, (int)stats->servers, (int)stats->routers, (int)stats->server_ops, (int)stats->router_ops); purple_notify_info(gc, NULL, _("Network Statistics"), msg); g_free(msg); } break; case SILC_COMMAND_PING: { if (status != SILC_STATUS_OK) { purple_notify_error(gc, _("Ping"), _("Ping failed"), silc_get_status_message(error)); return; } purple_notify_info(gc, _("Ping"), _("Ping reply received from server"), NULL); } break; case SILC_COMMAND_KILL: if (status != SILC_STATUS_OK) { purple_notify_error(gc, _("Kill User"), _("Could not kill user"), silc_get_status_message(error)); return; } break; case SILC_COMMAND_CMODE: { SilcChannelEntry channel_entry; SilcDList channel_pubkeys, list; SilcArgumentDecodedList e; if (status != SILC_STATUS_OK) return; channel_entry = va_arg(ap, SilcChannelEntry); (void)va_arg(ap, SilcUInt32); (void)va_arg(ap, SilcPublicKey); channel_pubkeys = va_arg(ap, SilcDList); if (!sg->chpk) break; list = silc_dlist_init(); if (channel_pubkeys) { silc_dlist_start(channel_pubkeys); while ((e = silc_dlist_get(channel_pubkeys))) { if (e->arg_type == 0x00 || e->arg_type == 0x03) silc_dlist_add(list, silc_pkcs_public_key_copy(e->argument)); } } silcpurple_chat_chauth_show(sg, channel_entry, list); } break; case SILC_COMMAND_WATCH: if (status != SILC_STATUS_OK) { purple_notify_error(gc, _("WATCH"), _("Cannot watch user"), silc_get_status_message(error)); return; } break; default: if (status == SILC_STATUS_OK) purple_debug_info("silc", "Unhandled command: %d (succeeded)\n", command); else purple_debug_info("silc", "Unhandled command: %d (failed: %s)\n", command, silc_get_status_message(error)); break; }}/* Generic command reply callback for silc_client_command_send. Simply calls the default command_reply client operation callback */SilcBool silcpurple_command_reply(SilcClient client, SilcClientConnection conn, SilcCommand command, SilcStatus status, SilcStatus error, void *context, va_list ap){ silc_command_reply(client, conn, command, status, error, ap); return TRUE;}typedef struct { union { SilcAskPassphrase ask_pass; SilcGetAuthMeth get_auth; } u; void *context;} *SilcPurpleAskPassphrase;static voidsilc_ask_auth_password_cb(const unsigned char *passphrase, SilcUInt32 passphrase_len, void *context){ SilcPurpleAskPassphrase internal = context; if (!passphrase || !(*passphrase)) internal->u.get_auth(SILC_AUTH_NONE, NULL, 0, internal->context); else internal->u.get_auth(SILC_AUTH_PASSWORD, (unsigned char *)passphrase, passphrase_len, internal->context); silc_free(internal);}/* Find authentication method and authentication data by hostname and port. The hostname may be IP address as well. The `auth_method' is the authentication method the remote connection requires. It is however possible that remote accepts also some other authentication method. Application should use the method that may have been configured for this connection. If none has been configured it should use the required `auth_method'. If the `auth_method' is SILC_AUTH_NONE, server does not require any authentication or the required authentication method is not known. The `completion' callback must be called to deliver the chosen authentication method and data. The `conn' may be NULL. */static voidsilc_get_auth_method(SilcClient client, SilcClientConnection conn, char *hostname, SilcUInt16 port, SilcAuthMethod auth_method, SilcGetAuthMeth completion, void *context){ PurpleConnection *gc = client->application; SilcPurple sg = gc->proto_data; SilcPurpleAskPassphrase internal; const char *password; /* Progress */ if (sg->resuming) purple_connection_update_progress(gc, _("Resuming session"), 4, 5); else purple_connection_update_progress(gc, _("Authenticating connection"), 4, 5); /* Check configuration if we have this connection configured. */ if (auth_method == SILC_AUTH_PUBLIC_KEY && purple_account_get_bool(sg->account, "pubkey-auth", FALSE)) { completion(SILC_AUTH_PUBLIC_KEY, NULL, 0, context); return; } if (auth_method == SILC_AUTH_PASSWORD) { password = purple_connection_get_password(gc); if (password && *password) { completion(SILC_AUTH_PASSWORD, (unsigned char *)password, strlen(password), context); return; } /* Ask password from user */ internal = silc_calloc(1, sizeof(*internal)); if (!internal) return; internal->u.get_auth = completion; internal->context = context; silc_ask_passphrase(client, conn, silc_ask_auth_password_cb, internal); return; } completion(SILC_AUTH_NONE, NULL, 0, context);}/* Called to verify received public key. The `conn_type' indicates which entity (server or client) has sent the public key. If user decides to trust the key the application may save the key as trusted public key for later use. The `completion' must be called after the public key has been verified. */static voidsilc_verify_public_key(SilcClient client, SilcClientConnection conn, SilcConnectionType conn_type, SilcPublicKey public_key, SilcVerifyPublicKey completion, void *context){ PurpleConnection *gc = client->application; SilcPurple sg = gc->proto_data; if (!sg->conn && (conn_type == SILC_CONN_SERVER || conn_type == SILC_CONN_ROUTER)) { /* Progress */ if (sg->resuming) purple_connection_update_progress(gc, _("Resuming session"), 3, 5); else purple_connection_update_progress(gc, _("Verifying server public key"), 3, 5); } /* Verify public key */ silcpurple_verify_public_key(client, conn, NULL, conn_type, public_key, completion, context);}static voidsilc_ask_passphrase_cb(SilcPurpleAskPassphrase internal, const char *passphrase){ if (!passphrase || !(*passphrase)) internal->u.ask_pass(NULL, 0, internal->context); else internal->u.ask_pass((unsigned char *)passphrase, strlen(passphrase), internal->context); silc_free(internal);}/* Ask (interact, that is) a passphrase from user. The passphrase is returned to the library by calling the `completion' callback with the `context'. The returned passphrase SHOULD be in UTF-8 encoded, if not then the library will attempt to encode. */static voidsilc_ask_passphrase(SilcClient client, SilcClientConnection conn, SilcAskPassphrase completion, void *context){ PurpleConnection *gc = client->application; SilcPurpleAskPassphrase internal = silc_calloc(1, sizeof(*internal)); if (!internal) return; internal->u.ask_pass = completion; internal->context = context; purple_request_input(gc, _("Passphrase"), NULL, _("Passphrase required"), NULL, FALSE, TRUE, NULL, _("OK"), G_CALLBACK(silc_ask_passphrase_cb), _("Cancel"), G_CALLBACK(silc_ask_passphrase_cb), purple_connection_get_account(gc), NULL, NULL, internal);}/* Called to indicate that incoming key agreement request has been received. If the application wants to perform key agreement it may call silc_client_perform_key_agreement to initiate key agreement or silc_client_send_key_agreement to provide connection point to the remote client in case the `hostname' is NULL. If key agreement is not desired this request can be ignored. The `protocol' is either value 0 for TCP or value 1 for UDP. */static voidsilc_key_agreement(SilcClient client, SilcClientConnection conn, SilcClientEntry client_entry, const char *hostname, SilcUInt16 protocol, SilcUInt16 port){ silcpurple_buddy_keyagr_request(client, conn, client_entry, hostname, port, protocol);}/* Notifies application that file transfer protocol session is being requested by the remote client indicated by the `client_entry' from the `hostname' and `port'. The `session_id' is the file transfer session and it can be used to either accept or reject the file transfer request, by calling the silc_client_file_receive or silc_client_file_close, respectively. */static voidsilc_ftp(SilcClient client, SilcClientConnection conn, SilcClientEntry client_entry, SilcUInt32 session_id, const char *hostname, SilcUInt16 port){ silcpurple_ftp_request(client, conn, client_entry, session_id, hostname, port);}SilcClientOperations ops = { silc_say, silc_channel_message, silc_private_message, silc_notify, silc_command, silc_command_reply, silc_get_auth_method, silc_verify_public_key, silc_ask_passphrase, silc_key_agreement, silc_ftp};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -