-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathdecode.cc
124 lines (103 loc) · 3.29 KB
/
decode.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
* 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 [email protected].
*
*/
#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