diff options
-rwxr-xr-x | indra/llcommon/CMakeLists.txt | 5 | ||||
-rw-r--r-- | indra/llcommon/lluriparser.cpp | 228 | ||||
-rw-r--r-- | indra/llcommon/lluriparser.h | 84 | ||||
-rwxr-xr-x | indra/llui/CMakeLists.txt | 3 | ||||
-rwxr-xr-x | indra/llui/lltextbase.cpp | 7 | ||||
-rwxr-xr-x | indra/llui/lltextutil.cpp | 91 | ||||
-rwxr-xr-x | indra/llui/lltextutil.h | 19 | ||||
-rwxr-xr-x | indra/llui/llurlentry.cpp | 21 | ||||
-rwxr-xr-x | indra/llui/llurlentry.h | 6 | ||||
-rwxr-xr-x | indra/llui/llurlregistry.cpp | 6 |
10 files changed, 338 insertions, 132 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 763f5a3521..debb42fb5f 100755 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -12,12 +12,14 @@ include(GoogleBreakpad) include(GooglePerfTools) include(Copy3rdPartyLibs) include(ZLIB) +include(URIPARSER) include_directories( ${EXPAT_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS} ${BREAKPAD_INCLUDE_DIRECTORIES} + ${URIPARSER_INCLUDE_DIRS} ) # add_executable(lltreeiterators lltreeiterators.cpp) @@ -103,6 +105,7 @@ set(llcommon_SOURCE_FILES lltracerecording.cpp lltracethreadrecorder.cpp lluri.cpp + lluriparser.cpp lluuid.cpp llworkerthread.cpp timing.cpp @@ -217,6 +220,7 @@ set(llcommon_HEADER_FILES llunits.h llunittype.h lluri.h + lluriparser.h lluuid.h llwin32headers.h llwin32headerslean.h @@ -261,6 +265,7 @@ target_link_libraries( ${BOOST_PROGRAM_OPTIONS_LIBRARY} ${BOOST_REGEX_LIBRARY} ${GOOGLE_PERFTOOLS_LIBRARIES} + ${URIPARSER_LIBRARIES} ) if (DARWIN) diff --git a/indra/llcommon/lluriparser.cpp b/indra/llcommon/lluriparser.cpp new file mode 100644 index 0000000000..ef4481d32f --- /dev/null +++ b/indra/llcommon/lluriparser.cpp @@ -0,0 +1,228 @@ +/** + * @file lluriparser.cpp + * @author Protey + * @date 2014-10-07 + * @brief Implementation of the LLUriParser class. + * + * $LicenseInfo:firstyear=2014&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "lluriparser.h" + +LLUriParser::LLUriParser(const std::string& u) : mTmpScheme(false), mRes(0) +{ + mState.uri = &mUri; + + if (u.find("://") == std::string::npos) + { + mNormalizedUri = "http://"; + mTmpScheme = true; + } + + mNormalizedUri += u.c_str(); + + mRes = parse(); +} + +LLUriParser::~LLUriParser() +{ + uriFreeUriMembersA(&mUri); +} + +S32 LLUriParser::parse() +{ + mRes = uriParseUriA(&mState, mNormalizedUri.c_str()); + return mRes; +} + +const char * LLUriParser::scheme() const +{ + return mScheme.c_str(); +} + +void LLUriParser::sheme(const std::string& s) +{ + mTmpScheme = !s.size(); + mScheme = s; +} + +const char * LLUriParser::port() const +{ + return mPort.c_str(); +} + +void LLUriParser::port(const std::string& s) +{ + mPort = s; +} + +const char * LLUriParser::host() const +{ + return mHost.c_str(); +} + +void LLUriParser::host(const std::string& s) +{ + mHost = s; +} + +const char * LLUriParser::path() const +{ + return mPath.c_str(); +} + +void LLUriParser::path(const std::string& s) +{ + mPath = s; +} + +const char * LLUriParser::query() const +{ + return mQuery.c_str(); +} + +void LLUriParser::query(const std::string& s) +{ + mQuery = s; +} + +const char * LLUriParser::fragment() const +{ + return mFragment.c_str(); +} + +void LLUriParser::fragment(const std::string& s) +{ + mFragment = s; +} + +void LLUriParser::textRangeToString(UriTextRangeA& textRange, std::string& str) +{ + S32 len = textRange.afterLast - textRange.first; + if (len) + { + str = textRange.first; + str = str.substr(0, len); + } +} + +void LLUriParser::extractParts() +{ + if (mTmpScheme) + { + mScheme.clear(); + } + else + { + textRangeToString(mUri.scheme, mScheme); + } + + textRangeToString(mUri.hostText, mHost); + textRangeToString(mUri.portText, mPort); + textRangeToString(mUri.query, mQuery); + textRangeToString(mUri.fragment, mFragment); + + UriPathSegmentA * pathHead = mUri.pathHead; + while (pathHead) + { + std::string partOfPath; + textRangeToString(pathHead->text, partOfPath); + + mPath += '/'; + mPath += partOfPath; + + pathHead = pathHead->next; + } +} + +S32 LLUriParser::normalize() +{ + if (!mRes) + { + mRes = uriNormalizeSyntaxExA(&mUri, URI_NORMALIZE_SCHEME | URI_NORMALIZE_HOST); + + if (!mRes) + { + S32 chars_required; + mRes = uriToStringCharsRequiredA(&mUri, &chars_required); + + if (!mRes) + { + chars_required++; + std::vector<char> label_buf(chars_required); + mRes = uriToStringA(&label_buf[0], &mUri, chars_required, NULL); + + if (!mRes) + { + mNormalizedUri = &label_buf[mTmpScheme ? 7 : 0]; + } + } + } + } + + return mRes; +} + +void LLUriParser::glue(std::string& uri) const +{ + if (mScheme.size()) + { + uri = mScheme; + uri += "://"; + } + + uri += mHost; + + if (mPort.size()) + { + uri += ':'; + uri += mPort; + } + + uri += mPath; + + if (mQuery.size()) + { + uri += '?'; + uri += mQuery; + + if (mFragment.size()) + { + uri += '#'; + uri += mFragment; + } + } +} + +bool LLUriParser::test() const +{ + std::string uri; + glue(uri); + + return uri == mNormalizedUri; +} + +const char * LLUriParser::normalizedUri() const +{ + return mNormalizedUri.c_str(); +} diff --git a/indra/llcommon/lluriparser.h b/indra/llcommon/lluriparser.h new file mode 100644 index 0000000000..719f916837 --- /dev/null +++ b/indra/llcommon/lluriparser.h @@ -0,0 +1,84 @@ +/** + * @file lluriparser.h + * @author Protey + * @date 20146-10-07 + * @brief Declaration of the UriParser class. + * + * $LicenseInfo:firstyear=2014&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLURIPARSER_H +#define LL_LLURIPARSER_H + +#include <string> +#include "uriparser/Uri.h" + +class LL_COMMON_API LLUriParser +{ +public: + LLUriParser(const std::string& u); + virtual ~LLUriParser(); + + const char * scheme() const; + void sheme (const std::string& s); + + const char * port() const; + void port (const std::string& s); + + const char * host() const; + void host (const std::string& s); + + const char * path() const; + void path (const std::string& s); + + const char * query() const; + void query (const std::string& s); + + const char * fragment() const; + void fragment (const std::string& s); + + const char * normalizedUri() const; + + void extractParts(); + void glue(std::string& uri) const; + bool test() const; + S32 normalize(); + +private: + S32 parse(); + void textRangeToString(UriTextRangeA& textRange, std::string& str); + std::string mScheme; + std::string mHost; + std::string mPort; + std::string mPath; + std::string mQuery; + std::string mFragment; + std::string mNormalizedUri; + + UriParserStateA mState; + UriUriA mUri; + + S32 mRes; + bool mTmpScheme; +}; + +#endif // LL_LLURIPARSER_H diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 24fdc2268d..52738aeb6f 100755 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -12,7 +12,6 @@ include(LLRender) include(LLWindow) include(LLVFS) include(LLXML) -include(URIPARSER) include_directories( ${LLCOMMON_INCLUDE_DIRS} @@ -29,7 +28,6 @@ include_directories( include_directories(SYSTEM ${LLCOMMON_SYSTEM_INCLUDE_DIRS} ${LLXML_SYSTEM_INCLUDE_DIRS} - ${URIPARSER_INCLUDE_DIRS} ) set(llui_SOURCE_FILES @@ -280,7 +278,6 @@ target_link_libraries(llui ${LLXML_LIBRARIES} ${LLMATH_LIBRARIES} ${HUNSPELL_LIBRARY} - ${URIPARSER_LIBRARIES} ${LLCOMMON_LIBRARIES} # must be after llimage, llwindow, llrender ) diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index fee271b943..09f923e74f 100755 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -38,6 +38,7 @@ #include "lltextutil.h" #include "lltooltip.h" #include "lluictrl.h" +#include "lluriparser.h" #include "llurlaction.h" #include "llurlregistry.h" #include "llview.h" @@ -2061,11 +2062,9 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para // add icon before url if need LLTextUtil::processUrlMatch(&match, this, isContentTrusted() || match.isTrusted()); - std::string label = match.getLabel(); - LLTextUtil::normalizeUri(label); - // output the styled Url - appendAndHighlightTextImpl(label, part, link_params, match.underlineOnHoverOnly()); + //appendAndHighlightTextImpl(label, part, link_params, match.underlineOnHoverOnly()); + appendAndHighlightTextImpl(match.getLabel(), part, link_params, match.underlineOnHoverOnly()); // set the tooltip for the Url label if (! match.getTooltip().empty()) diff --git a/indra/llui/lltextutil.cpp b/indra/llui/lltextutil.cpp index b67daf427b..fff04b34f2 100755 --- a/indra/llui/lltextutil.cpp +++ b/indra/llui/lltextutil.cpp @@ -30,8 +30,6 @@ #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) @@ -106,93 +104,4 @@ 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 176b4ba071..1be81ffd62 100755 --- a/indra/llui/lltextutil.h +++ b/indra/llui/lltextutil.h @@ -74,25 +74,6 @@ namespace LLTextUtil */ 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 3ebf06eefa..c06d6144b9 100755 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -31,14 +31,16 @@ #include "lluri.h" #include "llurlmatch.h" #include "llurlregistry.h" +#include "lluriparser.h" #include "llavatarnamecache.h" #include "llcachename.h" #include "lltrans.h" -#include "lltextutil.h" #include "lluicolortable.h" #include "message.h" +#include "uriparser/Uri.h" + #define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))" // Utility functions @@ -346,8 +348,8 @@ 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*", +{ + mPattern = boost::regex("\\b(https?://)?([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(:\\d{1,5})?(/\\S*)?\\b", boost::regex::perl|boost::regex::icase); mIcon = "Hand"; @@ -356,19 +358,14 @@ LLUrlEntrySeconlifeURL::LLUrlEntrySeconlifeURL() 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; + LLUriParser up(url); + up.extractParts(); + return up.host(); } std::string LLUrlEntrySeconlifeURL::getTooltip(const std::string &url) const { - std::string local_url(url); - LLTextUtil::normalizeUri(local_url); - return local_url; + return url; } // diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index f75d773803..1cb11cdb1c 100755 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -176,9 +176,9 @@ 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; + 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; diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index 462b3d6979..9e8d8d01f1 100755 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -27,6 +27,7 @@ #include "linden_common.h" #include "llurlregistry.h" +#include "lluriparser.h" #include <boost/regex.hpp> @@ -207,6 +208,11 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL { // fill in the LLUrlMatch object and return it std::string url = text.substr(match_start, match_end - match_start + 1); + + LLUriParser up(url); + up.normalize(); + url = up.normalizedUri(); + match.setValues(match_start, match_end, match_entry->getUrl(url), match_entry->getLabel(url, cb), |