123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- /* vi: set sw=4 ts=4: */
- /*
- * Licensed under GPLv2 or later, see file LICENSE in this source tree.
- */
- //kbuild:lib-y += percent_decode.o
- #include "libbb.h"
- static unsigned hex_to_bin(unsigned char c)
- {
- unsigned v;
- v = c - '0';
- if (v <= 9)
- return v;
- /* c | 0x20: letters to lower case, non-letters
- * to (potentially different) non-letters */
- v = (unsigned)(c | 0x20) - 'a';
- if (v <= 5)
- return v + 10;
- return ~0;
- /* For testing:
- void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); }
- int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f');
- t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; }
- */
- }
- char* FAST_FUNC percent_decode_in_place(char *str, int strict)
- {
- /* note that decoded string is always shorter than original */
- char *src = str;
- char *dst = str;
- char c;
- while ((c = *src++) != '\0') {
- unsigned v;
- if (!strict && c == '+') {
- *dst++ = ' ';
- continue;
- }
- if (c != '%') {
- *dst++ = c;
- continue;
- }
- v = hex_to_bin(src[0]);
- if (v > 15) {
- bad_hex:
- if (strict)
- return NULL;
- *dst++ = '%';
- continue;
- }
- v = (v * 16) | hex_to_bin(src[1]);
- if (v > 255)
- goto bad_hex;
- if (strict && (v == '/' || v == '\0')) {
- /* caller takes it as indication of invalid
- * (dangerous wrt exploits) chars */
- return str + 1;
- }
- *dst++ = v;
- src += 2;
- }
- *dst = '\0';
- return str;
- }
|