busybox/libbb/percent_decode.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
   4 */
   5//kbuild:lib-y += percent_decode.o
   6
   7#include "libbb.h"
   8
   9static unsigned hex_to_bin(unsigned char c)
  10{
  11        unsigned v;
  12
  13        v = c - '0';
  14        if (v <= 9)
  15                return v;
  16        /* c | 0x20: letters to lower case, non-letters
  17         * to (potentially different) non-letters */
  18        v = (unsigned)(c | 0x20) - 'a';
  19        if (v <= 5)
  20                return v + 10;
  21        return ~0;
  22/* For testing:
  23void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); }
  24int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f');
  25t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; }
  26*/
  27}
  28
  29char* FAST_FUNC percent_decode_in_place(char *str, int strict)
  30{
  31        /* note that decoded string is always shorter than original */
  32        char *src = str;
  33        char *dst = str;
  34        char c;
  35
  36        while ((c = *src++) != '\0') {
  37                unsigned v;
  38
  39                if (!strict && c == '+') {
  40                        *dst++ = ' ';
  41                        continue;
  42                }
  43                if (c != '%') {
  44                        *dst++ = c;
  45                        continue;
  46                }
  47                v = hex_to_bin(src[0]);
  48                if (v > 15) {
  49 bad_hex:
  50                        if (strict)
  51                                return NULL;
  52                        *dst++ = '%';
  53                        continue;
  54                }
  55                v = (v * 16) | hex_to_bin(src[1]);
  56                if (v > 255)
  57                        goto bad_hex;
  58                if (strict && (v == '/' || v == '\0')) {
  59                        /* caller takes it as indication of invalid
  60                         * (dangerous wrt exploits) chars */
  61                        return str + 1;
  62                }
  63                *dst++ = v;
  64                src += 2;
  65        }
  66        *dst = '\0';
  67        return str;
  68}
  69