m_alias: Preserve protocol framing characters

This commit is contained in:
Ed Kellett 2020-07-05 01:15:03 +01:00
parent 3ef1213be4
commit 4e14f9a413
No known key found for this signature in database
GPG key ID: CB9986DEF342FABC
4 changed files with 91 additions and 4 deletions

View file

@ -38,6 +38,7 @@ struct MsgBuf {
const char *origin; /* the origin of the message (or NULL) */ const char *origin; /* the origin of the message (or NULL) */
const char *target; /* the target of the message (either NULL, or custom defined) */ const char *target; /* the target of the message (either NULL, or custom defined) */
const char *cmd; /* the cmd/verb of the message (either NULL, or para[0]) */ const char *cmd; /* the cmd/verb of the message (either NULL, or para[0]) */
char *endp; /* one past the end of the original array */
size_t n_para; /* the number of parameters (always at least 1 if a full message) */ size_t n_para; /* the number of parameters (always at least 1 if a full message) */
const char *para[MAXPARA]; /* parameters vector (starting with cmd as para[0]) */ const char *para[MAXPARA]; /* parameters vector (starting with cmd as para[0]) */
@ -76,6 +77,12 @@ struct MsgBuf_cache {
*/ */
int msgbuf_parse(struct MsgBuf *msgbuf, char *line); int msgbuf_parse(struct MsgBuf *msgbuf, char *line);
/*
* Unparse the tail of a msgbuf perfectly, preserving framing details
* msgbuf->para[n] will reach to the end of the line
*/
void msgbuf_reconstruct_tail(struct MsgBuf *msgbuf, size_t n);
/* /*
* unparse a pure MsgBuf into a buffer. * unparse a pure MsgBuf into a buffer.
* if origin is NULL, me.name will be used. * if origin is NULL, me.name will be used.

View file

@ -154,6 +154,7 @@ msgbuf_parse(struct MsgBuf *msgbuf, char *line)
if (*ch == '\0') if (*ch == '\0')
return 2; return 2;
msgbuf->endp = &ch[strlen(ch)];
msgbuf->n_para = rb_string_to_array(ch, (char **)msgbuf->para, MAXPARA); msgbuf->n_para = rb_string_to_array(ch, (char **)msgbuf->para, MAXPARA);
if (msgbuf->n_para == 0) if (msgbuf->n_para == 0)
return 3; return 3;
@ -162,6 +163,40 @@ msgbuf_parse(struct MsgBuf *msgbuf, char *line)
return 0; return 0;
} }
/*
* Unparse the tail of a msgbuf perfectly, preserving framing details
* msgbuf->para[n] will reach to the end of the line
*/
void
msgbuf_reconstruct_tail(struct MsgBuf *msgbuf, size_t n)
{
if (msgbuf->endp == NULL || n > msgbuf->n_para)
return;
char *c;
const char *c_;
if (n == 0)
c_ = msgbuf->para[n];
else
c_ = msgbuf->para[n-1] + strlen(msgbuf->para[n-1]) + 1;
if (n == msgbuf->n_para && c_ == msgbuf->endp)
return;
msgbuf->para[n] = c_;
/* promote to non-const. msgbuf->endp witnesses that this is allowed */
c = msgbuf->endp - (msgbuf->endp - c_);
for ( ; c < msgbuf->endp; c++)
{
if (*c == '\0')
*c = ' ';
}
}
/* /*
* Unparse msgbuf tags into a buffer * Unparse msgbuf tags into a buffer
* returns the length of the tags written * returns the length of the tags written

View file

@ -114,7 +114,7 @@ m_alias(struct MsgBuf *msgbuf, struct Client *client_p, struct Client *source_p,
{ {
struct Client *target_p; struct Client *target_p;
struct alias_entry *aptr = rb_dictionary_retrieve(alias_dict, msgbuf->cmd); struct alias_entry *aptr = rb_dictionary_retrieve(alias_dict, msgbuf->cmd);
char *p, *str; char *p;
if(aptr == NULL) if(aptr == NULL)
{ {
@ -151,8 +151,8 @@ m_alias(struct MsgBuf *msgbuf, struct Client *client_p, struct Client *source_p,
return; return;
} }
str = reconstruct_parv(parc - 1, &parv[1]); msgbuf_reconstruct_tail(msgbuf, 1);
if(EmptyString(str)) if(EmptyString(parv[1]))
{ {
sendto_one(client_p, form_str(ERR_NOTEXTTOSEND), me.name, target_p->name); sendto_one(client_p, form_str(ERR_NOTEXTTOSEND), me.name, target_p->name);
return; return;
@ -161,5 +161,5 @@ m_alias(struct MsgBuf *msgbuf, struct Client *client_p, struct Client *source_p,
sendto_one(target_p, ":%s PRIVMSG %s :%s", sendto_one(target_p, ":%s PRIVMSG %s :%s",
get_id(client_p, target_p), get_id(client_p, target_p),
p != NULL ? aptr->target : get_id(target_p, target_p), p != NULL ? aptr->target : get_id(target_p, target_p),
str); parv[1]);
} }

View file

@ -3297,6 +3297,49 @@ static void unescape_8bit(void)
} }
} }
static struct MsgBuf *reconstruct_tail_prep(char *line, size_t n)
{
static struct MsgBuf msgbuf;
msgbuf_init(&msgbuf);
msgbuf_parse(&msgbuf, line);
msgbuf_reconstruct_tail(&msgbuf, n);
return &msgbuf;
}
static void reconstruct_tail(void)
{
struct MsgBuf *mb;
mb = reconstruct_tail_prep((char[]){"CMD P1"}, 2);
is_string("CMD", mb->para[0], MSG);
is_string("P1", mb->para[1], MSG);
mb = reconstruct_tail_prep((char[]){"CMD P1 P2"}, 2);
is_string("CMD", mb->para[0], MSG);
is_string("P1", mb->para[1], MSG);
is_string("P2", mb->para[2], MSG);
mb = reconstruct_tail_prep((char[]){" CMD P1 P2 :P3"}, 0);
is_string("CMD P1 P2 :P3", mb->para[0], MSG);
mb = reconstruct_tail_prep((char[]){"CMD P1 P2 :P3"}, 1);
is_string(" P1 P2 :P3", mb->para[1], MSG);
mb = reconstruct_tail_prep((char[]){"CMD P1 P2"}, 1);
is_string("P1 P2", mb->para[1], MSG);
mb = reconstruct_tail_prep((char[]){"CMD P1 P2 "}, 2);
is_string(" P2 ", mb->para[2], MSG);
mb = reconstruct_tail_prep((char[]){"CMD P1 "}, 2);
is_string(" ", mb->para[2], MSG);
mb = reconstruct_tail_prep((char[]){"CMD P1 :"}, 2);
is_string(":", mb->para[2], MSG);
mb = reconstruct_tail_prep((char[]){"CMD P1 :"}, 2);
is_string(" :", mb->para[2], MSG);
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
memset(&me, 0, sizeof(me)); memset(&me, 0, sizeof(me));
@ -3411,5 +3454,7 @@ int main(int argc, char *argv[])
unescape_8bit(); unescape_8bit();
reconstruct_tail();
return 0; return 0;
} }