Fix escaping of keyword substitutions.
Using adc_msg_escape will escape spaces etc inside keyword subsitutions in user command messages (e.g., %[line:Enter a value] becomes %[line:Enter\sa\svalue]) which leads to them being displayed wrong in the client. Values outside the substitutions still need to be escaped. This commit adds an (internal) ucmd_msg_escape() function, plus a ucmd_msg_escape_length() helper, to the user command handler which correctly handles keyword substitutions.
This commit is contained in:
parent
2e7f0f9c12
commit
7a440211dd
@ -57,6 +57,107 @@ int ucmd_expand_tt(struct plugin_ucmd* ucmd, size_t size)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Calculate the number of characters needed to store the escaped message. */
|
||||||
|
size_t ucmd_msg_escape_length(const char* message)
|
||||||
|
{
|
||||||
|
size_t extra = 0;
|
||||||
|
size_t i;
|
||||||
|
int insub = 0;
|
||||||
|
for(i = 0; message[i]; i++)
|
||||||
|
{
|
||||||
|
/* In a substitution block, no escaping needed. */
|
||||||
|
if(insub == 2)
|
||||||
|
{
|
||||||
|
if(message[i] == ']') insub = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not in a substitution block. */
|
||||||
|
else{
|
||||||
|
/* A character that needs escaping. */
|
||||||
|
if(message[i] == ' ' || message[i] == '\n' || message[i] == '\\'){
|
||||||
|
extra++;
|
||||||
|
insub = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See if we're heading into a substitution block. */
|
||||||
|
else if(message[i] == '%') insub = 1;
|
||||||
|
else if(message[i] == '[' && insub == 1) insub = 2;
|
||||||
|
else insub = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Done. */
|
||||||
|
return i + extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Escape a message that is being put into a user command. We cannot use
|
||||||
|
* adc_msg_escape for this as keyword substitutions should not be escaped while
|
||||||
|
* general text should be. */
|
||||||
|
char* ucmd_msg_escape(const char* message)
|
||||||
|
{
|
||||||
|
/* Allocate the memory we need. */
|
||||||
|
size_t esclen = ucmd_msg_escape_length(message);
|
||||||
|
char *escaped = malloc(esclen + 1);
|
||||||
|
|
||||||
|
int insub = 0;
|
||||||
|
size_t i;
|
||||||
|
size_t n = 0;
|
||||||
|
|
||||||
|
for(i = 0; message[i]; i++)
|
||||||
|
{
|
||||||
|
/* In a substitution block, no escaping needed. */
|
||||||
|
if(insub == 2)
|
||||||
|
{
|
||||||
|
if(message[i] == ']') insub = 0;
|
||||||
|
escaped[n++] = message[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not in a substitution block. */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch(message[i])
|
||||||
|
{
|
||||||
|
/* Deal with characters that need escaping. */
|
||||||
|
case '\\':
|
||||||
|
escaped[n++] = '\\';
|
||||||
|
escaped[n++] = '\\';
|
||||||
|
insub = 0;
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
escaped[n++] = '\\';
|
||||||
|
escaped[n++] = 'n';
|
||||||
|
insub = 0;
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
escaped[n++] = '\\';
|
||||||
|
escaped[n++] = 's';
|
||||||
|
insub = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Characters that start a substitution block. */
|
||||||
|
case '%':
|
||||||
|
escaped[n++] = message[i];
|
||||||
|
insub = 1;
|
||||||
|
break;
|
||||||
|
case '[':
|
||||||
|
escaped[n++] = message[i];
|
||||||
|
if(insub == 1) insub = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Standard character. */
|
||||||
|
default:
|
||||||
|
escaped[n++] = message[i];
|
||||||
|
insub = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Done. */
|
||||||
|
escaped[n] = 0;
|
||||||
|
return escaped;
|
||||||
|
}
|
||||||
|
|
||||||
struct plugin_ucmd* cbfunc_ucmd_create(struct plugin_handle* plugin, const char* name, size_t length){
|
struct plugin_ucmd* cbfunc_ucmd_create(struct plugin_handle* plugin, const char* name, size_t length){
|
||||||
/* Need a name. */
|
/* Need a name. */
|
||||||
if(name == NULL)
|
if(name == NULL)
|
||||||
@ -102,8 +203,10 @@ struct plugin_ucmd* cbfunc_ucmd_create(struct plugin_handle* plugin, const char*
|
|||||||
int cbfunc_ucmd_add_chat(struct plugin_handle* plugin, struct plugin_ucmd* ucmd, const char* message, int me)
|
int cbfunc_ucmd_add_chat(struct plugin_handle* plugin, struct plugin_ucmd* ucmd, const char* message, int me)
|
||||||
{
|
{
|
||||||
/* Double-escape the message - once for when the client sends it back, and
|
/* Double-escape the message - once for when the client sends it back, and
|
||||||
* then again to insert it into the user command message we send to them. */
|
* then again to insert it into the user command message we send to them.
|
||||||
char* temp = adc_msg_escape(message);
|
* Note the two different escape functions used for the different escapes -
|
||||||
|
* the UCMD escape is needed to handle substitution blocks correctly. */
|
||||||
|
char* temp = ucmd_msg_escape(message);
|
||||||
char* escmsg = adc_msg_escape(temp);
|
char* escmsg = adc_msg_escape(temp);
|
||||||
free(temp);
|
free(temp);
|
||||||
size_t msglen = strlen(escmsg);
|
size_t msglen = strlen(escmsg);
|
||||||
@ -148,8 +251,10 @@ int cbfunc_ucmd_add_chat(struct plugin_handle* plugin, struct plugin_ucmd* ucmd,
|
|||||||
int cbfunc_ucmd_add_pm(struct plugin_handle* plugin, struct plugin_ucmd* ucmd, const char* to, const char* message, int echo)
|
int cbfunc_ucmd_add_pm(struct plugin_handle* plugin, struct plugin_ucmd* ucmd, const char* to, const char* message, int echo)
|
||||||
{
|
{
|
||||||
/* Double-escape the message - once for when the client sends it back, and
|
/* Double-escape the message - once for when the client sends it back, and
|
||||||
* then again to insert it into the user command message we send to them. */
|
* then again to insert it into the user command message we send to them.
|
||||||
char* temp = adc_msg_escape(message);
|
* Note the two different escape functions used for the different escapes -
|
||||||
|
* the UCMD escape is needed to handle substitution blocks correctly. */
|
||||||
|
char* temp = ucmd_msg_escape(message);
|
||||||
char* escmsg = adc_msg_escape(temp);
|
char* escmsg = adc_msg_escape(temp);
|
||||||
free(temp);
|
free(temp);
|
||||||
size_t msglen = strlen(escmsg);
|
size_t msglen = strlen(escmsg);
|
||||||
|
Loading…
Reference in New Issue
Block a user