int jk_unescape_url()

in native/common/jk_url.c [176:291]


int jk_unescape_url(char *const unescaped,
                    const char *const url,
                    size_t slen,
                    const char *const forbid,
                    const char *const reserved,
                    const int plus,
                    size_t *len)
{
    size_t size = 1;
    int found = 0;
    const char *s = (const char *) url;
    char *d = (char *) unescaped;
    register int badesc, badpath;

    if (!url) {
        return JK_FALSE;
    }

    badesc = 0;
    badpath = 0;
    if (s) {
        if (d) {
            for (; *s && slen; ++s, d++, slen--) {
                if (plus && *s == '+') {
                    *d = ' ';
                    found = 1;
                }
                else if (*s != '%') {
                    *d = *s;
                }
                else {
                    if (!jk_isxdigit(*(s + 1)) || !jk_isxdigit(*(s + 2))) {
                        badesc = 1;
                        *d = '%';
                    }
                    else {
                        char decoded;
                        decoded = x2c(s + 1);
                        if ((decoded == '\0')
                                || (forbid && strchr(forbid, decoded))) {
                            badpath = 1;
                            *d = decoded;
                            s += 2;
                            slen -= 2;
                        }
                        else if (reserved && strchr(reserved, decoded)) {
                            *d++ = *s++;
                            *d++ = *s++;
                            *d = *s;
                            size += 2;
                        }
                        else {
                            *d = decoded;
                            s += 2;
                            slen -= 2;
                            found = 1;
                        }
                    }
                }
                size++;
            }
            *d = '\0';
        }
        else {
            for (; *s && slen; ++s, slen--) {
                if (plus && *s == '+') {
                    found = 1;
                }
                else if (*s != '%') {
                    /* character unchanged */
                }
                else {
                    if (!jk_isxdigit(*(s + 1)) || !jk_isxdigit(*(s + 2))) {
                        badesc = 1;
                    }
                    else {
                        char decoded;
                        decoded = x2c(s + 1);
                        if ((decoded == '\0')
                                || (forbid && strchr(forbid, decoded))) {
                            badpath = 1;
                            s += 2;
                            slen -= 2;
                        }
                        else if (reserved && strchr(reserved, decoded)) {
                            s += 2;
                            slen -= 2;
                            size += 2;
                        }
                        else {
                            s += 2;
                            slen -= 2;
                            found = 1;
                        }
                    }
                }
                size++;
            }
        }
    }

    if (len) {
        *len = size;
    }
    if (badesc) {
        return JK_FALSE;
    }
    else if (badpath) {
        return JK_FALSE;
    }
    else if (!found) {
        return JK_TRUE;
    }

    return JK_TRUE;
}