diff options
| author | Martin Reddy <lynx@lindenlab.com> | 2009-09-22 18:00:16 +0000 | 
|---|---|---|
| committer | Martin Reddy <lynx@lindenlab.com> | 2009-09-22 18:00:16 +0000 | 
| commit | 12762053e5aff372a9f8d473c71aa81e805bb474 (patch) | |
| tree | c2c29e3b178cc9c51b99bd94d2f478e96d8a7d30 | |
| parent | be41bf82c6325fc45c7c6474645f384479e27091 (diff) | |
EXT-944 EXT-1026: converted the LLUrlRegistry::findUrl() method to
work on an LLWString instead of a std::string, so that we don't have
to worry about character offsets for variable-length-encoded UTF-8
strings.
This was causing crashes whenever we would try to show a textbox with
a URL and foreign characters (> 1 byte chars). Damn, I suck!
| -rw-r--r-- | indra/llui/lltextbase.cpp | 2 | ||||
| -rw-r--r-- | indra/llui/lltextbox.cpp | 4 | ||||
| -rw-r--r-- | indra/llui/lltexteditor.cpp | 11 | ||||
| -rw-r--r-- | indra/llui/llurlaction.cpp | 4 | ||||
| -rw-r--r-- | indra/llui/llurlentry.cpp | 44 | ||||
| -rw-r--r-- | indra/llui/llurlentry.h | 4 | ||||
| -rw-r--r-- | indra/llui/llurlregistry.cpp | 12 | ||||
| -rw-r--r-- | indra/llui/llurlregistry.h | 3 | ||||
| -rw-r--r-- | indra/llui/tests/llurlentry_test.cpp | 34 | 
9 files changed, 61 insertions, 57 deletions
| diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index cb60b4fe36..325c7a8104 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -429,7 +429,7 @@ LLContextMenu *LLTextBase::createUrlContextMenu(const std::string &in_url)  	// work out the XUI menu file to use for this url  	LLUrlMatch match;  	std::string url = in_url; -	if (! LLUrlRegistry::instance().findUrl(url, match)) +	if (! LLUrlRegistry::instance().findUrl(utf8str_to_wstring(url), match))  	{  		return NULL;  	} diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 810626268f..3cde42d75c 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -297,7 +297,7 @@ LLWString LLTextBox::getWrappedText(const LLStringExplicit& in_text, F32 max_wid  	// find the next Url in the text string  	LLUrlMatch match; -	while ( LLUrlRegistry::instance().findUrl(wstring_to_utf8str(wtext), match)) +	while ( LLUrlRegistry::instance().findUrl(wtext, match))  	{  		S32 start = match.getStart();  		S32 end = match.getEnd() + 1; @@ -573,7 +573,7 @@ void LLTextBox::updateDisplayTextAndSegments()  	LLWString text = mText.getWString();  	// find the next Url in the text string -	while ( LLUrlRegistry::instance().findUrl(wstring_to_utf8str(text), match, +	while ( LLUrlRegistry::instance().findUrl(text, match,  											  boost::bind(&LLTextBox::onUrlLabelUpdated, this, _1, _2)) )  	{  		// work out the char offset for the start/end of the url diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 983777b747..f7680a0a2b 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -3525,7 +3525,7 @@ void LLTextEditor::appendStyledText(const std::string &new_text,  		S32 start=0,end=0;  		LLUrlMatch match; -		std::string text = new_text; +		LLWString text = utf8str_to_wstring(new_text);  		while ( LLUrlRegistry::instance().findUrl(text, match,  		        boost::bind(&LLTextEditor::onUrlLabelUpdated, this, _1, _2)) )  		{ @@ -3549,8 +3549,8 @@ void LLTextEditor::appendStyledText(const std::string &new_text,  				{  					part = (S32)LLTextParser::MIDDLE;  				} -				std::string subtext=text.substr(0,start); -				appendHighlightedText(subtext,allow_undo, prepend_newline, part, style_params);  +				std::string subtext = wstring_to_utf8str(text.substr(0,start)); +				appendHighlightedText(subtext, allow_undo, prepend_newline, part, style_params);   				prepend_newline = false;  			} @@ -3595,7 +3595,8 @@ void LLTextEditor::appendStyledText(const std::string &new_text,  			}  		}  		if (part != (S32)LLTextParser::WHOLE) part=(S32)LLTextParser::END; -		if (end < (S32)text.length()) appendHighlightedText(text,allow_undo, prepend_newline, part, style_params);		 +		if (end < (S32)text.length()) appendHighlightedText(wstring_to_utf8str(text), allow_undo, +															prepend_newline, part, style_params);		  	}  	else  	{ @@ -4137,7 +4138,7 @@ void LLTextEditor::updateLinkSegments()  			LLUrlMatch match;  			LLStyleSP style = static_cast<LLStyleSP>(segment->getStyle());  			std::string url_label = getText().substr(segment->getStart(), segment->getEnd()-segment->getStart()); -			if (LLUrlRegistry::instance().findUrl(url_label, match)) +			if (LLUrlRegistry::instance().findUrl(utf8str_to_wstring(url_label), match))  			{  				LLStringUtil::trim(url_label);  				style->setLinkHREF(url_label); diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp index 3b689b93c0..7721d0e502 100644 --- a/indra/llui/llurlaction.cpp +++ b/indra/llui/llurlaction.cpp @@ -112,7 +112,7 @@ void LLUrlAction::clickAction(std::string url)  void LLUrlAction::teleportToLocation(std::string url)  {  	LLUrlMatch match; -	if (LLUrlRegistry::instance().findUrl(url, match)) +	if (LLUrlRegistry::instance().findUrl(utf8str_to_wstring(url), match))  	{  		if (! match.getLocation().empty())  		{ @@ -129,7 +129,7 @@ void LLUrlAction::copyURLToClipboard(std::string url)  void LLUrlAction::copyLabelToClipboard(std::string url)  {  	LLUrlMatch match; -	if (LLUrlRegistry::instance().findUrl(url, match)) +	if (LLUrlRegistry::instance().findUrl(utf8str_to_wstring(url), match))  	{  		LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(match.getLabel()));  	}	 diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index c20212c375..e4bcc27428 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -148,8 +148,8 @@ void LLUrlEntryBase::callObservers(const std::string &id, const std::string &lab  //  LLUrlEntryHTTP::LLUrlEntryHTTP()  { -	mPattern = boost::regex("https?://([-\\w\\.]+)+(:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?/?\\S*", -							boost::regex::perl|boost::regex::icase); +	mPattern = boost::wregex(L"https?://([-\\w\\.]+)+(:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?/?\\S*", +							 boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_http.xml";  	mTooltip = LLTrans::getString("TooltipHttpUrl");  	//mIcon = "gear.tga"; @@ -166,8 +166,8 @@ std::string LLUrlEntryHTTP::getLabel(const std::string &url, const LLUrlLabelCal  //  LLUrlEntryHTTPLabel::LLUrlEntryHTTPLabel()  { -	mPattern = boost::regex("\\[https?://\\S+[ \t]+[^\\]]+\\]", -							boost::regex::perl|boost::regex::icase); +	mPattern = boost::wregex(L"\\[https?://\\S+[ \t]+[^\\]]+\\]", +							 boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_http.xml";  	mTooltip = LLTrans::getString("TooltipHttpUrl");  } @@ -188,8 +188,8 @@ std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string)  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*", -							boost::regex::perl|boost::regex::icase); +	mPattern = boost::wregex(L"http://slurl.com/secondlife/\\S+/?(\\d+)?/?(\\d+)?/?(\\d+)?/?\\S*", +							 boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_slurl.xml";  	mTooltip = LLTrans::getString("TooltipSLURL");  } @@ -260,8 +260,8 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const  //  LLUrlEntryAgent::LLUrlEntryAgent()  { -	mPattern = boost::regex("secondlife:///app/agent/[\\da-f-]+/about", -							boost::regex::perl|boost::regex::icase); +	mPattern = boost::wregex(L"secondlife:///app/agent/[\\da-f-]+/about", +							 boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_agent.xml";  	mTooltip = LLTrans::getString("TooltipAgentUrl");  } @@ -302,8 +302,8 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa  //  LLUrlEntryGroup::LLUrlEntryGroup()  { -	mPattern = boost::regex("secondlife:///app/group/[\\da-f-]+/about", -							boost::regex::perl|boost::regex::icase); +	mPattern = boost::wregex(L"secondlife:///app/group/[\\da-f-]+/about", +							 boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_group.xml";  	mTooltip = LLTrans::getString("TooltipGroupUrl");  } @@ -344,8 +344,8 @@ std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCa  ///  LLUrlEntryParcel::LLUrlEntryParcel()  { -	mPattern = boost::regex("secondlife:///app/parcel/[\\da-f-]+/about", -							boost::regex::perl|boost::regex::icase); +	mPattern = boost::wregex(L"secondlife:///app/parcel/[\\da-f-]+/about", +							 boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_parcel.xml";  	mTooltip = LLTrans::getString("TooltipParcelUrl");  } @@ -360,8 +360,8 @@ std::string LLUrlEntryParcel::getLabel(const std::string &url, const LLUrlLabelC  //  LLUrlEntryPlace::LLUrlEntryPlace()  { -	mPattern = boost::regex("secondlife://\\S+/?(\\d+/\\d+/\\d+|\\d+/\\d+)/?", -							boost::regex::perl|boost::regex::icase); +	mPattern = boost::wregex(L"secondlife://\\S+/?(\\d+/\\d+/\\d+|\\d+/\\d+)/?", +							 boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_slurl.xml";  	mTooltip = LLTrans::getString("TooltipSLURL");  } @@ -416,8 +416,8 @@ std::string LLUrlEntryPlace::getLocation(const std::string &url) const  //  LLUrlEntryTeleport::LLUrlEntryTeleport()  { -	mPattern = boost::regex("secondlife:///app/teleport/\\S+(/\\d+)?(/\\d+)?(/\\d+)?/?\\S*", -							boost::regex::perl|boost::regex::icase); +	mPattern = boost::wregex(L"secondlife:///app/teleport/\\S+(/\\d+)?(/\\d+)?(/\\d+)?/?\\S*", +							 boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_teleport.xml";  	mTooltip = LLTrans::getString("TooltipTeleportUrl");  } @@ -488,8 +488,8 @@ std::string LLUrlEntryTeleport::getLocation(const std::string &url) const  ///  LLUrlEntryObjectIM::LLUrlEntryObjectIM()  { -	mPattern = boost::regex("secondlife:///app/objectim/[\\da-f-]+\\??\\S*", -							boost::regex::perl|boost::regex::icase); +	mPattern = boost::wregex(L"secondlife:///app/objectim/[\\da-f-]+\\??\\S*", +							 boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_objectim.xml";  	mTooltip = LLTrans::getString("TooltipObjectIMUrl");  } @@ -532,8 +532,8 @@ std::string LLUrlEntryObjectIM::getLocation(const std::string &url) const  //  LLUrlEntrySL::LLUrlEntrySL()  { -	mPattern = boost::regex("secondlife://(\\w+)?(:\\d+)?/\\S+", -							boost::regex::perl|boost::regex::icase); +	mPattern = boost::wregex(L"secondlife://(\\w+)?(:\\d+)?/\\S+", +							 boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_slapp.xml";  	mTooltip = LLTrans::getString("TooltipSLAPP");  } @@ -549,8 +549,8 @@ std::string LLUrlEntrySL::getLabel(const std::string &url, const LLUrlLabelCallb  //  LLUrlEntrySLLabel::LLUrlEntrySLLabel()  { -	mPattern = boost::regex("\\[secondlife://\\S+[ \t]+[^\\]]+\\]", -							boost::regex::perl|boost::regex::icase); +	mPattern = boost::wregex(L"\\[secondlife://\\S+[ \t]+[^\\]]+\\]", +							 boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_slapp.xml";  	mTooltip = LLTrans::getString("TooltipSLAPP");  } diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 54053872df..36758566ed 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -68,7 +68,7 @@ public:  	virtual ~LLUrlEntryBase();  	/// Return the regex pattern that matches this Url  -	boost::regex getPattern() const { return mPattern; } +	boost::wregex getPattern() const { return mPattern; }  	/// Return the url from a string that matched the regex  	virtual std::string getUrl(const std::string &string); @@ -102,7 +102,7 @@ protected:  		LLUrlLabelSignal *signal;  	} LLUrlEntryObserver; -	boost::regex                                   mPattern; +	boost::wregex                                  mPattern;  	std::string                                    mIcon;  	std::string                                    mMenuName;  	std::string                                    mTooltip; diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index f2d340deb7..2ea3c59e03 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -75,9 +75,9 @@ void LLUrlRegistry::registerUrl(LLUrlEntryBase *url)  	}  } -static bool matchRegex(const char *text, boost::regex regex, U32 &start, U32 &end) +static bool matchRegex(const wchar_t *text, boost::wregex regex, U32 &start, U32 &end)  { -	boost::cmatch result; +	boost::wcmatch result;  	bool found;  	// regex_search can potentially throw an exception, so check for it @@ -107,7 +107,7 @@ static bool matchRegex(const char *text, boost::regex regex, U32 &start, U32 &en  	}  	// ignore a terminating ')' when Url contains no matching '('  	// see DEV-19842 for details -	else if (text[end] == ')' && std::string(text+start, end-start).find('(') == std::string::npos) +	else if (text[end] == ')' && LLWString(text+start, end-start).find('(') == std::string::npos)  	{  		end--;  	} @@ -115,10 +115,10 @@ static bool matchRegex(const char *text, boost::regex regex, U32 &start, U32 &en  	return true;  } -bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb) +bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUrlLabelCallback &cb)  {  	// avoid costly regexes if there is clearly no URL in the text -	if (text.find("://") == std::string::npos) +	if (text.find(L"://") == std::string::npos)  	{  		return false;  	} @@ -149,7 +149,7 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL  	if (match_entry)  	{  		// fill in the LLUrlMatch object and return it -		std::string url = text.substr(match_start, match_end - match_start + 1); +		std::string url = wstring_to_utf8str(text.substr(match_start, match_end - match_start + 1));  		match.setValues(match_start, match_end,  						match_entry->getUrl(url),  						match_entry->getLabel(url, cb), diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h index 84b033036c..bf5257d630 100644 --- a/indra/llui/llurlregistry.h +++ b/indra/llui/llurlregistry.h @@ -37,6 +37,7 @@  #include "llurlentry.h"  #include "llurlmatch.h"  #include "llsingleton.h" +#include "llstring.h"  #include <string>  #include <vector> @@ -74,7 +75,7 @@ public:  	/// get the next Url in an input string, starting at a given character offset  	/// your callback is invoked if the matched Url's label changes in the future -	bool findUrl(const std::string &text, LLUrlMatch &match, +	bool findUrl(const LLWString &text, LLUrlMatch &match,  				 const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback);  private: diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index 1e7a0f7f2c..89a80f1e73 100644 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -44,17 +44,19 @@ namespace  namespace tut  { -	void testRegex(const std::string &testname, boost::regex regex, +	void testRegex(const std::string &testname, boost::wregex regex,  				   const char *text, const std::string &expected)  	{  		std::string url = ""; -		boost::cmatch result; -		bool found = boost::regex_search(text, result, regex); +		boost::wcmatch result; +		LLWString wtext = utf8str_to_wstring(text); +		const wchar_t *wctext = wtext.c_str(); +		bool found = boost::regex_search(wctext, result, regex);  		if (found)  		{ -			S32 start = static_cast<U32>(result[0].first - text); -			S32 end = static_cast<U32>(result[0].second - text); -			url = std::string(text+start, end-start); +			S32 start = static_cast<U32>(result[0].first - wctext); +			S32 end = static_cast<U32>(result[0].second - wctext); +			url = wstring_to_utf8str(wtext.substr(start, end-start));  		}  		ensure_equals(testname, url, expected);  	} @@ -66,7 +68,7 @@ namespace tut  		// test LLUrlEntryHTTP - standard http Urls  		//  		LLUrlEntryHTTP url; -		boost::regex r = url.getPattern(); +		boost::wregex r = url.getPattern();  		testRegex("no valid url", r,  				  "htp://slurl.com/", @@ -145,7 +147,7 @@ namespace tut  		// test LLUrlEntryHTTPLabel - wiki-style http Urls with labels  		//  		LLUrlEntryHTTPLabel url; -		boost::regex r = url.getPattern(); +		boost::wregex r = url.getPattern();  		testRegex("invalid wiki url [1]", r,  				  "[http://www.example.org]", @@ -187,7 +189,7 @@ namespace tut  		// test LLUrlEntrySLURL - second life URLs  		//  		LLUrlEntrySLURL url; -		boost::regex r = url.getPattern(); +		boost::wregex r = url.getPattern();  		testRegex("no valid slurl [1]", r,  				  "htp://slurl.com/secondlife/Ahern/50/50/50/", @@ -259,7 +261,7 @@ namespace tut  		// test LLUrlEntryAgent - secondlife://app/agent Urls  		//  		LLUrlEntryAgent url; -		boost::regex r = url.getPattern(); +		boost::wregex r = url.getPattern();  		testRegex("Invalid Agent Url", r,  				  "secondlife:///app/agent/0e346d8b-4433-4d66-XXXX-fd37083abc4c/about", @@ -285,7 +287,7 @@ namespace tut  		// test LLUrlEntryGroup - secondlife://app/group Urls  		//  		LLUrlEntryGroup url; -		boost::regex r = url.getPattern(); +		boost::wregex r = url.getPattern();  		testRegex("Invalid Group Url", r,  				  "secondlife:///app/group/00005ff3-4044-c79f-XXXX-fb28ae0df991/about", @@ -311,7 +313,7 @@ namespace tut  		// test LLUrlEntryPlace - secondlife://<location> URLs  		//  		LLUrlEntryPlace url; -		boost::regex r = url.getPattern(); +		boost::wregex r = url.getPattern();  		testRegex("no valid slurl [1]", r,  				  "secondlife://Ahern/FOO/50/", @@ -359,7 +361,7 @@ namespace tut  		// test LLUrlEntryParcel - secondlife://app/parcel Urls  		//  		LLUrlEntryParcel url; -		boost::regex r = url.getPattern(); +		boost::wregex r = url.getPattern();  		testRegex("Invalid Classified Url", r,  				  "secondlife:///app/parcel/0000060e-4b39-e00b-XXXX-d98b1934e3a8/about", @@ -384,7 +386,7 @@ namespace tut  		// test LLUrlEntryTeleport - secondlife://app/teleport URLs  		//  		LLUrlEntryTeleport url; -		boost::regex r = url.getPattern(); +		boost::wregex r = url.getPattern();  		testRegex("no valid teleport [1]", r,  				  "http://slurl.com/secondlife/Ahern/50/50/50/", @@ -460,7 +462,7 @@ namespace tut  		// test LLUrlEntrySL - general secondlife:// URLs  		//  		LLUrlEntrySL url; -		boost::regex r = url.getPattern(); +		boost::wregex r = url.getPattern();  		testRegex("no valid slapp [1]", r,  				  "http:///app/", @@ -498,7 +500,7 @@ namespace tut  		// test LLUrlEntrySLLabel - general secondlife:// URLs with labels  		//  		LLUrlEntrySLLabel url; -		boost::regex r = url.getPattern(); +		boost::wregex r = url.getPattern();  		testRegex("invalid wiki url [1]", r,  				  "[secondlife:///app/]", | 
