/* * ModSecurity, http://www.modsecurity.org/ * Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/) * * You may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * If any of the files related to licensing are missing or if you have any * other questions related to licensing please contact Trustwave Holdings, Inc. * directly using the email address security@modsecurity.org. * */ #include "src/utils/decode.h" #include "modsecurity/modsecurity.h" #include "src/utils/string.h" namespace modsecurity { namespace utils { int urldecode_nonstrict_inplace(unsigned char *input, uint64_t input_len, int *invalid_count, int *changed) { unsigned char *d = (unsigned char *)input; uint64_t i, count; *changed = 0; if (input == NULL) { return -1; } i = count = 0; while (i < input_len) { if (input[i] == '%') { /* Character is a percent sign. */ /* Are there enough bytes available? */ if (i + 2 < input_len) { char c1 = input[i + 1]; char c2 = input[i + 2]; if (VALID_HEX(c1) && VALID_HEX(c2)) { uint64_t uni = string::x2c(&input[i + 1]); *d++ = (wchar_t)uni; count++; i += 3; *changed = 1; } else { /* Not a valid encoding, skip this % */ *d++ = input[i++]; count++; (*invalid_count)++; } } else { /* Not enough bytes available, copy the raw bytes. */ *d++ = input[i++]; count++; (*invalid_count)++; } } else { /* Character is not a percent sign. */ if (input[i] == '+') { *d++ = ' '; *changed = 1; } else { *d++ = input[i]; } count++; i++; } } #if 0 *d = '\0'; #endif return count; } std::string uri_decode(const std::string & sSrc) { // Note from RFC1630: "Sequences which start with a percent // sign but are not followed by two hexadecimal characters // (0-9, A-F) are reserved for future extension" const unsigned char * pSrc = (const unsigned char *)sSrc.c_str(); const int SRC_LEN = sSrc.length(); const unsigned char * const SRC_END = pSrc + SRC_LEN; // last decodable '%' const unsigned char * const SRC_LAST_DEC = SRC_END - 2; char * const pStart = new char[SRC_LEN]; char * pEnd = pStart; while (pSrc < SRC_LAST_DEC) { if (*pSrc == '%') { char dec1, dec2; if (-1 != (dec1 = string::HEX2DEC[*(pSrc + 1)]) && -1 != (dec2 = string::HEX2DEC[*(pSrc + 2)])) { *pEnd++ = (dec1 << 4) + dec2; pSrc += 3; continue; } } *pEnd++ = *pSrc++; } // the last 2- chars while (pSrc < SRC_END) { *pEnd++ = *pSrc++; } std::string sResult(pStart, pEnd); delete [] pStart; return sResult; } } // namespace utils } // namespace modsecurity