summaryrefslogtreecommitdiff
path: root/indra/llcommon/lluri.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/lluri.cpp')
-rw-r--r--indra/llcommon/lluri.cpp83
1 files changed, 65 insertions, 18 deletions
diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp
index deeee3173d..0f6ddd9bc6 100644
--- a/indra/llcommon/lluri.cpp
+++ b/indra/llcommon/lluri.cpp
@@ -43,28 +43,68 @@
// system includes
#include <boost/tokenizer.hpp>
+void encode_character(std::ostream& ostr, std::string::value_type val)
+{
+ ostr << "%" << std::uppercase << std::hex << std::setw(2) << std::setfill('0')
+ // VWR-4010 Cannot cast to U32 because sign-extension on
+ // chars > 128 will result in FFFFFFC3 instead of F3.
+ << static_cast<S32>(static_cast<U8>(c));
+}
+
// static
-std::string LLURI::escape(const std::string& str, const std::string & allowed)
+std::string LLURI::escape(
+ const std::string& str,
+ const std::string& allowed,
+ bool is_allowed_sorted)
{
- std::ostringstream ostr;
+ // *NOTE: This size determination feels like a good value to
+ // me. If someone wante to come up with a more precise heuristic
+ // with some data to back up the assertion that 'sort is good'
+ // then feel free to change this test a bit.
+ if(!is_allowed_sorted && (str.size() > 2 * allowed.size()))
+ {
+ // if it's already sorted, or if the url is quite long, we
+ // want to optimize this process.
+ std::string sorted_allowed(allowed);
+ std::sort(sorted_allowed.begin(), sorted_allowed.end());
+ return escape(str, sorted_allowed, true);
+ }
+ std::ostringstream ostr;
std::string::const_iterator it = str.begin();
std::string::const_iterator end = str.end();
- for(; it != end; ++it)
+ std::string::value_type c;
+ if(is_allowed_sorted)
{
- std::string::value_type c = *it;
- if(allowed.find(c) == std::string::npos)
- {
- ostr << "%"
- << std::uppercase << std::hex << std::setw(2) << std::setfill('0')
- // VWR-4010 Cannot cast to U32 because sign-extension on
- // chars > 128 will result in FFFFFFC3 instead of F3.
- << static_cast<S32>(static_cast<U8>(c));
- }
- else
- {
- ostr << c;
- }
+ std::string::const_iterator allowed_begin(allowed.begin());
+ std::string::const_iterator allowed_end(allowed.end());
+ for(; it != end; ++it)
+ {
+ c = *it;
+ if(std::binary_search(allowed_begin, allowed_end, c))
+ {
+ ostr << c;
+ }
+ else
+ {
+ encode_character(ostr, c);
+ }
+ }
+ }
+ else
+ {
+ for(; it != end; ++it)
+ {
+ c = *it;
+ if(allowed.find(c) == std::string::npos)
+ {
+ encode_character(ostr, c);
+ }
+ else
+ {
+ ostr << c;
+ }
+ }
}
return ostr.str();
}
@@ -121,11 +161,18 @@ namespace
{ return LLURI::escape(s, unreserved() + ":@!$'()*+,="); } // sub_delims - "&;" + ":@"
}
-// TODO: USE CURL!! After http textures gets merged everywhere.
+// *TODO: Consider using curl. After http textures gets merged everywhere.
// static
std::string LLURI::escape(const std::string& str)
{
- return escape(str,unreserved() + ":@!$'()*+,=");
+ static std::string default_allowed(unreserved() + ":@!$'()*+,=/?&#;");
+ static bool initialized = false;
+ if(!initialized)
+ {
+ std::sort(default_allowed.begin(), default_allowed.end());
+ initialized = true;
+ }
+ return escape(str, default_allowed, true);
}
LLURI::LLURI()