summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormaksymsproductengine <maksymsproductengine@lindenlab.com>2014-10-02 18:20:10 +0300
committermaksymsproductengine <maksymsproductengine@lindenlab.com>2014-10-02 18:20:10 +0300
commita25748e11ea59d72f8190373be5b8930288d4744 (patch)
treeddfebd4b4a738c7b636427b9ba469929b81627a5
parentd95feec8dc38dad52f5265a9abc58175019c6d18 (diff)
MAINT-4119 FIXED Uniquely decorate links on Second Life or Linden Lab domains
-rwxr-xr-xindra/llui/lltextbase.cpp70
-rwxr-xr-xindra/llui/lltextutil.cpp91
-rwxr-xr-xindra/llui/lltextutil.h29
-rwxr-xr-xindra/llui/llurlentry.cpp30
-rwxr-xr-xindra/llui/llurlentry.h17
-rwxr-xr-xindra/llui/llurlmatch.cpp6
-rwxr-xr-xindra/llui/llurlmatch.h6
-rwxr-xr-xindra/llui/llurlregistry.cpp7
-rw-r--r--indra/newview/skins/default/textures/icons/hand.pngbin0 -> 957 bytes
-rwxr-xr-xindra/newview/skins/default/textures/textures.xml2
10 files changed, 191 insertions, 67 deletions
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 8395e74715..fee271b943 100755
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -44,8 +44,6 @@
#include "llwindow.h"
#include <boost/bind.hpp>
-#include "uriparser/Uri.h"
-
const F32 CURSOR_FLASH_DELAY = 1.0f; // in seconds
const S32 CURSOR_THICKNESS = 2;
const F32 TRIPLE_CLICK_INTERVAL = 0.3f; // delay between double and triple click.
@@ -2021,60 +2019,7 @@ static LLUIImagePtr image_from_icon_name(const std::string& icon_name)
static LLTrace::BlockTimerStatHandle FTM_PARSE_HTML("Parse HTML");
-S32 LLTextBase::normalizeUri(std::string& uri_string)
-{
- UriParserStateA state;
- UriUriA uri;
- state.uri = &uri;
-
- S32 res = uriParseUriA(&state, uri_string.c_str());
-
- if (!res)
- {
- if (uri.scheme.afterLast - uri.scheme.first > 0)
- {
- res = uriNormalizeSyntaxExA(&uri, URI_NORMALIZE_SCHEME | URI_NORMALIZE_HOST);
- if (!res)
- {
- S32 chars_required;
- res = uriToStringCharsRequiredA(&uri, &chars_required);
-
- if (!res)
- {
- chars_required++;
- std::vector<char> label_buf(chars_required);
- res = uriToStringA(&label_buf[0], &uri, chars_required, NULL);
-
- if (!res)
- {
- uri_string = &label_buf[0];
- }
- }
- }
- }
- else if (uri_string.find_first_of('.') != std::string::npos)
- {
- static bool recursive_call = false;
-
- // allow only single level recursive call
- if (!recursive_call)
- {
- recursive_call = true;
-
- // force uri to be with scheme and try to normalize
- std::string uri_with_scheme = "http://";
- uri_with_scheme += uri_string;
- normalizeUri(uri_with_scheme);
- uri_string = uri_with_scheme.substr(7);
- recursive_call = false;
- }
- }
- }
-
- uriFreeUriMembersA(&uri);
- return res;
-}
void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params)
{
@@ -2113,8 +2058,11 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
appendAndHighlightText(subtext, part, style_params);
}
+ // add icon before url if need
+ LLTextUtil::processUrlMatch(&match, this, isContentTrusted() || match.isTrusted());
+
std::string label = match.getLabel();
- normalizeUri(label);
+ LLTextUtil::normalizeUri(label);
// output the styled Url
appendAndHighlightTextImpl(label, part, link_params, match.underlineOnHoverOnly());
@@ -2124,14 +2072,12 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
{
segment_set_t::iterator it = getSegIterContaining(getLength()-1);
if (it != mSegments.end())
- {
- LLTextSegmentPtr segment = *it;
- segment->setToolTip(match.getTooltip());
- }
+ {
+ LLTextSegmentPtr segment = *it;
+ segment->setToolTip(match.getTooltip());
+ }
}
- LLTextUtil::processUrlMatch(&match,this,isContentTrusted());
-
// move on to the rest of the text after the Url
if (end < (S32)text.length())
{
diff --git a/indra/llui/lltextutil.cpp b/indra/llui/lltextutil.cpp
index fff04b34f2..b67daf427b 100755
--- a/indra/llui/lltextutil.cpp
+++ b/indra/llui/lltextutil.cpp
@@ -30,6 +30,8 @@
#include "lltextbox.h"
#include "llurlmatch.h"
+#include "uriparser/Uri.h"
+
boost::function<bool(LLUrlMatch*,LLTextBase*)> LLTextUtil::TextHelpers::iconCallbackCreationFunction = 0;
void LLTextUtil::textboxSetHighlightedVal(LLTextBox *txtbox, const LLStyle::Params& normal_style, const std::string& text, const std::string& hl)
@@ -104,4 +106,93 @@ bool LLTextUtil::processUrlMatch(LLUrlMatch* match,LLTextBase* text_base, bool i
return false;
}
+static void textRangeToString(UriTextRangeA& textRange, std::string& str)
+{
+ S32 len = textRange.afterLast - textRange.first;
+ if (len)
+ {
+ str = textRange.first;
+ str = str.substr(0, len);
+ }
+}
+
+S32 LLTextUtil::normalizeUri(std::string& uri_string, Uri * urip/* = NULL*/)
+{
+ UriParserStateA state;
+ UriUriA uri;
+ state.uri = &uri;
+
+ S32 res = uriParseUriA(&state, uri_string.c_str());
+
+ if (!res)
+ {
+ S32 len = uri.scheme.afterLast - uri.scheme.first;
+
+ if (len > 0)
+ {
+ res = uriNormalizeSyntaxExA(&uri, URI_NORMALIZE_SCHEME | URI_NORMALIZE_HOST);
+
+ if (!res)
+ {
+ S32 chars_required;
+ res = uriToStringCharsRequiredA(&uri, &chars_required);
+
+ if (!res)
+ {
+ chars_required++;
+ std::vector<char> label_buf(chars_required);
+ res = uriToStringA(&label_buf[0], &uri, chars_required, NULL);
+
+ if (!res)
+ {
+ uri_string = &label_buf[0];
+ }
+ }
+ }
+
+ // fill urip if requested
+ if (urip)
+ {
+ textRangeToString(uri.scheme, urip->scheme);
+ textRangeToString(uri.hostText, urip->host);
+ textRangeToString(uri.portText, urip->port);
+ textRangeToString(uri.query, urip->query);
+ textRangeToString(uri.fragment, urip->fragment);
+
+ UriPathSegmentA * pathHead = uri.pathHead;
+ while (pathHead)
+ {
+ std::string partOfPath;
+ textRangeToString(pathHead->text, partOfPath);
+
+ urip->path += '/';
+ urip->path += partOfPath;
+
+ pathHead = pathHead->next;
+ }
+ }
+ }
+ else if (uri_string.find_first_of('.') != std::string::npos)
+ {
+ static bool recursive_call = false;
+
+ // allow only single level recursive call
+ if (!recursive_call)
+ {
+ recursive_call = true;
+
+ // force uri to be with scheme and try to normalize
+ std::string uri_with_scheme = "http://";
+ uri_with_scheme += uri_string;
+ normalizeUri(uri_with_scheme, urip);
+ uri_string = uri_with_scheme.substr(7);
+ recursive_call = false;
+ }
+ }
+ }
+
+ uriFreeUriMembersA(&uri);
+ return res;
+}
+
// EOF
diff --git a/indra/llui/lltextutil.h b/indra/llui/lltextutil.h
index 798f14d086..176b4ba071 100755
--- a/indra/llui/lltextutil.h
+++ b/indra/llui/lltextutil.h
@@ -64,7 +64,34 @@ namespace LLTextUtil
*/
const std::string& formatPhoneNumber(const std::string& phone_str);
- bool processUrlMatch(LLUrlMatch* match,LLTextBase* text_base, bool is_content_trusted);
+ /**
+ * Adds icon before url if need.
+ *
+ * @param[in] match an object with results of matching
+ * @param[in] text_base pointer to UI text object
+ * @param[in] is_content_trusted true if context is trusted
+ * @return reference to string with formatted phone number
+ */
+ bool processUrlMatch(LLUrlMatch* match, LLTextBase* text_base, bool is_content_trusted);
+
+ typedef struct
+ {
+ std::string scheme;
+ std::string host;
+ std::string port;
+ std::string path;
+ std::string query;
+ std::string fragment;
+ } Uri;
+
+ /**
+ * Translates uri's host name and scheme to lowercase
+ *
+ * @param[in, out] uri_string string with original uri
+ * @param[out] uri receives parts of uri
+ * @return 0 on success, error code otherwise
+ */
+ S32 normalizeUri(std::string& uri_string, Uri * uri = NULL);
class TextHelpers
{
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index be583c83d8..3ebf06eefa 100755
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -35,6 +35,7 @@
#include "llavatarnamecache.h"
#include "llcachename.h"
#include "lltrans.h"
+#include "lltextutil.h"
#include "lluicolortable.h"
#include "message.h"
@@ -342,6 +343,35 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const
}
//
+// LLUrlEntrySeconlifeURLs Describes *secondlife.com and *lindenlab.com urls to substitute icon 'hand.png' before link
+//
+LLUrlEntrySeconlifeURL::LLUrlEntrySeconlifeURL()
+{
+ mPattern = boost::regex("\\b(https?://)?([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com\\S*",
+ boost::regex::perl|boost::regex::icase);
+
+ mIcon = "Hand";
+ mMenuName = "menu_url_http.xml";
+}
+
+std::string LLUrlEntrySeconlifeURL::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ std::string local_url(url);
+
+ LLTextUtil::Uri uri;
+ LLTextUtil::normalizeUri(local_url, &uri);
+
+ return uri.host;
+}
+
+std::string LLUrlEntrySeconlifeURL::getTooltip(const std::string &url) const
+{
+ std::string local_url(url);
+ LLTextUtil::normalizeUri(local_url);
+ return local_url;
+}
+
+//
// LLUrlEntryAgent Describes a Second Life agent Url, e.g.,
// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index ffcd45dfde..f75d773803 100755
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -96,6 +96,8 @@ public:
/// Should this link text be underlined only when mouse is hovered over it?
virtual bool underlineOnHoverOnly(const std::string &string) const { return false; }
+ virtual bool isTrusted() const { return false; }
+
virtual LLUUID getID(const std::string &string) const { return LLUUID::null; }
bool isLinkDisabled() const;
@@ -168,6 +170,21 @@ public:
};
///
+/// LLUrlEntrySeconlifeURLs Describes *secondlife.com and *lindenlab.com Urls
+///
+class LLUrlEntrySeconlifeURL : public LLUrlEntryBase
+{
+public:
+ LLUrlEntrySeconlifeURL();
+ virtual bool isTrusted() const { return true; }
+ virtual std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ virtual std::string getTooltip(const std::string &url) const;
+
+private:
+ std::string mLabel;
+};
+
+///
/// LLUrlEntryAgent Describes a Second Life agent Url, e.g.,
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
class LLUrlEntryAgent : public LLUrlEntryBase
diff --git a/indra/llui/llurlmatch.cpp b/indra/llui/llurlmatch.cpp
index c1f1382a9f..016d1ca92d 100755
--- a/indra/llui/llurlmatch.cpp
+++ b/indra/llui/llurlmatch.cpp
@@ -37,7 +37,8 @@ LLUrlMatch::LLUrlMatch() :
mIcon(""),
mMenuName(""),
mLocation(""),
- mUnderlineOnHoverOnly(false)
+ mUnderlineOnHoverOnly(false),
+ mTrusted(false)
{
}
@@ -45,7 +46,7 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
const std::string &label, const std::string &tooltip,
const std::string &icon, const LLStyle::Params& style,
const std::string &menu, const std::string &location,
- const LLUUID& id, bool underline_on_hover_only)
+ const LLUUID& id, bool underline_on_hover_only, bool trusted)
{
mStart = start;
mEnd = end;
@@ -59,4 +60,5 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
mLocation = location;
mID = id;
mUnderlineOnHoverOnly = underline_on_hover_only;
+ mTrusted = trusted;
}
diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h
index 2818f45207..9f8960b32f 100755
--- a/indra/llui/llurlmatch.h
+++ b/indra/llui/llurlmatch.h
@@ -80,12 +80,15 @@ public:
/// Should this link text be underlined only when mouse is hovered over it?
bool underlineOnHoverOnly() const { return mUnderlineOnHoverOnly; }
+ /// Return true if Url is trusted.
+ bool isTrusted() const { return mTrusted; }
+
/// Change the contents of this match object (used by LLUrlRegistry)
void setValues(U32 start, U32 end, const std::string &url, const std::string &label,
const std::string &tooltip, const std::string &icon,
const LLStyle::Params& style, const std::string &menu,
const std::string &location, const LLUUID& id,
- bool underline_on_hover_only = false );
+ bool underline_on_hover_only = false, bool trusted = false );
const LLUUID& getID() const { return mID; }
private:
@@ -100,6 +103,7 @@ private:
LLUUID mID;
LLStyle::Params mStyle;
bool mUnderlineOnHoverOnly;
+ bool mTrusted;
};
#endif
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index ef0789e0e4..462b3d6979 100755
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -44,6 +44,10 @@ LLUrlRegistry::LLUrlRegistry()
mUrlEntryIcon = new LLUrlEntryIcon();
registerUrl(mUrlEntryIcon);
registerUrl(new LLUrlEntrySLURL());
+
+ // decorated links for host names like: secondlife.com and lindenlab.com
+ registerUrl(new LLUrlEntrySeconlifeURL());
+
registerUrl(new LLUrlEntryHTTP());
mUrlEntryHTTPLabel = new LLUrlEntryHTTPLabel();
registerUrl(mUrlEntryHTTPLabel);
@@ -212,7 +216,8 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
match_entry->getMenuName(),
match_entry->getLocation(url),
match_entry->getID(url),
- match_entry->underlineOnHoverOnly(url));
+ match_entry->underlineOnHoverOnly(url),
+ match_entry->isTrusted());
return true;
}
diff --git a/indra/newview/skins/default/textures/icons/hand.png b/indra/newview/skins/default/textures/icons/hand.png
new file mode 100644
index 0000000000..41b9600da6
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/hand.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 46698b3949..8fdc770009 100755
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -229,6 +229,8 @@ with the same filename but different name
<texture name="Generic_Person" file_name="icons/Generic_Person.png" preload="false" />
<texture name="Generic_Person_Large" file_name="icons/Generic_Person_Large.png" preload="false" />
+ <texture name="Hand" file_name="icons/hand.png" preload="false" />
+
<texture name="Help_Press" file_name="navbar/Help_Press.png" preload="false" />
<texture name="Hierarchy_View_Disabled" file_name="icons/Hierarchy_View_Disabled.png" preload="false" />