mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-17 22:56:18 +03:00
125 lines
3.3 KiB
C++
125 lines
3.3 KiB
C++
/*
|
|
* 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 ((char)-1 != (dec1 = string::HEX2DEC[*(pSrc + 1)])
|
|
&& (char)-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
|