----------------------------------------------------------------------------- Purpose: Internal implementation of encode, works in the strict RFC manner, or with spaces turned to + like HTML form encoding. -----------------------------------------------------------------------------
| 350 | // with spaces turned to + like HTML form encoding. |
| 351 | //----------------------------------------------------------------------------- |
| 352 | void V_URLEncodeInternal( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen, |
| 353 | bool bUsePlusForSpace, std::function< bool(const char)> fnNeedsEscape ) |
| 354 | { |
| 355 | //AssertMsg( nDestLen > 3*nSourceLen, "Target buffer for V_URLEncode should be 3x source length, plus one for terminating null\n" ); |
| 356 | |
| 357 | int iDestPos = 0; |
| 358 | for ( int i=0; i < nSourceLen; ++i ) |
| 359 | { |
| 360 | // worst case we need 3 additional chars |
| 361 | if( (iDestPos+3) > nDestLen ) |
| 362 | { |
| 363 | pchDest[0] = '\0'; |
| 364 | // AssertMsg( false, "Target buffer too short\n" ); |
| 365 | return; |
| 366 | } |
| 367 | |
| 368 | // We allow only a-z, A-Z, 0-9, period, underscore, and hyphen to pass through unescaped. |
| 369 | // These are the characters allowed by both the original RFC 1738 and the latest RFC 3986. |
| 370 | // Current specs also allow '~', but that is forbidden under original RFC 1738. |
| 371 | if ( fnNeedsEscape( pchSource[i] ) ) |
| 372 | { |
| 373 | if ( bUsePlusForSpace && pchSource[i] == ' ' ) |
| 374 | { |
| 375 | pchDest[iDestPos++] = '+'; |
| 376 | } |
| 377 | else |
| 378 | { |
| 379 | pchDest[iDestPos++] = '%'; |
| 380 | uint8_t iValue = pchSource[i]; |
| 381 | if ( iValue == 0 ) |
| 382 | { |
| 383 | pchDest[iDestPos++] = '0'; |
| 384 | pchDest[iDestPos++] = '0'; |
| 385 | } |
| 386 | else |
| 387 | { |
| 388 | char cHexDigit1 = cIntToHexDigit( iValue % 16 ); |
| 389 | iValue /= 16; |
| 390 | char cHexDigit2 = cIntToHexDigit( iValue ); |
| 391 | pchDest[iDestPos++] = cHexDigit2; |
| 392 | pchDest[iDestPos++] = cHexDigit1; |
| 393 | } |
| 394 | } |
| 395 | } |
| 396 | else |
| 397 | { |
| 398 | pchDest[iDestPos++] = pchSource[i]; |
| 399 | } |
| 400 | } |
| 401 | |
| 402 | if( (iDestPos+1) > nDestLen ) |
| 403 | { |
| 404 | pchDest[0] = '\0'; |
| 405 | //AssertMsg( false, "Target buffer too short to terminate\n" ); |
| 406 | return; |
| 407 | } |
| 408 | |
| 409 | // Null terminate |
no test coverage detected