The LLURI::buildHTTP() overloads that take an LLSD 'path' accept 'undefined',
LLSD::String and (LLSD::Array of LLSD::String). A sequence of path components
passed in an Array is constructed into a slash-separated path. There are unit
tests in lluri_test.cpp to exercise that case.
To my amazement, there were NO unit tests covering the case of an LLSD::String
path. The code for that case escaped and appended the entire passed string.
While that might be fine for a 'path' consisting of a single undecorated path
component, the available documentation does not forbid one from passing a path
containing slashes as well. But this had the dubious effect of replacing every
slash with %2F.
In particular, decomposing a URL string with one LLURI instance and
constructing another like it using LLURI::buildHTTP() was not symmetrical.
Having consulted with Richard, I made the string-path logic a bit more nuanced:
- The passed path string is split on slashes. Every path component is
individually escaped, then recombined with slashes into the final path.
- Duplicate slashes are eliminated.
- The presence or absence of a trailing slash in the original path string is
carefully respected.
Now that we've nailed down how it ought to behave -- added unit tests to
ensure that it DOES behave that way!!
(1) the LLLand class had to be forward declared in a cpp file that did not include llland.h
(2) ensure_equals(const char*, type, type) requires that type have an operator!=(type, type) defined.
(3) ensure_equals(const char*, type, type) is so overloaded that the compiler can have trouble picking the right version when it has to implicitly cast a std::string to "const char*" AND multiple valid casts exist for type --> S32, F32, etc. To solve this problem we must explicitly pass in a "const char*" instead of a std::string.
Reviewed with CG