patch 9.1.1669: Vim script: no support for URI de-/encoding
Problem: Vim script: no support for URI de-/encoding
(ubaldot)
Solution: Add the uri_encode() and uri_decode() functions
(Yegappan Lakshmanan)
fixes: #17861
closes: #18034
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
da34f84847
commit
454c7ea484
145
src/strings.c
145
src/strings.c
@ -2310,6 +2310,151 @@ f_trim(typval_T *argvars, typval_T *rettv)
|
||||
rettv->vval.v_string = vim_strnsave(head, tail - head);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decodes a URI-encoded string.
|
||||
*
|
||||
* Parameters:
|
||||
* str - The URI-encoded input string (may contain %XX sequences and '+').
|
||||
*
|
||||
* Returns:
|
||||
* A newly allocated string with URI encoding decoded:
|
||||
* - %XX sequences are converted to the corresponding character.
|
||||
* - If the input is malformed (e.g., incomplete % sequence), the original
|
||||
* characters are copied.
|
||||
* The output string will never be longer than the input string.
|
||||
* The caller is responsible for freeing the returned string.
|
||||
*
|
||||
* Returns NULL if input is NULL or memory allocation fails.
|
||||
*/
|
||||
static char_u *
|
||||
uri_decode(char_u *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
|
||||
size_t len = STRLEN(str);
|
||||
|
||||
char_u *decoded = alloc(len + 1);
|
||||
if (!decoded)
|
||||
return NULL;
|
||||
|
||||
char_u *p = decoded;
|
||||
size_t i = 0;
|
||||
|
||||
while (i < len)
|
||||
{
|
||||
if (str[i] == '%')
|
||||
{
|
||||
if (i + 2 >= len)
|
||||
{
|
||||
// Malformed encoding
|
||||
*p++ = str[i++];
|
||||
if (str[i] != NUL)
|
||||
*p++ = str[i++];
|
||||
}
|
||||
else
|
||||
{
|
||||
int val = hexhex2nr(&str[i + 1]);
|
||||
if (val != -1)
|
||||
{
|
||||
*p++ = (char_u)val;
|
||||
i += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
// invalid hex digits following "%"
|
||||
for (int j = 0; j < 3; j++)
|
||||
*p++ = str[i++];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
*p++ = str[i++];
|
||||
}
|
||||
|
||||
*p = NUL;
|
||||
|
||||
return decoded;
|
||||
}
|
||||
|
||||
/*
|
||||
* "uri_decode({str})" function
|
||||
*/
|
||||
void
|
||||
f_uridecode(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = NULL;
|
||||
|
||||
if (check_for_string_arg(argvars, 0) == FAIL)
|
||||
return;
|
||||
|
||||
rettv->vval.v_string = uri_decode(tv_get_string(&argvars[0]));
|
||||
}
|
||||
|
||||
/*
|
||||
* Encodes a string for safe use in a URI.
|
||||
*
|
||||
* Parameters:
|
||||
* str - The input string to encode.
|
||||
*
|
||||
* Returns:
|
||||
* A newly allocated string where:
|
||||
* - Alphanumeric characters and '-', '_', '.', '~' are left unchanged.
|
||||
* - All other bytes are encoded as %XX (uppercase hex).
|
||||
* The caller is responsible for freeing the returned string.
|
||||
*
|
||||
* Returns NULL if input is NULL or memory allocation fails.
|
||||
*/
|
||||
static char_u *
|
||||
uri_encode(char_u *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
|
||||
size_t len = STRLEN(str);
|
||||
|
||||
// Worst case: every character needs encoding => 3x size + 1 for null
|
||||
// terminator
|
||||
char_u *encoded = alloc(len * 3 + 1);
|
||||
if (encoded == NULL)
|
||||
return NULL;
|
||||
|
||||
char_u *p = encoded;
|
||||
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
char_u c = str[i];
|
||||
if (ASCII_ISALNUM(c) || c == '-' || c == '_' || c == '.' || c == '~')
|
||||
*p++ = c;
|
||||
else
|
||||
{
|
||||
sprintf((char *)p, "%%%02X", c);
|
||||
p += 3;
|
||||
}
|
||||
}
|
||||
|
||||
*p = NUL;
|
||||
|
||||
return encoded;
|
||||
}
|
||||
|
||||
/*
|
||||
* "uri_encode({str})" function
|
||||
*/
|
||||
void
|
||||
f_uriencode(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = NULL;
|
||||
|
||||
if (check_for_string_arg(argvars, 0) == FAIL)
|
||||
return;
|
||||
|
||||
rettv->vval.v_string = uri_encode(tv_get_string(&argvars[0]));
|
||||
}
|
||||
|
||||
static char *e_printf = N_(e_insufficient_arguments_for_printf);
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user