Merge STORM-796
commit
fa9cbe50fa
|
|
@ -805,6 +805,69 @@ std::string LLUrlEntryPlace::getLocation(const std::string &url) const
|
|||
return ::getStringAfterToken(url, "://");
|
||||
}
|
||||
|
||||
//
|
||||
// LLUrlEntryRegion Describes secondlife:///app/region/REGION_NAME/X/Y/Z URLs, e.g.
|
||||
// secondlife:///app/region/Ahern/128/128/0
|
||||
//
|
||||
LLUrlEntryRegion::LLUrlEntryRegion()
|
||||
{
|
||||
mPattern = boost::regex("secondlife:///app/region/[^/\\s]+(/\\d+)?(/\\d+)?(/\\d+)?/?",
|
||||
boost::regex::perl|boost::regex::icase);
|
||||
mMenuName = "menu_url_slurl.xml";
|
||||
mTooltip = LLTrans::getString("TooltipSLURL");
|
||||
}
|
||||
|
||||
std::string LLUrlEntryRegion::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
|
||||
{
|
||||
//
|
||||
// we handle SLURLs in the following formats:
|
||||
// - secondlife:///app/region/Place/X/Y/Z
|
||||
// - secondlife:///app/region/Place/X/Y
|
||||
// - secondlife:///app/region/Place/X
|
||||
// - secondlife:///app/region/Place
|
||||
//
|
||||
|
||||
LLSD path_array = LLURI(url).pathArray();
|
||||
S32 path_parts = path_array.size();
|
||||
|
||||
if (path_parts < 3) // no region name
|
||||
{
|
||||
llwarns << "Failed to parse url [" << url << "]" << llendl;
|
||||
return url;
|
||||
}
|
||||
|
||||
std::string label = unescapeUrl(path_array[2]); // region name
|
||||
|
||||
if (path_parts > 3) // secondlife:///app/region/Place/X
|
||||
{
|
||||
std::string x = path_array[3];
|
||||
label += " (" + x;
|
||||
|
||||
if (path_parts > 4) // secondlife:///app/region/Place/X/Y
|
||||
{
|
||||
std::string y = path_array[4];
|
||||
label += "," + y;
|
||||
|
||||
if (path_parts > 5) // secondlife:///app/region/Place/X/Y/Z
|
||||
{
|
||||
std::string z = path_array[5];
|
||||
label = label + "," + z;
|
||||
}
|
||||
}
|
||||
|
||||
label += ")";
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
std::string LLUrlEntryRegion::getLocation(const std::string &url) const
|
||||
{
|
||||
LLSD path_array = LLURI(url).pathArray();
|
||||
std::string region_name = unescapeUrl(path_array[2]);
|
||||
return region_name;
|
||||
}
|
||||
|
||||
//
|
||||
// LLUrlEntryTeleport Describes a Second Life teleport Url, e.g.,
|
||||
// secondlife:///app/teleport/Ahern/50/50/50/
|
||||
|
|
|
|||
|
|
@ -301,6 +301,18 @@ public:
|
|||
/*virtual*/ std::string getLocation(const std::string &url) const;
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryRegion Describes a Second Life location Url, e.g.,
|
||||
/// secondlife:///app/region/Ahern/128/128/0
|
||||
///
|
||||
class LLUrlEntryRegion : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryRegion();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
/*virtual*/ std::string getLocation(const std::string &url) const;
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryTeleport Describes a Second Life teleport Url, e.g.,
|
||||
/// secondlife:///app/teleport/Ahern/50/50/50/
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ LLUrlRegistry::LLUrlRegistry()
|
|||
registerUrl(new LLUrlEntryGroup());
|
||||
registerUrl(new LLUrlEntryParcel());
|
||||
registerUrl(new LLUrlEntryTeleport());
|
||||
registerUrl(new LLUrlEntryRegion());
|
||||
registerUrl(new LLUrlEntryWorldMap());
|
||||
registerUrl(new LLUrlEntryObjectIM());
|
||||
registerUrl(new LLUrlEntryPlace());
|
||||
|
|
|
|||
|
|
@ -103,6 +103,45 @@ namespace tut
|
|||
ensure_equals(testname, url, expected);
|
||||
}
|
||||
|
||||
void dummyCallback(const std::string &url, const std::string &label, const std::string& icon)
|
||||
{
|
||||
}
|
||||
|
||||
void testLabel(const std::string &testname, LLUrlEntryBase &entry,
|
||||
const char *text, const std::string &expected)
|
||||
{
|
||||
boost::regex regex = entry.getPattern();
|
||||
std::string label = "";
|
||||
boost::cmatch result;
|
||||
bool found = boost::regex_search(text, result, regex);
|
||||
if (found)
|
||||
{
|
||||
S32 start = static_cast<U32>(result[0].first - text);
|
||||
S32 end = static_cast<U32>(result[0].second - text);
|
||||
std::string url = std::string(text+start, end-start);
|
||||
label = entry.getLabel(url, boost::bind(dummyCallback, _1, _2, _3));
|
||||
}
|
||||
ensure_equals(testname, label, expected);
|
||||
}
|
||||
|
||||
void testLocation(const std::string &testname, LLUrlEntryBase &entry,
|
||||
const char *text, const std::string &expected)
|
||||
{
|
||||
boost::regex regex = entry.getPattern();
|
||||
std::string location = "";
|
||||
boost::cmatch result;
|
||||
bool found = boost::regex_search(text, result, regex);
|
||||
if (found)
|
||||
{
|
||||
S32 start = static_cast<U32>(result[0].first - text);
|
||||
S32 end = static_cast<U32>(result[0].second - text);
|
||||
std::string url = std::string(text+start, end-start);
|
||||
location = entry.getLocation(url);
|
||||
}
|
||||
ensure_equals(testname, location, expected);
|
||||
}
|
||||
|
||||
|
||||
template<> template<>
|
||||
void object::test<1>()
|
||||
{
|
||||
|
|
@ -697,4 +736,114 @@ namespace tut
|
|||
"<nolink>My Object</nolink>",
|
||||
"My Object");
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<13>()
|
||||
{
|
||||
//
|
||||
// test LLUrlEntryRegion - secondlife:///app/region/<location> URLs
|
||||
//
|
||||
LLUrlEntryRegion url;
|
||||
|
||||
// Regex tests.
|
||||
testRegex("no valid region", url,
|
||||
"secondlife:///app/region/",
|
||||
"");
|
||||
|
||||
testRegex("invalid coords", url,
|
||||
"secondlife:///app/region/Korea2/a/b/c",
|
||||
"secondlife:///app/region/Korea2/"); // don't count invalid coords
|
||||
|
||||
testRegex("Ahern (50,50,50) [1]", url,
|
||||
"secondlife:///app/region/Ahern/50/50/50/",
|
||||
"secondlife:///app/region/Ahern/50/50/50/");
|
||||
|
||||
testRegex("Ahern (50,50,50) [2]", url,
|
||||
"XXX secondlife:///app/region/Ahern/50/50/50/ XXX",
|
||||
"secondlife:///app/region/Ahern/50/50/50/");
|
||||
|
||||
testRegex("Ahern (50,50,50) [3]", url,
|
||||
"XXX secondlife:///app/region/Ahern/50/50/50 XXX",
|
||||
"secondlife:///app/region/Ahern/50/50/50");
|
||||
|
||||
testRegex("Ahern (50,50,50) multicase", url,
|
||||
"XXX secondlife:///app/region/Ahern/50/50/50/ XXX",
|
||||
"secondlife:///app/region/Ahern/50/50/50/");
|
||||
|
||||
testRegex("Ahern (50,50) [1]", url,
|
||||
"XXX secondlife:///app/region/Ahern/50/50/ XXX",
|
||||
"secondlife:///app/region/Ahern/50/50/");
|
||||
|
||||
testRegex("Ahern (50,50) [2]", url,
|
||||
"XXX secondlife:///app/region/Ahern/50/50 XXX",
|
||||
"secondlife:///app/region/Ahern/50/50");
|
||||
|
||||
// DEV-21577: In-world SLURLs containing "(" or ")" are not treated as a hyperlink in chat
|
||||
testRegex("Region with brackets", url,
|
||||
"XXX secondlife:///app/region/Burning%20Life%20(Hyper)/27/210/30 XXX",
|
||||
"secondlife:///app/region/Burning%20Life%20(Hyper)/27/210/30");
|
||||
|
||||
// DEV-35459: SLURLs and teleport Links not parsed properly
|
||||
testRegex("Region with quote", url,
|
||||
"XXX secondlife:///app/region/A'ksha%20Oasis/41/166/701 XXX",
|
||||
"secondlife:///app/region/A%27ksha%20Oasis/41/166/701");
|
||||
|
||||
// Rendering tests.
|
||||
testLabel("Render /app/region/Ahern/50/50/50/", url,
|
||||
"secondlife:///app/region/Ahern/50/50/50/",
|
||||
"Ahern (50,50,50)");
|
||||
|
||||
testLabel("Render /app/region/Ahern/50/50/50", url,
|
||||
"secondlife:///app/region/Ahern/50/50/50",
|
||||
"Ahern (50,50,50)");
|
||||
|
||||
testLabel("Render /app/region/Ahern/50/50/", url,
|
||||
"secondlife:///app/region/Ahern/50/50/",
|
||||
"Ahern (50,50)");
|
||||
|
||||
testLabel("Render /app/region/Ahern/50/50", url,
|
||||
"secondlife:///app/region/Ahern/50/50",
|
||||
"Ahern (50,50)");
|
||||
|
||||
testLabel("Render /app/region/Ahern/50/", url,
|
||||
"secondlife:///app/region/Ahern/50/",
|
||||
"Ahern (50)");
|
||||
|
||||
testLabel("Render /app/region/Ahern/50", url,
|
||||
"secondlife:///app/region/Ahern/50",
|
||||
"Ahern (50)");
|
||||
|
||||
testLabel("Render /app/region/Ahern/", url,
|
||||
"secondlife:///app/region/Ahern/",
|
||||
"Ahern");
|
||||
|
||||
testLabel("Render /app/region/Ahern/ within context", url,
|
||||
"XXX secondlife:///app/region/Ahern/ XXX",
|
||||
"Ahern");
|
||||
|
||||
testLabel("Render /app/region/Ahern", url,
|
||||
"secondlife:///app/region/Ahern",
|
||||
"Ahern");
|
||||
|
||||
testLabel("Render /app/region/Ahern within context", url,
|
||||
"XXX secondlife:///app/region/Ahern XXX",
|
||||
"Ahern");
|
||||
|
||||
testLabel("Render /app/region/Product%20Engine/", url,
|
||||
"secondlife:///app/region/Product%20Engine/",
|
||||
"Product Engine");
|
||||
|
||||
testLabel("Render /app/region/Product%20Engine", url,
|
||||
"secondlife:///app/region/Product%20Engine",
|
||||
"Product Engine");
|
||||
|
||||
// Location parsing texts.
|
||||
testLocation("Location /app/region/Ahern/50/50/50/", url,
|
||||
"secondlife:///app/region/Ahern/50/50/50/",
|
||||
"Ahern");
|
||||
|
||||
testLocation("Location /app/region/Product%20Engine", url,
|
||||
"secondlife:///app/region/Product%20Engine",
|
||||
"Product Engine");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue