X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/d670fe5271c76714c3a85fdcb2d88eb483f84c14..e23126c83b87bd59ab4a9f89bdd0d1aa76e96129:/ircd/msgbuf.c diff --git a/ircd/msgbuf.c b/ircd/msgbuf.c index a7fe53b2..4d47b186 100644 --- a/ircd/msgbuf.c +++ b/ircd/msgbuf.c @@ -22,6 +22,8 @@ #include "stdinc.h" #include "ircd_defs.h" #include "msgbuf.h" +#include "client.h" +#include "ircd.h" /* * parse a message into a MsgBuf. @@ -111,3 +113,134 @@ msgbuf_parse(struct MsgBuf *msgbuf, char *line) return 0; } + +static int +msgbuf_has_matching_tags(struct MsgBuf *msgbuf, unsigned int capmask) +{ + int i; + + for (i = 0; i < msgbuf->n_tags; i++) + { + if ((msgbuf->tags[i].capmask & capmask) != 0) + return 1; + } + + return 0; +} + +static void +msgbuf_unparse_tags(char *buf, size_t buflen, struct MsgBuf *msgbuf, unsigned int capmask) +{ + int i; + + if (!msgbuf_has_matching_tags(msgbuf, capmask)) + return; + + *buf = '@'; + + for (i = 0; i < msgbuf->n_tags; i++) + { + if ((msgbuf->tags[i].capmask & capmask) == 0) + continue; + + if (i != 0) + rb_strlcat(buf, ";", buflen); + + rb_strlcat(buf, msgbuf->tags[i].key, buflen); + + /* XXX properly handle escaping */ + if (msgbuf->tags[i].value) + { + rb_strlcat(buf, "=", buflen); + rb_strlcat(buf, msgbuf->tags[i].value, buflen); + } + } + + rb_strlcat(buf, " ", buflen); +} + +void +msgbuf_unparse_prefix(char *buf, size_t buflen, struct MsgBuf *msgbuf, unsigned int capmask) +{ + memset(buf, 0, buflen); + + if (msgbuf->n_tags > 0) + msgbuf_unparse_tags(buf, buflen, msgbuf, capmask); + + rb_snprintf_append(buf, buflen, ":%s ", msgbuf->origin != NULL ? msgbuf->origin : me.name); + + if (msgbuf->cmd != NULL) + rb_snprintf_append(buf, buflen, "%s ", msgbuf->cmd); + + if (msgbuf->target != NULL) + rb_snprintf_append(buf, buflen, "%s ", msgbuf->target); +} + +/* + * unparse a pure MsgBuf into a buffer. + * if origin is NULL, me.name will be used. + * cmd may not be NULL. + * returns 0 on success, 1 on error. + */ +int +msgbuf_unparse(char *buf, size_t buflen, struct MsgBuf *msgbuf, unsigned int capmask) +{ + int i; + + msgbuf_unparse_prefix(buf, buflen, msgbuf, capmask); + + for (i = msgbuf->cmd != NULL ? 0 : 1; i < msgbuf->n_para; i++) + { + if (i == (msgbuf->n_para - 1)) + { + if (strchr(msgbuf->para[i], ' ') != NULL) + rb_snprintf_append(buf, buflen, ":%s", msgbuf->para[i]); + else + rb_strlcat(buf, msgbuf->para[i], buflen); + } + else + rb_strlcat(buf, msgbuf->para[i], buflen); + } + + return 0; +} + +/* + * unparse a MsgBuf stem + format string into a buffer + * if origin is NULL, me.name will be used. + * cmd may not be NULL. + * returns 0 on success, 1 on error. + */ +int +msgbuf_vunparse_fmt(char *buf, size_t buflen, struct MsgBuf *head, unsigned int capmask, const char *fmt, va_list va) +{ + char *ws; + size_t prefixlen; + + msgbuf_unparse_prefix(buf, buflen, head, capmask); + prefixlen = strlen(buf); + + ws = buf + prefixlen; + vsnprintf(ws, buflen - prefixlen, fmt, va); + + return 0; +} + +/* + * unparse a MsgBuf stem + format string into a buffer (with va_list handling) + * if origin is NULL, me.name will be used. + * cmd may not be NULL. + * returns 0 on success, 1 on error. + */ +int +msgbuf_unparse_fmt(char *buf, size_t buflen, struct MsgBuf *head, unsigned int capmask, const char *fmt, ...) +{ + va_list va; + int res; + + va_start(va, fmt); + res = msgbuf_vunparse_fmt(buf, buflen, head, capmask, fmt, va); + va_end(va); + + return res; +}