summaryrefslogtreecommitdiff
path: root/indra/llui/llurlentry.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui/llurlentry.cpp')
-rw-r--r--indra/llui/llurlentry.cpp295
1 files changed, 216 insertions, 79 deletions
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 52e4229fb4..e8e3459673 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -34,12 +34,16 @@
#include "linden_common.h"
#include "llurlentry.h"
#include "lluri.h"
+#include "llurlmatch.h"
+#include "llurlregistry.h"
+
#include "llcachename.h"
#include "lltrans.h"
#include "lluicolortable.h"
-LLUrlEntryBase::LLUrlEntryBase()
-: mColor(LLUIColorTable::instance().getColor("HTMLLinkColor"))
+LLUrlEntryBase::LLUrlEntryBase() :
+ mColor(LLUIColorTable::instance().getColor("HTMLLinkColor")),
+ mDisabledLink(false)
{
}
@@ -47,7 +51,7 @@ LLUrlEntryBase::~LLUrlEntryBase()
{
}
-std::string LLUrlEntryBase::getUrl(const std::string &string)
+std::string LLUrlEntryBase::getUrl(const std::string &string) const
{
return escapeUrl(string);
}
@@ -79,7 +83,7 @@ std::string LLUrlEntryBase::escapeUrl(const std::string &url) const
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789"
- "-._~!$?&()*+,@:;=/%";
+ "-._~!$?&()*+,@:;=/%#";
std::sort(no_escape_chars.begin(), no_escape_chars.end());
initialized = true;
@@ -87,7 +91,7 @@ std::string LLUrlEntryBase::escapeUrl(const std::string &url) const
return LLURI::escape(url, no_escape_chars, true);
}
-std::string LLUrlEntryBase::getLabelFromWikiLink(const std::string &url)
+std::string LLUrlEntryBase::getLabelFromWikiLink(const std::string &url) const
{
// return the label part from [http://www.example.org Label]
const char *text = url.c_str();
@@ -100,10 +104,10 @@ std::string LLUrlEntryBase::getLabelFromWikiLink(const std::string &url)
{
start++;
}
- return url.substr(start, url.size()-start-1);
+ return unescapeUrl(url.substr(start, url.size()-start-1));
}
-std::string LLUrlEntryBase::getUrlFromWikiLink(const std::string &string)
+std::string LLUrlEntryBase::getUrlFromWikiLink(const std::string &string) const
{
// return the url part from [http://www.example.org Label]
const char *text = string.c_str();
@@ -145,6 +149,18 @@ void LLUrlEntryBase::callObservers(const std::string &id, const std::string &lab
}
}
+static std::string getStringAfterToken(const std::string str, const std::string token)
+{
+ size_t pos = str.find(token);
+ if (pos == std::string::npos)
+ {
+ return "";
+ }
+
+ pos += token.size();
+ return str.substr(pos, str.size() - pos);
+}
+
//
// LLUrlEntryHTTP Describes generic http: and https: Urls
//
@@ -154,7 +170,6 @@ LLUrlEntryHTTP::LLUrlEntryHTTP()
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_http.xml";
mTooltip = LLTrans::getString("TooltipHttpUrl");
- //mIcon = "gear.tga";
}
std::string LLUrlEntryHTTP::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
@@ -179,18 +194,47 @@ std::string LLUrlEntryHTTPLabel::getLabel(const std::string &url, const LLUrlLab
return getLabelFromWikiLink(url);
}
-std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string)
+std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string) const
{
return getUrlFromWikiLink(string);
}
//
+// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com
+//
+LLUrlEntryHTTPNoProtocol::LLUrlEntryHTTPNoProtocol()
+{
+ mPattern = boost::regex("("
+ "\\bwww\\.\\S+\\.\\S+" // i.e. www.FOO.BAR
+ "|" // or
+ "(?<!@)\\b[^[:space:]:@/>]+\\.(?:com|net|edu|org)([/:][^[:space:]<]*)?\\b" // i.e. FOO.net
+ ")",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_http.xml";
+ mTooltip = LLTrans::getString("TooltipHttpUrl");
+}
+
+std::string LLUrlEntryHTTPNoProtocol::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return unescapeUrl(url);
+}
+
+std::string LLUrlEntryHTTPNoProtocol::getUrl(const std::string &string) const
+{
+ if (string.find("://") == std::string::npos)
+ {
+ return "http://" + escapeUrl(string);
+ }
+ return escapeUrl(string);
+}
+
+//
// LLUrlEntrySLURL Describes generic http: and https: Urls
//
LLUrlEntrySLURL::LLUrlEntrySLURL()
{
// see http://slurl.com/about.php for details on the SLURL format
- mPattern = boost::regex("http://slurl.com/secondlife/\\S+/?(\\d+)?/?(\\d+)?/?(\\d+)?/?\\S*",
+ mPattern = boost::regex("http://(maps.secondlife.com|slurl.com)/secondlife/[^ /]+(/\\d+){0,3}(/?(\\?title|\\?img|\\?msg)=\\S*)?/?",
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_slurl.xml";
mTooltip = LLTrans::getString("TooltipSLURL");
@@ -245,7 +289,7 @@ std::string LLUrlEntrySLURL::getLabel(const std::string &url, const LLUrlLabelCa
std::string LLUrlEntrySLURL::getLocation(const std::string &url) const
{
// return the part of the Url after slurl.com/secondlife/
- const std::string search_string = "secondlife";
+ const std::string search_string = "/secondlife";
size_t pos = url.find(search_string);
if (pos == std::string::npos)
{
@@ -278,6 +322,38 @@ void LLUrlEntryAgent::onAgentNameReceived(const LLUUID& id,
callObservers(id.asString(), first + " " + last);
}
+std::string LLUrlEntryAgent::getTooltip(const std::string &string) const
+{
+ // return a tooltip corresponding to the URL type instead of the generic one
+ std::string url = getUrl(string);
+
+ if (LLStringUtil::endsWith(url, "/mute"))
+ {
+ return LLTrans::getString("TooltipAgentMute");
+ }
+ if (LLStringUtil::endsWith(url, "/unmute"))
+ {
+ return LLTrans::getString("TooltipAgentUnmute");
+ }
+ if (LLStringUtil::endsWith(url, "/im"))
+ {
+ return LLTrans::getString("TooltipAgentIM");
+ }
+ if (LLStringUtil::endsWith(url, "/pay"))
+ {
+ return LLTrans::getString("TooltipAgentPay");
+ }
+ if (LLStringUtil::endsWith(url, "/offerteleport"))
+ {
+ return LLTrans::getString("TooltipAgentOfferTeleport");
+ }
+ if (LLStringUtil::endsWith(url, "/requestfriend"))
+ {
+ return LLTrans::getString("TooltipAgentRequestFriend");
+ }
+ return LLTrans::getString("TooltipAgentUrl");
+}
+
std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
{
if (!gCacheName)
@@ -301,6 +377,31 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa
}
else if (gCacheName->getFullName(agent_id, full_name))
{
+ // customize label string based on agent SLapp suffix
+ if (LLStringUtil::endsWith(url, "/mute"))
+ {
+ return LLTrans::getString("SLappAgentMute") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/unmute"))
+ {
+ return LLTrans::getString("SLappAgentUnmute") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/im"))
+ {
+ return LLTrans::getString("SLappAgentIM") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/pay"))
+ {
+ return LLTrans::getString("SLappAgentPay") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/offerteleport"))
+ {
+ return LLTrans::getString("SLappAgentOfferTeleport") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/requestfriend"))
+ {
+ return LLTrans::getString("SLappAgentRequestFriend") + " " + full_name;
+ }
return full_name;
}
else
@@ -372,6 +473,26 @@ std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCa
}
}
+//
+// LLUrlEntryInventory Describes a Second Life inventory Url, e.g.,
+// secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select
+//
+LLUrlEntryInventory::LLUrlEntryInventory()
+{
+ //*TODO: add supporting of inventory item names with whitespaces
+ //this pattern cann't parse for example
+ //secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select?name=name with spaces&param2=value
+ mPattern = boost::regex("secondlife:///app/inventory/[\\da-f-]+/\\w+\\S*",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_inventory.xml";
+}
+
+std::string LLUrlEntryInventory::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ std::string label = getStringAfterToken(url, "name=");
+ return LLURI::unescape(label.empty() ? url : label);
+}
+
///
/// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,
/// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about
@@ -390,7 +511,7 @@ std::string LLUrlEntryParcel::getLabel(const std::string &url, const LLUrlLabelC
}
//
-// LLUrlEntryPlace Describes secondlife:///<location> URLs
+// LLUrlEntryPlace Describes secondlife://<location> URLs
//
LLUrlEntryPlace::LLUrlEntryPlace()
{
@@ -433,15 +554,7 @@ std::string LLUrlEntryPlace::getLabel(const std::string &url, const LLUrlLabelCa
std::string LLUrlEntryPlace::getLocation(const std::string &url) const
{
// return the part of the Url after secondlife:// part
- const std::string search_string = "://";
- size_t pos = url.find(search_string);
- if (pos == std::string::npos)
- {
- return "";
- }
-
- pos += search_string.size();
- return url.substr(pos, url.size() - pos);
+ return ::getStringAfterToken(url, "://");
}
//
@@ -468,6 +581,7 @@ std::string LLUrlEntryTeleport::getLabel(const std::string &url, const LLUrlLabe
LLURI uri(url);
LLSD path_array = uri.pathArray();
S32 path_parts = path_array.size();
+ const std::string label = LLTrans::getString("SLurlLabelTeleport");
if (path_parts == 6)
{
// handle teleport url with (X,Y,Z) coordinates
@@ -475,7 +589,7 @@ std::string LLUrlEntryTeleport::getLabel(const std::string &url, const LLUrlLabe
std::string x = path_array[path_parts-3];
std::string y = path_array[path_parts-2];
std::string z = path_array[path_parts-1];
- return "Teleport to " + location + " (" + x + "," + y + "," + z + ")";
+ return label + " " + location + " (" + x + "," + y + "," + z + ")";
}
else if (path_parts == 5)
{
@@ -483,20 +597,20 @@ std::string LLUrlEntryTeleport::getLabel(const std::string &url, const LLUrlLabe
std::string location = unescapeUrl(path_array[path_parts-3]);
std::string x = path_array[path_parts-2];
std::string y = path_array[path_parts-1];
- return "Teleport to " + location + " (" + x + "," + y + ")";
+ return label + " " + location + " (" + x + "," + y + ")";
}
else if (path_parts == 4)
{
// handle teleport url with (X) coordinate only
std::string location = unescapeUrl(path_array[path_parts-2]);
std::string x = path_array[path_parts-1];
- return "Teleport to " + location + " (" + x + ")";
+ return label + " " + location + " (" + x + ")";
}
else if (path_parts == 3)
{
// handle teleport url with no coordinates
std::string location = unescapeUrl(path_array[path_parts-1]);
- return "Teleport to " + location;
+ return label + " " + location;
}
return url;
@@ -505,59 +619,7 @@ std::string LLUrlEntryTeleport::getLabel(const std::string &url, const LLUrlLabe
std::string LLUrlEntryTeleport::getLocation(const std::string &url) const
{
// return the part of the Url after ///app/teleport
- const std::string search_string = "teleport";
- size_t pos = url.find(search_string);
- if (pos == std::string::npos)
- {
- return "";
- }
-
- pos += search_string.size() + 1;
- return url.substr(pos, url.size() - pos);
-}
-
-///
-/// LLUrlEntryObjectIM Describes a Second Life object instant msg Url, e.g.,
-/// secondlife:///app/objectim/<sessionid>
-///
-LLUrlEntryObjectIM::LLUrlEntryObjectIM()
-{
- mPattern = boost::regex("secondlife:///app/objectim/[\\da-f-]+\\??\\S*",
- boost::regex::perl|boost::regex::icase);
- mMenuName = "menu_url_objectim.xml";
- mTooltip = LLTrans::getString("TooltipObjectIMUrl");
-}
-
-std::string LLUrlEntryObjectIM::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
-{
- LLURI uri(url);
- LLSD params = uri.queryMap();
- if (params.has("name"))
- {
- // look for a ?name=<obj-name> param in the url
- // and use that as the label if present.
- std::string name = params.get("name");
- LLStringUtil::trim(name);
- if (name.empty())
- {
- name = LLTrans::getString("Unnamed");
- }
- return name;
- }
-
- return unescapeUrl(url);
-}
-
-std::string LLUrlEntryObjectIM::getLocation(const std::string &url) const
-{
- LLURI uri(url);
- LLSD params = uri.queryMap();
- if (params.has("slurl"))
- {
- return params.get("slurl");
- }
-
- return "";
+ return ::getStringAfterToken(url, "app/teleport/");
}
//
@@ -594,8 +656,83 @@ std::string LLUrlEntrySLLabel::getLabel(const std::string &url, const LLUrlLabel
return getLabelFromWikiLink(url);
}
-std::string LLUrlEntrySLLabel::getUrl(const std::string &string)
+std::string LLUrlEntrySLLabel::getUrl(const std::string &string) const
{
return getUrlFromWikiLink(string);
}
+std::string LLUrlEntrySLLabel::getTooltip(const std::string &string) const
+{
+ // return a tooltip corresponding to the URL type instead of the generic one (EXT-4574)
+ std::string url = getUrl(string);
+ LLUrlMatch match;
+ if (LLUrlRegistry::instance().findUrl(url, match))
+ {
+ return match.getTooltip();
+ }
+
+ // unrecognized URL? should not happen
+ return LLUrlEntryBase::getTooltip(string);
+}
+
+//
+// LLUrlEntryWorldMap Describes secondlife:///<location> URLs
+//
+LLUrlEntryWorldMap::LLUrlEntryWorldMap()
+{
+ mPattern = boost::regex("secondlife:///app/worldmap/\\S+/?(\\d+)?/?(\\d+)?/?(\\d+)?/?\\S*",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_map.xml";
+ mTooltip = LLTrans::getString("TooltipMapUrl");
+}
+
+std::string LLUrlEntryWorldMap::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ //
+ // we handle SLURLs in the following formats:
+ // - secondlife:///app/worldmap/PLACE/X/Y/Z
+ // - secondlife:///app/worldmap/PLACE/X/Y
+ // - secondlife:///app/worldmap/PLACE/X
+ //
+ LLURI uri(url);
+ LLSD path_array = uri.pathArray();
+ S32 path_parts = path_array.size();
+ if (path_parts < 3)
+ {
+ return url;
+ }
+
+ const std::string label = LLTrans::getString("SLurlLabelShowOnMap");
+ std::string location = path_array[2];
+ std::string x = (path_parts > 3) ? path_array[3] : "128";
+ std::string y = (path_parts > 4) ? path_array[4] : "128";
+ std::string z = (path_parts > 5) ? path_array[5] : "0";
+ return label + " " + location + " (" + x + "," + y + "," + z + ")";
+}
+
+std::string LLUrlEntryWorldMap::getLocation(const std::string &url) const
+{
+ // return the part of the Url after secondlife:///app/worldmap/ part
+ return ::getStringAfterToken(url, "app/worldmap/");
+}
+
+//
+// LLUrlEntryNoLink lets us turn of URL detection with <nolink>...</nolink> tags
+//
+LLUrlEntryNoLink::LLUrlEntryNoLink()
+{
+ mPattern = boost::regex("<nolink>[^<]*</nolink>",
+ boost::regex::perl|boost::regex::icase);
+ mDisabledLink = true;
+}
+
+std::string LLUrlEntryNoLink::getUrl(const std::string &url) const
+{
+ // return the text between the <nolink> and </nolink> tags
+ return url.substr(8, url.size()-8-9);
+}
+
+std::string LLUrlEntryNoLink::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return getUrl(url);
+}