Skip to content

Commit 15a16b9

Browse files
committed
Added url encoder/decoder
Bugfix in cookie parser
1 parent b97dd5d commit 15a16b9

File tree

7 files changed

+113
-28
lines changed

7 files changed

+113
-28
lines changed

httpserver.userprefs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<Properties>
2-
<MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" />
3-
<MonoDevelop.Ide.Workbench ActiveDocument="httpserver/Utils.h">
2+
<MonoDevelop.Ide.Workspace ActiveConfiguration="Release" />
3+
<MonoDevelop.Ide.Workbench ActiveDocument="httpserver/DataVariantTextPlain.cpp">
44
<Files>
5-
<File FileName="httpserver/Server.cpp" Line="1" Column="1" />
6-
<File FileName="httpserver/Server.h" Line="1" Column="1" />
5+
<File FileName="httpserver/Server.cpp" Line="382" Column="27" />
6+
<File FileName="httpserver/Server.h" Line="20" Column="14" />
77
<File FileName="httpserver/Main.cpp" Line="1" Column="1" />
88
<File FileName="httpserver/Main.h" Line="1" Column="1" />
99
<File FileName="httpserver/DataVariantMultipartFormData.h" Line="1" Column="1" />
@@ -13,21 +13,21 @@
1313
<File FileName="httpserver/Event.cpp" Line="1" Column="1" />
1414
<File FileName="httpserver/DataVariantAbstract.h" Line="1" Column="1" />
1515
<File FileName="httpserver/DataVariantFormUrlencoded.h" Line="1" Column="1" />
16-
<File FileName="httpserver/DataVariantFormUrlencoded.cpp" Line="1" Column="1" />
16+
<File FileName="httpserver/DataVariantFormUrlencoded.cpp" Line="41" Column="5" />
1717
<File FileName="httpserver/ServerApplicationSettings.h" Line="1" Column="1" />
1818
<File FileName="httpserver/ServerApplicationsTree.h" Line="1" Column="1" />
1919
<File FileName="httpserver/ServerApplicationsTree.cpp" Line="1" Column="1" />
2020
<File FileName="httpserver/Module.h" Line="1" Column="1" />
2121
<File FileName="httpserver/Event.h" Line="1" Column="1" />
2222
<File FileName="httpserver/System.h" Line="1" Column="1" />
2323
<File FileName="httpserver/DataVariantTextPlain.h" Line="1" Column="1" />
24-
<File FileName="httpserver/DataVariantTextPlain.cpp" Line="1" Column="1" />
24+
<File FileName="httpserver/DataVariantTextPlain.cpp" Line="33" Column="6" />
2525
<File FileName="httpserver/SignalsHandles.cpp" Line="1" Column="1" />
2626
<File FileName="httpserver/SignalsHandles.h" Line="1" Column="1" />
2727
<File FileName="httpserver/System.cpp" Line="1" Column="1" />
28-
<File FileName="httpserver/Socket.cpp" Line="18" Column="2" />
29-
<File FileName="httpserver/Utils.h" Line="35" Column="46" />
30-
<File FileName="httpserver/Utils.cpp" Line="287" Column="18" />
28+
<File FileName="httpserver/Socket.cpp" Line="1" Column="1" />
29+
<File FileName="httpserver/Utils.h" Line="1" Column="1" />
30+
<File FileName="httpserver/Utils.cpp" Line="320" Column="3" />
3131
<File FileName="httpserver/Socket.h" Line="1" Column="1" />
3232
<File FileName="httpserver/FileIncoming.h" Line="1" Column="1" />
3333
<File FileName="httpserver/RawData.h" Line="1" Column="1" />

httpserver/DataVariantFormUrlencoded.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11

22
#include "DataVariantFormUrlencoded.h"
33

4+
#include "Utils.h"
5+
46
namespace HttpServer
57
{
68
DataVariantFormUrlencoded::DataVariantFormUrlencoded()
@@ -44,11 +46,11 @@ namespace HttpServer
4446
// Если последний параметр
4547
if (std::string::npos == var_end)
4648
{
47-
var_value = str.substr(delimiter);
49+
var_value = Utils::urlDecode(str.substr(delimiter) );
4850
}
4951
else // Если не последний параметр
5052
{
51-
var_value = str.substr(delimiter, var_end - delimiter);
53+
var_value = Utils::urlDecode(str.substr(delimiter, var_end - delimiter) );
5254
}
5355

5456
// Сохранить параметр и значение

httpserver/FileIncoming.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,8 @@ namespace HttpServer
1818
}
1919

