@@ -2369,24 +2369,49 @@ ResponseCode CResource::HandleRequest(HttpRequest* ipoHttpRequest, HttpResponse*
2369
2369
return HTTPRESPONSECODE_200_OK;
2370
2370
}
2371
2371
2372
- void Unescape (std::string& str )
2372
+ std::string Unescape (std::string_view sv )
2373
2373
{
2374
- const char * pPercent = strchr (str.c_str (), ' %' );
2374
+ // Converts a character to a hexadecimal value
2375
+ auto toHex = [](char c)
2376
+ {
2377
+ if (c >= ' 0' && c <= ' 9' )
2378
+ return c - ' 0' ;
2379
+ if (c >= ' a' && c <= ' f' )
2380
+ return c - ' a' + 10 ;
2381
+ if (c >= ' A' && c <= ' F' )
2382
+ return c - ' A' + 10 ;
2383
+ return 0 ;
2384
+ };
2375
2385
2376
- while (pPercent)
2386
+ std::string out;
2387
+ // String can only shrink here
2388
+ // as %?? is collapsed to a single char
2389
+ out.reserve (sv.length ());
2390
+ auto it = sv.begin ();
2391
+ while (it != sv.end ())
2377
2392
{
2378
- if (pPercent[ 1 ] && pPercent[ 2 ] )
2393
+ if (*it == ' % ' )
2379
2394
{
2380
- int iCharCode = 0 ;
2381
- sscanf (&pPercent[1 ], " %02X" , &iCharCode);
2382
- str.replace (pPercent - str.c_str (), 3 , (char *)&iCharCode);
2383
- pPercent = strchr (pPercent + 3 , ' %' );
2395
+ // Avoid reading past the end
2396
+ if (std::distance (it, sv.end ()) < 3 )
2397
+ {
2398
+ out.push_back (*it++);
2399
+ continue ;
2400
+ }
2401
+ // Skip %
2402
+ ++it;
2403
+ // Read two digits/letters and convert to char
2404
+ uint8_t digit1 = toHex (*it++);
2405
+ uint8_t digit2 = toHex (*it++);
2406
+ out.push_back (static_cast <char >(digit1 * 0x10 + digit2));
2384
2407
}
2385
2408
else
2386
2409
{
2387
- break ;
2410
+ // Push normally
2411
+ out.push_back (*it++);
2388
2412
}
2389
2413
}
2414
+ return out;
2390
2415
}
2391
2416
2392
2417
ResponseCode CResource::HandleRequestCall (HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse, CAccount* pAccount)
@@ -2447,7 +2472,7 @@ ResponseCode CResource::HandleRequestCall(HttpRequest* ipoHttpRequest, HttpRespo
2447
2472
if (iKey >= 0 && iKey < MAX_INPUT_VARIABLES)
2448
2473
{
2449
2474
std::string strValue (pEqual + 1 , pAnd - (pEqual + 1 ));
2450
- Unescape (strValue);
2475
+ strValue = Unescape (strValue);
2451
2476
2452
2477
if (iKey + 1 > static_cast <int >(vecArguments.size ()))
2453
2478
vecArguments.resize (iKey + 1 );
@@ -2463,7 +2488,7 @@ ResponseCode CResource::HandleRequestCall(HttpRequest* ipoHttpRequest, HttpRespo
2463
2488
}
2464
2489
}
2465
2490
2466
- Unescape (strFuncName);
2491
+ strFuncName = Unescape (strFuncName);
2467
2492
2468
2493
for (CExportedFunction& Exported : m_ExportedFunctions)
2469
2494
{
@@ -2673,6 +2698,7 @@ ResponseCode CResource::HandleRequestActive(HttpRequest* ipoHttpRequest, HttpRes
2673
2698
}
2674
2699
2675
2700
Unescape (strFile);
2701
+ strFile = Unescape (strFile);
2676
2702
2677
2703
for (CResourceFile* pResourceFile : m_ResourceFiles)
2678
2704
{
0 commit comments