#include "stdinc.h"
#include "ircd_defs.h"
#include "msgbuf.h"
+#include "client.h"
+#include "ircd.h"
/*
* parse a message into a MsgBuf.
char *ch;
char *parv[MAXPARA];
size_t n_para;
- int i;
/* skip any leading spaces */
for (ch = line; *ch && *ch == ' '; ch++)
if (*ch == '@')
{
- char *t = ch++;
+ char *t = ch + 1;
ch = strchr(ch, ' ');
if (ch != NULL)
{
- while (t < ch)
+ while (1)
{
char *next = strchr(t, ';');
char *eq = strchr(t, '=');
if (next != NULL)
+ {
*next = '\0';
- if (eq > next)
- eq = NULL;
+ if (eq > next)
+ eq = NULL;
+ }
if (eq != NULL)
- *eq = '\0';
+ *eq++ = '\0';
- msgbuf_append_tag(msgbuf, t, eq);
- t = next + 1;
+ if (*t && *t != ' ')
+ msgbuf_append_tag(msgbuf, t, eq, 0);
+ else
+ break;
+
+ if (next != NULL)
+ t = next + 1;
+ else
+ break;
}
+
+ *ch++ = '\0';
}
}
return 1;
msgbuf->cmd = parv[0];
- msgbuf->n_para = n_para - 1;
-
- for (i = 1; i < n_para; i++)
+ for (size_t i = 0; i < n_para; i++)
msgbuf_append_para(msgbuf, parv[i]);
return 0;
}
+
+static int
+msgbuf_has_matching_tags(struct MsgBuf *msgbuf, unsigned int capmask)
+{
+ for (size_t 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)
+{
+ if (!msgbuf_has_matching_tags(msgbuf, capmask))
+ return;
+
+ *buf = '@';
+
+ for (size_t 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)
+{
+ msgbuf_unparse_prefix(buf, buflen, msgbuf, capmask);
+
+ for (size_t 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;
+}