2020
FileIncoming::FileIncoming(FileIncoming &&file)
21-
: file_name(file.file_name), file_type(file.file_type), file_size(file.file_size)
21+
: file_name(std::move(file.file_name) ), file_type(std::move(file.file_type) ), file_size(file.file_size)
2222
{
23-
file.file_name.clear();
24-
file.file_type.clear();
2523
file.file_size = 0;
2624
}
2725

httpserver/Server.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -357,25 +357,25 @@ namespace HttpServer
357357
/**
358358
* Парсинг переданных параметров (URI)
359359
*/
360-
bool Server::parseIncomingVars(std::unordered_multimap<std::string, std::string> &map, const std::string &str, const size_t start, const size_t end) const
360+
bool Server::parseIncomingVars(std::unordered_multimap<std::string, std::string> &map, const std::string &uriParams) const
361361
{
362-
if (str.length() > start)
362+
if (uriParams.length() )
363363
{
364-
for (size_t var_pos = start, var_end; std::string::npos != var_pos; var_pos = var_end)
364+
for (size_t var_pos = 0, var_end; std::string::npos != var_pos; var_pos = var_end)
365365
{
366366
// Поиск следующего параметра
367-
var_end = str.find('&', var_pos);
367+
var_end = uriParams.find('&', var_pos);
368368

369369
// Поиск значения параметра
370-
size_t delimiter = str.find('=', var_pos);
370+
size_t delimiter = uriParams.find('=', var_pos);
371371

372372
if (std::string::npos == delimiter || delimiter > var_end)
373373
{
374374
return false;
375375
}
376376

377377
// Получить имя параметра
378-
std::string var_name = str.substr(var_pos, delimiter - var_pos);
378+
std::string var_name = uriParams.substr(var_pos, delimiter - var_pos);
379379

380380
++delimiter;
381381

@@ -384,11 +384,11 @@ namespace HttpServer
384384
// Если последний параметр
385385
if (std::string::npos == var_end)
386386
{
387-
var_value = str.substr(delimiter, end - delimiter);
387+
var_value = Utils::urlDecode(uriParams.substr(delimiter) );
388388
}
389389
else // Если не последний параметр
390390
{
391-
var_value = str.substr(delimiter, var_end - delimiter);
391+
var_value = Utils::urlDecode(uriParams.substr(delimiter, var_end - delimiter) );
392392
}
393393

394394
// Сохранить параметр и значение
@@ -530,13 +530,13 @@ namespace HttpServer
530530
// Поиск именованных параметров запросов (переменных ?)
531531
size_t params_pos = str_buf.find('?', delimiter);
532532

533-
// Сохранить полную ссылку URI (с параметрами)
533+
// Сохранить полную ссылку URI (без параметров)
534534
uri_reference = (std::string::npos == params_pos) ? str_buf.substr(delimiter) : str_buf.substr(delimiter, params_pos - delimiter);
535535

536536
if (std::string::npos != params_pos)
537537
{
538538
// Извлекаем параметры запроса из URI
539-
if (false == parseIncomingVars(incoming_params, str_buf, params_pos + 1, uri_end) )
539+
if (false == parseIncomingVars(incoming_params, str_buf.substr(params_pos + 1, uri_end) ) )
540540
{
541541
// HTTP 400 Bad Request
542542
sendStatus(clientSocket, timeout, 400);

httpserver/Server.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ namespace HttpServer
4545
int threadRequestProc(Socket) const;
4646
int transferFilePart(const Socket &, const std::chrono::milliseconds &, const std::string &, const time_t, const size_t, const std::string &, const std::string &, const std::string &, const bool) const;
4747
int transferFile(const Socket &, const std::chrono::milliseconds &, const std::string &, const std::unordered_map<std::string, std::string> &, const std::map<std::string, std::string> &, const std::string &, const bool) const;
48-
bool parseIncomingVars(std::unordered_multimap<std::string, std::string> &, const std::string &, const size_t, const size_t) const;
48+
bool parseIncomingVars(std::unordered_multimap<std::string, std::string> &, const std::string &) const;
4949

5050
bool includeConfigFile(const std::string &, std::string &, const size_t);
5151
bool loadConfig();

httpserver/Utils.cpp

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "Utils.h"
33

44
#include <cstring>
5+
#include <iomanip>
56

67
namespace Utils
78
{
@@ -224,7 +225,7 @@ namespace Utils
224225

225226
::time_t cur_time = tTime;
226227

227-
if (std::numeric_limits<::time_t>::max() == tTime)
228+
if ( (time_t)~0 == tTime)
228229
{
229230
::time(&cur_time);
230231
}
@@ -278,7 +279,7 @@ namespace Utils
278279

279280
for (size_t cur_pos = 0, next_value; std::string::npos != cur_pos; cur_pos = next_value)
280281
{
281-
next_value = cookieHeader.find(' ', cur_pos);
282+
next_value = cookieHeader.find(';', cur_pos);
282283

283284
size_t delimiter = cookieHeader.find('=', cur_pos);
284285

@@ -289,11 +290,13 @@ namespace Utils
289290

290291
std::string key = cookieHeader.substr(cur_pos, delimiter - cur_pos);
291292
trim(key);
293+
key = urlDecode(key);
292294

293295
++delimiter;
294296

295297
std::string value = cookieHeader.substr(delimiter, std::string::npos != next_value ? next_value - delimiter : next_value);
296298
trim(value);
299+
value = urlDecode(value);
297300

298301
cookies.emplace(std::move(key), std::move(value) );
299302

@@ -305,4 +308,83 @@ namespace Utils
305308

306309
return true;
307310
}
311+
312+
inline bool isUrlAllowed(const std::string::value_type c)
313+
{
314+
static const std::string special("-_.~");
315+
316+
return std::string::npos != special.find(c);
317+
}
318+
319+
std::string urlEncode(const std::string &str)
320+
{
321+
std::ostringstream encoded;
322+
encoded.fill('0');
323+
encoded << std::hex;
324+
325+
for (auto it = str.cbegin(); str.cend() != it; ++it)
326+
{
327+
const std::string::value_type &c = *it;
328+
329+
if (' ' == c)
330+
{
331+
encoded << '+';
332+
}
333+
else if (std::isalnum(c) || isUrlAllowed(c) )
334+
{
335+
encoded << c;
336+
}
337+
else
338+
{
339+
encoded << '%' << std::setw(2) << (int) ( (unsigned char) c);
340+
}
341+
}
342+
343+
return encoded.str();
344+
}
345+
346+
std::string urlDecode(const std::string &str)
347+
{
348+
std::string decoded;
349+
350+
std::string::value_type ch[3] = {0};
351+
352+
for (auto it = str.cbegin(); str.cend() != it; ++it)
353+
{
354+
const std::string::value_type &c = *it;
355+
356+
if ('%' == c)
357+
{
358+
++it;
359+
360+
if (str.cend() == it)
361+
{
362+
break;
363+
}
364+
365+
ch[0] = *it;
366+
367+
++it;
368+
369+
if (str.cend() == it)
370+
{
371+
break;
372+
}
373+
374+
ch[1] = *it;
375+
376+
decoded.push_back(strtoul(ch, nullptr, 16) );
377+
}
378+
else if ('+' == c)
379+
{
380+
decoded.push_back(' ');
381+
}
382+
else
383+
{
384+
decoded.push_back(c);
385+
}
386+
}
387+
388+
return decoded;
389+
}
308390
};

httpserver/Utils.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,12 @@ namespace Utils
4949

5050
time_t stringTimeToTimestamp(const std::string &);
5151

52-
std::string getDatetimeStringValue(const ::time_t = std::numeric_limits<::time_t>::max(), const bool = false);
52+
std::string getDatetimeStringValue(const ::time_t tTime = ~0, const bool isGmtTime = false);
5353

5454
size_t getNumberLength(const size_t number);
5555

5656
bool parseCookies(const std::string &, std::unordered_multimap<std::string, std::string> &);
57+
58+
std::string urlEncode(const std::string &);
59+
std::string urlDecode(const std::string &);
5760
};

0 commit comments

Comments
 (0)