diff --git a/extensions/Makefile.am b/extensions/Makefile.am index e4460d1cd..cf44a3702 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -78,6 +78,7 @@ extension_LTLIBRARIES = \ spy_stats_p_notice.la \ spy_trace_notice.la \ drain.la \ + identify_msg.la \ example_module.la if HAVE_HYPERSCAN diff --git a/extensions/identify_msg.c b/extensions/identify_msg.c new file mode 100644 index 000000000..32f35fc27 --- /dev/null +++ b/extensions/identify_msg.c @@ -0,0 +1,29 @@ +#include +#include +#include + +static const char identify_msg_desc[] = "Provides the freenode.net/identify-msg client capability"; + +static void identmsg_outbound(void *); +unsigned int CLICAP_IDENTIFY_MSG = 0; + +mapi_cap_list_av2 identmsg_cap_list[] = { + { MAPI_CAP_CLIENT, "freenode.net/identify-msg", NULL, &CLICAP_IDENTIFY_MSG }, + { 0, NULL, NULL, NULL } +}; + +static mapi_hfn_list_av1 identmsg_hfnlist[] = { + { "outbound_msgbuf", identmsg_outbound }, + { NULL, NULL } +}; + +static void identmsg_outbound(void *data_) +{ + hook_data *data = data_; + struct MsgBuf *msgbuf = data->arg1; + + if (IsIdentified(data->client)) + msgbuf_append_tag(msgbuf, "freenode.net/identified", NULL, CLICAP_IDENTIFY_MSG); +} + +DECLARE_MODULE_AV2(identify_msg, NULL, NULL, NULL, NULL, identmsg_hfnlist, identmsg_cap_list, NULL, identify_msg_desc); diff --git a/include/client.h b/include/client.h index e43838b91..b3174072d 100644 --- a/include/client.h +++ b/include/client.h @@ -429,6 +429,7 @@ struct ListClient #define FLAGS_EXEMPTSPAMBOT 0x02000000 #define FLAGS_EXEMPTSHIDE 0x04000000 #define FLAGS_EXEMPTJUPE 0x08000000 +#define FLAGS_IDENTIFIED 0x10000000 /* owns their current nick */ /* flags for local clients, this needs stuff moved from above to here at some point */ @@ -494,6 +495,9 @@ struct ListClient #define IsTGExcessive(x) ((x)->flags & FLAGS_TGEXCESSIVE) #define SetTGExcessive(x) ((x)->flags |= FLAGS_TGEXCESSIVE) #define ClearTGExcessive(x) ((x)->flags &= ~FLAGS_TGEXCESSIVE) +#define IsIdentified(x) ((x)->flags & FLAGS_IDENTIFIED) +#define SetIdentified(x) ((x)->flags |= FLAGS_IDENTIFIED) +#define ClearIdentified(x) ((x)->flags &= ~FLAGS_IDENTIFIED) /* local flags */ diff --git a/ircd/modules.c b/ircd/modules.c index 54acf80f2..0f254bc7f 100644 --- a/ircd/modules.c +++ b/ircd/modules.c @@ -51,6 +51,7 @@ static const char *core_module_table[] = { "m_ban", "m_die", "m_error", + "m_identified", "m_join", "m_kick", "m_kill", diff --git a/modules/Makefile.am b/modules/Makefile.am index d70055775..3ebe628fc 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -97,4 +97,5 @@ module_LTLIBRARIES = \ core/m_part.la \ core/m_quit.la \ core/m_server.la \ - core/m_squit.la + core/m_squit.la \ + core/m_identified.la diff --git a/modules/core/m_identified.c b/modules/core/m_identified.c new file mode 100644 index 000000000..46d0918ff --- /dev/null +++ b/modules/core/m_identified.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include + +static const char identified_desc[] = "Provides the IDENTIFIED server-to-server command"; + +static void m_identified(struct MsgBuf *, struct Client *, struct Client *, int, const char *[]); + +static struct Message identified_msgtab = { + "IDENTIFIED", 0, 0, 0, 0, + {mg_ignore, mg_ignore, mg_ignore, mg_ignore, {m_identified, 3}, mg_ignore} +}; + +static mapi_clist_av1 identified_clist[] = { + &identified_msgtab, + NULL +}; + +static void identified_nick_change(void *); +static void identified_burst_client(void *); + +static mapi_hfn_list_av1 identified_hfnlist[] = { + { "local_nick_change", identified_nick_change, HOOK_MONITOR }, + { "remote_nick_change", identified_nick_change, HOOK_MONITOR }, + { "burst_client", identified_burst_client }, + { NULL, NULL } +}; + +static void m_identified(struct MsgBuf *msgbuf, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) +{ + struct Client *target_p = find_person(parv[1]); + const char *nick = parv[2]; + + if (target_p == NULL) + return; + + if (irccmp(target_p->name, nick)) + return; + + if (parc > 3 && irccmp(parv[3], "OFF") == 0) + ClearIdentified(target_p); + else + SetIdentified(target_p); +} + +static void identified_nick_change(void *data_) +{ + hook_cdata *data = data_; + const char *oldnick = data->arg1, *newnick = data->arg2; + + if (irccmp(oldnick, newnick) != 0) + ClearIdentified(data->client); +} + +static void identified_burst_client(void *data_) +{ + hook_data_client *data = data_; + + if (IsIdentified(data->target)) + sendto_one(data->client, ":%s ENCAP * IDENTIFIED %s :%s", me.id, use_id(data->target), data->target->name); +} + +DECLARE_MODULE_AV2(identified, NULL, NULL, identified_clist, NULL, identified_hfnlist, NULL, NULL, identified_desc);