Skip to content

Commit 6e4dbcc

Browse files
authored
Merge pull request #172 from polycube-network/pr/add_url_enconding
add url enconding
2 parents 811976d + 6a86e3d commit 6e4dbcc

File tree

6 files changed

+140
-10
lines changed

6 files changed

+140
-10
lines changed

src/polycubectl/cliargs/cliargs.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"fmt"
2121
"strconv"
2222
"strings"
23+
"net/url"
2324

2425
"os"
2526
"bufio"
@@ -304,22 +305,22 @@ func ParseCLIArgs(args []string) (*CLIArgs, error) {
304305
}
305306

306307
func (cli *CLIArgs) buildURL() string {
307-
var url string
308+
var url_str string
308309

309310
for _, str := range cli.PathArgs {
310-
url += str + "/"
311+
url_str += url.PathEscape(str) + "/"
311312
}
312313

313314
if cli.IsHelp {
314315
// TODO: is this check really needed?
315-
if len(url) > 0 {
316-
url = url[:len(url)-1] + cli.getHelpQueryParam()
316+
if len(url_str) > 0 {
317+
url_str = url_str[:len(url_str)-1] + cli.getHelpQueryParam()
317318
} else {
318-
url = cli.getHelpQueryParam()
319+
url_str = cli.getHelpQueryParam()
319320
}
320321
}
321322

322-
return url
323+
return url_str
323324
}
324325

325326
func (cli *CLIArgs) buildBody() []byte {

src/polycubectl/completion/polycubectl.sh

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,26 @@ parse_yaml() {
2525

2626
BASE_URL_="http://localhost:9000/polycube/v1/"
2727

28+
# https://stackoverflow.com/a/10660730
29+
rawurlencode() {
30+
local string="${1}"
31+
local strlen=${#string}
32+
local encoded=""
33+
local pos c o
34+
35+
for (( pos=0 ; pos<strlen ; pos++ )); do
36+
c=${string:$pos:1}
37+
case "$c" in
38+
[-_.~a-zA-Z0-9] ) o="${c}" ;;
39+
* ) printf -v o '%%%02x' "'$c"
40+
esac
41+
encoded+="${o}"
42+
done
43+
echo "${encoded}" # You can either set a return variable (FASTER)
44+
#REPLY="${encoded}" #+or echo the result (EASIER)... or both... :p
45+
#return "${encoded}"
46+
}
47+
2848
_polycubectl_completions() {
2949
if [ -a "$HOME/.config/polycube/polycubectl_config.yaml" ]
3050
then
@@ -78,7 +98,7 @@ _polycubectl_completions() {
7898
fi
7999

80100
#echo $X
81-
URL0+=$X
101+
URL0+=$(rawurlencode $X)
82102
URL0+='/'
83103
done
84104

src/polycubed/src/server/Resources/Endpoint/ListResource.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "PathParamField.h"
2727
#include "Service.h"
2828
#include "rest_server.h"
29+
#include "utils/utils.h"
2930

3031
#include "../Data/Lib/ListResource.h"
3132

@@ -113,8 +114,10 @@ std::vector<Response> ListResource::RequestValidate(
113114
void ListResource::Keys(const Pistache::Rest::Request &request,
114115
ListKeyValues &parsed) const {
115116
for (const auto &k : keys_) {
117+
std::string param_ = request.param(':' + k.Name()).as<std::string>();
118+
std::string param = utils::decode_url(param_);
116119
parsed.push_back(
117-
{k.Name(), k.Type(), request.param(':' + k.Name()).as<std::string>()});
120+
{k.Name(), k.Type(), param});
118121
}
119122
dynamic_cast<const ParentResource *const>(parent_)->Keys(request, parsed);
120123
}
@@ -123,8 +126,10 @@ void ListResource::GetListKeys(const Pistache::Rest::Request &request,
123126
ListKeyValues &parsed) const {
124127
for (const auto &k : keys_) {
125128
if (request.hasParam(':' + k.Name())) {
129+
std::string param_ = request.param(':' + k.Name()).as<std::string>();
130+
std::string param = utils::decode_url(param_);
126131
parsed.push_back(
127-
{k.Name(), k.Type(), request.param(':' + k.Name()).as<std::string>()});
132+
{k.Name(), k.Type(), param});
128133
}
129134
}
130135
}

src/polycubed/src/server/Resources/Endpoint/PathParamField.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include <memory>
1919
#include <vector>
2020

21+
#include "utils/utils.h"
22+
2123
#include "../../Validators/EmptyValidator.h"
2224
#include "../../Validators/ValueValidator.h"
2325

@@ -41,7 +43,7 @@ const std::string &PathParamField::Name() const {
4143
ErrorTag PathParamField::Validate(const Pistache::Rest::Request &value) const {
4244
if (!value.hasParam(name_))
4345
return kMissingElement;
44-
const auto &param = value.param(name_).as<std::string>();
46+
const auto &param = utils::decode_url(value.param(name_).as<std::string>());
4547
for (const auto &validator : validators_) {
4648
if (!validator->Validate(param))
4749
return ErrorTag::kBadElement;

src/polycubed/src/utils/utils.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,107 @@ std::map<std::string, json> strip_port_tcubes(json &jcube) {
9292
return cubes;
9393
}
9494

95+
// taken from pistache
96+
inline size_t to_utf8(int code, char *buff) {
97+
if (code < 0x0080) {
98+
buff[0] = (code & 0x7F);
99+
return 1;
100+
} else if (code < 0x0800) {
101+
buff[0] = (0xC0 | ((code >> 6) & 0x1F));
102+
buff[1] = (0x80 | (code & 0x3F));
103+
return 2;
104+
} else if (code < 0xD800) {
105+
buff[0] = (0xE0 | ((code >> 12) & 0xF));
106+
buff[1] = (0x80 | ((code >> 6) & 0x3F));
107+
buff[2] = (0x80 | (code & 0x3F));
108+
return 3;
109+
} else if (code < 0xE000) { // D800 - DFFF is invalid...
110+
return 0;
111+
} else if (code < 0x10000) {
112+
buff[0] = (0xE0 | ((code >> 12) & 0xF));
113+
buff[1] = (0x80 | ((code >> 6) & 0x3F));
114+
buff[2] = (0x80 | (code & 0x3F));
115+
return 3;
116+
} else if (code < 0x110000) {
117+
buff[0] = (0xF0 | ((code >> 18) & 0x7));
118+
buff[1] = (0x80 | ((code >> 12) & 0x3F));
119+
buff[2] = (0x80 | ((code >> 6) & 0x3F));
120+
buff[3] = (0x80 | (code & 0x3F));
121+
return 4;
122+
}
123+
124+
// NOTREACHED
125+
return 0;
126+
}
127+
128+
inline bool is_hex(char c, int &v) {
129+
if (0x20 <= c && isdigit(c)) {
130+
v = c - '0';
131+
return true;
132+
} else if ('A' <= c && c <= 'F') {
133+
v = c - 'A' + 10;
134+
return true;
135+
} else if ('a' <= c && c <= 'f') {
136+
v = c - 'a' + 10;
137+
return true;
138+
}
139+
return false;
140+
}
141+
142+
inline bool from_hex_to_i(const std::string &s, int i, int cnt, int &val) {
143+
val = 0;
144+
for (; cnt; i++, cnt--) {
145+
if (!s[i]) {
146+
return false;
147+
}
148+
int v = 0;
149+
if (is_hex(s[i], v)) {
150+
val = val * 16 + v;
151+
} else {
152+
return false;
153+
}
154+
}
155+
return true;
156+
}
157+
158+
std::string decode_url(const std::string &s) {
159+
std::string result;
160+
161+
for (int i = 0; s[i]; i++) {
162+
if (s[i] == '%') {
163+
if (s[i + 1] && s[i + 1] == 'u') {
164+
int val = 0;
165+
if (from_hex_to_i(s, i + 2, 4, val)) {
166+
// 4 digits Unicode codes
167+
char buff[4];
168+
size_t len = to_utf8(val, buff);
169+
if (len > 0) {
170+
result.append(buff, len);
171+
}
172+
i += 5; // 'u0000'
173+
} else {
174+
result += s[i];
175+
}
176+
} else {
177+
int val = 0;
178+
if (from_hex_to_i(s, i + 1, 2, val)) {
179+
// 2 digits hex codes
180+
result += val;
181+
i += 2; // '00'
182+
} else {
183+
result += s[i];
184+
}
185+
}
186+
} else if (s[i] == '+') {
187+
result += ' ';
188+
} else {
189+
result += s[i];
190+
}
191+
}
192+
193+
return result;
194+
}
195+
95196
} // namespace utils
96197
} // namespace polycubed
97198
} // namespace polycube

src/polycubed/src/utils/utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ namespace utils {
2727
bool check_kernel_version(const std::string &version);
2828
std::map<std::string, std::string> strip_port_peers(json &cubes);
2929
std::map<std::string, json> strip_port_tcubes(json &jcube);
30+
std::string decode_url(const std::string &url);
3031

3132
} // namespace utils
3233
} // namespace polycubed

0 commit comments

Comments
 (0)