From b1ad8dbd71266a53f7760a88d981b33a032631ca Mon Sep 17 00:00:00 2001 From: Egor Date: Fri, 27 Oct 2023 23:59:10 +0300 Subject: [PATCH] add chghost, setname, account-notify --- src/admin.c | 11 +++++++++++ src/common.h | 3 +++ src/irc.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- src/irc.h | 1 + src/ircfmt.c | 15 +++++++++++++++ src/ircfmt.h | 3 +++ 6 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/admin.c b/src/admin.c index 431d699..b249422 100644 --- a/src/admin.c +++ b/src/admin.c @@ -253,6 +253,15 @@ static int fn_channel_part(lua_State *L) channel_part(cl, chan, reason, kicker); return 0; } +static int fn_client_chghost(lua_State *L) +{ + struct client_data *cl = *(struct client_data **)luaL_checkudata(L, 1, "client"); + const char *newusername = luaL_checkstring(L, 2); + const char *newhostname = luaL_checkstring(L, 3); + client_chghost(cl, newusername, newhostname); + return 0; +} + void admin_init(void) { lua_State *L = luaL_newstate(); @@ -309,6 +318,8 @@ void admin_init(void) lua_setglobal(L, "channel_join"); lua_pushcfunction(L, fn_channel_part); lua_setglobal(L, "channel_part"); + lua_pushcfunction(L, fn_client_chghost); + lua_setglobal(L, "client_chghost"); } void admin_fini(void) { diff --git a/src/common.h b/src/common.h index 3f1dafe..1c59cba 100644 --- a/src/common.h +++ b/src/common.h @@ -29,6 +29,9 @@ struct tls; #define CAP_AWAYNOTIFY 8 #define CAP_INVITENOTIFY 16 #define CAP_EXTENDEDMONITOR 32 +#define CAP_CHGHOST 64 +#define CAP_SETNAME 128 +#define CAP_ACCOUNTNOTIFY 256 struct client_data { SOCKET FD; struct tls *cctx; diff --git a/src/irc.c b/src/irc.c index 508457f..83ee3fc 100644 --- a/src/irc.c +++ b/src/irc.c @@ -201,6 +201,9 @@ int processPacket(struct client_data *client, char *source, char *command, int a { "away-notify", CAP_AWAYNOTIFY }, { "invite-notify", CAP_INVITENOTIFY }, { "extended-monitor", CAP_EXTENDEDMONITOR }, + { "chghost", CAP_CHGHOST }, + { "setname", CAP_SETNAME }, + { "account-notify", CAP_ACCOUNTNOTIFY }, { 0, 0 } }; @@ -1137,6 +1140,16 @@ int processPacket(struct client_data *client, char *source, char *command, int a default: return err_needmoreparams(client, command), sendbuf(client), 0; /* FIXME: wrong error */ } + } else if(strcmp(command, "SETNAME") == 0) { + if (!is_registered(client)) + return err_notregistered(client), sendbuf(client), 0; + if (argc == 0) + return err_needmoreparams(client, command), sendbuf(client), 0; + free(client->realname); + client->realname = mystrdup(args[0]); + msg_setname(client); + int cookie = sendbuf_visible_caps(client, CAP_SETNAME, 0); + sendbuf_monitor(client->key, cookie, CAP_SETNAME|CAP_EXTENDEDMONITOR, 0); #ifdef HAS_LUA } else if(strcmp(command, "LUA") == 0) { if (argc < 1) @@ -1301,9 +1314,43 @@ void setNick(struct client_data *client, char* nickname) { if (map_set(&client_map, client->key, client, 0) == -1) abort(); rpl_mononline(0, client), sendbuf_monitor(client->key, 0, 0, 0); - return; } +void client_chghost(struct client_data *client, const char *newusername, const char *newhostname) +{ + if (!strcmp(client->username, newusername) && !strcmp(client->hostname, newhostname)) + return; + msg_quit(client, "Changing hostname", ""); + sendbuf_visible_caps(client, 0, CAP_CHGHOST); + msg_chghost(client, newusername, newhostname); + int cookie = sendbuf_visible_caps(client, CAP_CHGHOST, 0); + sendbuf_monitor(client->key, cookie, CAP_CHGHOST|CAP_EXTENDEDMONITOR, 0); + int changedacc = client->username[0] != '~' || newusername[0] != '~'; + free(client->username); + client->username = mystrdup(newusername); + free(client->hostname); + client->hostname = mystrdup(newhostname); + struct channel *chan; + map_foreach(&client->channels, 0, &chan) { + msg_join(client, chan); + sendbuf_list_sans_self_caps(client, &chan->members, 0, 0, CAP_EXTENDEDJOIN|CAP_CHGHOST); + msg_join(client, chan); + sendbuf_list_sans_self_caps(client, &chan->members, 0, CAP_EXTENDEDJOIN, CAP_CHGHOST); + if (map_get(&chan->v, client->key)) { + copy_strf(&databuf, ":cia!cia@cia.gov MODE %s +v %s\r\n", chan->name, client->nick); + sendbuf_list_sans_self_caps(client, &chan->members, 0, 0, CAP_CHGHOST); + } + if (map_get(&chan->o, client->key)) { + copy_strf(&databuf, ":cia!cia@cia.gov MODE %s +o %s\r\n", chan->name, client->nick); + sendbuf_list_sans_self_caps(client, &chan->members, 0, 0, CAP_CHGHOST); + } + } + if (changedacc) { + msg_account(client); + int cookie = sendbuf_visible_caps(client, CAP_ACCOUNTNOTIFY, 0); + sendbuf_monitor(client->key, cookie, CAP_ACCOUNTNOTIFY|CAP_EXTENDEDMONITOR, 0); + } +} void channel_sendtopic(struct client_data *client, struct channel *chan, int joining) { if (chan->topic) { diff --git a/src/irc.h b/src/irc.h index 93b2cf8..0a1f9e4 100644 --- a/src/irc.h +++ b/src/irc.h @@ -13,6 +13,7 @@ void newUser(struct client_data *client); void sendLUSERS(struct client_data *client); void sendMOTD(struct client_data *client); void setNick(struct client_data *client, char* nickname); +void client_chghost(struct client_data *client, const char *newusername, const char *newhostname); struct client_data *findClient(const char *nickname); struct channel *findChannel(const char *channel); void channel_sendtopic(struct client_data *client, struct channel *chan, int joining); diff --git a/src/ircfmt.c b/src/ircfmt.c index 79de2e5..5a1457d 100644 --- a/src/ircfmt.c +++ b/src/ircfmt.c @@ -115,6 +115,21 @@ void msg_wallops(struct client_data *src, const char *msg) copy_strf(&databuf, ":%s!%s@%s WALLOPS :%s\r\n", src->nick, src->username, src->hostname, msg); } +void msg_chghost(struct client_data *src, const char *newusername, const char *newhostname) +{ + copy_strf(&databuf, ":%s!%s@%s CHGHOST %s %s\r\n", + src->nick, src->username, src->hostname, newusername, newhostname); +} +void msg_setname(struct client_data *src) +{ + copy_strf(&databuf, ":%s!%s@%s SETNAME :%s\r\n", + src->nick, src->username, src->hostname, src->realname); +} +void msg_account(struct client_data *src) +{ + copy_strf(&databuf, ":%s!%s@%s ACCOUNT %s\r\n", + src->nick, src->username, src->hostname, src->username[0] != '~' ? src->username : "*"); +} void rpl_welcome(struct client_data *client) // 001 { copy_strf(&databuf, ":%s 001 %s :Welcome to the Patchy Network, %s\r\n", hostname, client->nick, client->nick); diff --git a/src/ircfmt.h b/src/ircfmt.h index b39a76b..2b0f285 100644 --- a/src/ircfmt.h +++ b/src/ircfmt.h @@ -18,6 +18,9 @@ void msg_notice(struct client_data *src, const char *dst, const char *msg); void msg_notice_server(const char *src, const char *dst, const char *msg); void msg_kill(struct client_data *src, struct client_data *dst, const char *reason); void msg_wallops(struct client_data *src, const char *msg); +void msg_chghost(struct client_data *src, const char *newusername, const char *newhostname); +void msg_setname(struct client_data *src); +void msg_account(struct client_data *src); void rpl_welcome(struct client_data *client); // 001 void rpl_yourhost(struct client_data *client); // 002 void rpl_created(struct client_data *client); // 003 -- 2.56.0