diff options
Diffstat (limited to 'indra')
-rw-r--r-- | indra/newview/llslurl.cpp | 823 | ||||
-rw-r--r-- | indra/newview/tests/llslurl_test.cpp | 6 |
2 files changed, 412 insertions, 417 deletions
diff --git a/indra/newview/llslurl.cpp b/indra/newview/llslurl.cpp index a9b7b0e417..3858a1b9ce 100644 --- a/indra/newview/llslurl.cpp +++ b/indra/newview/llslurl.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llurlsimstring.cpp (was llsimurlstring.cpp) * @brief Handles "SLURL fragments" like Ahern/123/45 for * startup processing, login screen, prefs, etc. @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -36,7 +36,7 @@ #include "curl/curl.h" const char* LLSLURL::SLURL_HTTP_SCHEME = "http"; const char* LLSLURL::SLURL_HTTPS_SCHEME = "https"; -const char* LLSLURL::SLURL_SECONDLIFE_SCHEME = "secondlife"; +const char* LLSLURL::SLURL_SECONDLIFE_SCHEME = "secondlife"; const char* LLSLURL::SLURL_SECONDLIFE_PATH = "secondlife"; const char* LLSLURL::SLURL_COM = "slurl.com"; // For DnD - even though www.slurl.com redirects to slurl.com in a browser, you can copy and drag @@ -54,480 +54,469 @@ const char* LLSLURL::SIM_LOCATION_LAST = "last"; // resolve a simstring from a slurl LLSLURL::LLSLURL(const std::string& slurl) { - // by default we go to agni. - mType = INVALID; - - if(slurl == SIM_LOCATION_HOME) - { - mType = HOME_LOCATION; - } - else if(slurl.empty() || (slurl == SIM_LOCATION_LAST)) - { - mType = LAST_LOCATION; - } - else - { - LLURI slurl_uri; - // parse the slurl as a uri - if(slurl.find(':') == std::string::npos) - { - // There may be no scheme ('secondlife:' etc.) passed in. In that case - // we want to normalize the slurl by putting the appropriate scheme - // in front of the slurl. So, we grab the appropriate slurl base - // from the grid manager which may be http://slurl.com/secondlife/ for maingrid, or - // https://<hostname>/region/ for Standalone grid (the word region, not the region name) - // these slurls are typically passed in from the 'starting location' box on the login panel, - // where the user can type in <regionname>/<x>/<y>/<z> - std::string fixed_slurl = LLGridManager::getInstance()->getSLURLBase(); - - // the slurl that was passed in might have a prepended /, or not. So, - // we strip off the prepended '/' so we don't end up with http://slurl.com/secondlife/<region>/<x>/<y>/<z> - // or some such. - - if(slurl[0] == '/') - { - fixed_slurl += slurl.substr(1); - } - else - { - fixed_slurl += slurl; - } - // We then load the slurl into a LLURI form - slurl_uri = LLURI(fixed_slurl); - } - else - { - // as we did have a scheme, implying a URI style slurl, we - // simply parse it as a URI - slurl_uri = LLURI(slurl); - } - - LLSD path_array = slurl_uri.pathArray(); - - // determine whether it's a maingrid URI or an Standalone/open style URI - // by looking at the scheme. If it's a 'secondlife:' slurl scheme or - // 'sl:' scheme, we know it's maingrid - - // At the end of this if/else block, we'll have determined the grid, - // and the slurl type (APP or LOCATION) - if(slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME) - { - if (path_array.size() == 0) - { - // um, we need a path... - mType = EMPTY; - return; - } - - // parse a maingrid style slurl. We know the grid is maingrid - // so grab it. - // A location slurl for maingrid (with the special schemes) can be in the form - // secondlife://<regionname>/<x>/<y>/<z> - // or - // secondlife://<Grid>/secondlife/<region>/<x>/<y>/<z> - // where if grid is empty, it specifies Agni - - // An app style slurl for maingrid can be - // secondlife://<Grid>/app/<app parameters> - // where an empty grid implies Agni - - // we'll start by checking the top of the 'path' which will be - // either 'app', 'secondlife', or <x>. - - // default to maingrid - - mGrid = MAINGRID; - - if ((path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH) || - (path_array[0].asString() == LLSLURL::SLURL_APP_PATH)) - { - // it's in the form secondlife://<grid>/(app|secondlife) - // so parse the grid name to derive the grid ID - if (!slurl_uri.hostName().empty()) - { - mGrid = LLGridManager::getInstance()->getGridId(slurl_uri.hostName()); - } - else if(path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH) - { - // If the slurl is in the form secondlife:///secondlife/<region> form, - // then we are in fact on maingrid. - mGrid = MAINGRID; - } - else if(path_array[0].asString() == LLSLURL::SLURL_APP_PATH) - { - // for app style slurls, where no grid name is specified, assume the currently - // selected or logged in grid. - mGrid = LLGridManager::getInstance()->getGridId(); - } - - if(mGrid.empty()) - { - // we couldn't find the grid in the grid manager, so bail - LL_WARNS("AppInit")<<"unable to find grid"<<LL_ENDL; - return; - } - // set the type as appropriate. - if(path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH) - { - mType = LOCATION; - } - else - { - mType = APP; - } - path_array.erase(0); - } - else - { - if(slurl_uri.hostName() == LLSLURL::SLURL_APP_PATH) + // by default we go to agni. + mType = INVALID; + + if (slurl.empty() || (slurl == SIM_LOCATION_LAST)) + { + mType = LAST_LOCATION; + } + else if (slurl == SIM_LOCATION_HOME) + { + mType = HOME_LOCATION; + } + else + { + LLURI slurl_uri; + // parse the slurl as a uri + if (slurl.find(':') == std::string::npos) + { + // There may be no scheme ('secondlife:' etc.) passed in. In that case + // we want to normalize the slurl by putting the appropriate scheme + // in front of the slurl. So, we grab the appropriate slurl base + // from the grid manager which may be http://slurl.com/secondlife/ for maingrid, or + // https://<hostname>/region/ for Standalone grid (the word region, not the region name) + // these slurls are typically passed in from the 'starting location' box on the login panel, + // where the user can type in <regionname>/<x>/<y>/<z> + std::string fixed_slurl = LLGridManager::getInstance()->getSLURLBase(); + + // the slurl that was passed in might have a prepended /, or not. So, + // we strip off the prepended '/' so we don't end up with http://slurl.com/secondlife/<region>/<x>/<y>/<z> + // or some such. + + if (slurl[0] == '/') + { + fixed_slurl += slurl.substr(1); + } + else + { + fixed_slurl += slurl; + } + // We then load the slurl into a LLURI form + slurl_uri = LLURI(fixed_slurl); + } + else + { + // as we did have a scheme, implying a URI style slurl, we + // simply parse it as a URI + slurl_uri = LLURI(slurl); + } + + LLSD path_array = slurl_uri.pathArray(); + + // determine whether it's a maingrid URI or an Standalone/open style URI + // by looking at the scheme. If it's a 'secondlife:' slurl scheme or + // 'sl:' scheme, we know it's maingrid + + // At the end of this if/else block, we'll have determined the grid, + // and the slurl type (APP or LOCATION) + if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME) + { + if (path_array.size() == 0) + { + if (slurl_uri.authority().empty() && slurl_uri.escapedQuery().empty()) + { + mType = EMPTY; + } + // um, we need a path... + return; + } + + // parse a maingrid style slurl. We know the grid is maingrid + // so grab it. + // A location slurl for maingrid (with the special schemes) can be in the form + // secondlife://<regionname>/<x>/<y>/<z> + // or + // secondlife://<Grid>/secondlife/<region>/<x>/<y>/<z> + // where if grid is empty, it specifies Agni + + // An app style slurl for maingrid can be + // secondlife://<Grid>/app/<app parameters> + // where an empty grid implies Agni + + // we'll start by checking the top of the 'path' which will be + // either 'app', 'secondlife', or <x>. + + // default to maingrid + + mGrid = MAINGRID; + + if ((path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH) || + (path_array[0].asString() == LLSLURL::SLURL_APP_PATH)) + { + // it's in the form secondlife://<grid>/(app|secondlife) + // so parse the grid name to derive the grid ID + if (!slurl_uri.hostName().empty()) + { + mGrid = LLGridManager::getInstance()->getGridId(slurl_uri.hostName()); + } + else if(path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH) + { + // If the slurl is in the form secondlife:///secondlife/<region> form, + // then we are in fact on maingrid. + mGrid = MAINGRID; + } + else if(path_array[0].asString() == LLSLURL::SLURL_APP_PATH) + { + // for app style slurls, where no grid name is specified, assume the currently + // selected or logged in grid. + mGrid = LLGridManager::getInstance()->getGridId(); + } + + if (mGrid.empty()) + { + // we couldn't find the grid in the grid manager, so bail + LL_WARNS("AppInit")<<"unable to find grid"<<LL_ENDL; + return; + } + // set the type as appropriate. + if (path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH) + { + mType = LOCATION; + } + else + { + mType = APP; + } + path_array.erase(0); + } + else + { + if (slurl_uri.hostName() == LLSLURL::SLURL_APP_PATH) { mType = APP; } else { // it wasn't a /secondlife/<region> or /app/<params>, so it must be secondlife://<region> - // therefore the hostname will be the region name, and it's a location type - mType = LOCATION; - // 'normalize' it so the region name is in fact the head of the path_array - path_array.insert(0, slurl_uri.hostName()); + // therefore the hostname will be the region name, and it's a location type + mType = LOCATION; + // 'normalize' it so the region name is in fact the head of the path_array + path_array.insert(0, slurl_uri.hostName()); + } + } + } + else if ((slurl_uri.scheme() == LLSLURL::SLURL_HTTP_SCHEME) || + (slurl_uri.scheme() == LLSLURL::SLURL_HTTPS_SCHEME) || + (slurl_uri.scheme() == LLSLURL::SLURL_X_GRID_LOCATION_INFO_SCHEME)) + { + // We're dealing with either a Standalone style slurl or slurl.com slurl + if ((slurl_uri.hostName() == LLSLURL::SLURL_COM) || + (slurl_uri.hostName() == LLSLURL::WWW_SLURL_COM) || + (slurl_uri.hostName() == LLSLURL::MAPS_SECONDLIFE_COM)) + { + // slurl.com implies maingrid + mGrid = MAINGRID; + } + else + { + // Don't try to match any old http://<host>/ URL as a SLurl. + // SLE SLurls will have the grid hostname in the URL, so only + // match http URLs if the hostname matches the grid hostname + // (or its a slurl.com or maps.secondlife.com URL). + if ((slurl_uri.scheme() == LLSLURL::SLURL_HTTP_SCHEME || + slurl_uri.scheme() == LLSLURL::SLURL_HTTPS_SCHEME) && + slurl_uri.hostName() != LLGridManager::getInstance()->getGrid()) + { + return; } - } - } - else if((slurl_uri.scheme() == LLSLURL::SLURL_HTTP_SCHEME) || - (slurl_uri.scheme() == LLSLURL::SLURL_HTTPS_SCHEME) || - (slurl_uri.scheme() == LLSLURL::SLURL_X_GRID_LOCATION_INFO_SCHEME)) - { - // We're dealing with either a Standalone style slurl or slurl.com slurl - if ((slurl_uri.hostName() == LLSLURL::SLURL_COM) || - (slurl_uri.hostName() == LLSLURL::WWW_SLURL_COM) || - (slurl_uri.hostName() == LLSLURL::MAPS_SECONDLIFE_COM)) - { - // slurl.com implies maingrid - mGrid = MAINGRID; - } - else - { - // Don't try to match any old http://<host>/ URL as a SLurl. - // SLE SLurls will have the grid hostname in the URL, so only - // match http URLs if the hostname matches the grid hostname - // (or its a slurl.com or maps.secondlife.com URL). - if ((slurl_uri.scheme() == LLSLURL::SLURL_HTTP_SCHEME || - slurl_uri.scheme() == LLSLURL::SLURL_HTTPS_SCHEME) && - slurl_uri.hostName() != LLGridManager::getInstance()->getGrid()) - { - return; - } - - // As it's a Standalone grid/open, we will always have a hostname, as Standalone/open style - // urls are properly formed, unlike the stinky maingrid style - mGrid = slurl_uri.hostName(); - } - if (path_array.size() == 0) - { - // um, we need a path... - return; - } - - // we need to normalize the urls so - // the path portion starts with the 'command' that we want to do - // it can either be region or app. - if ((path_array[0].asString() == LLSLURL::SLURL_REGION_PATH) || - (path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH)) - { - // strip off 'region' or 'secondlife' - path_array.erase(0); - // it's a location - mType = LOCATION; - } - else if (path_array[0].asString() == LLSLURL::SLURL_APP_PATH) - { - mType = APP; - path_array.erase(0); - // leave app appended. - } - else - { - // not a valid https/http/x-grid-location-info slurl, so it'll likely just be a URL - return; - } - } - else - { - // invalid scheme, so bail - return; - } - - - if(path_array.size() == 0) - { - // we gotta have some stuff after the specifier as to whether it's a region or command - return; - } - - // now that we know whether it's an app slurl or a location slurl, - // parse the slurl into the proper data structures. - if(mType == APP) - { - // grab the app command type and strip it (could be a command to jump somewhere, - // or whatever ) - mAppCmd = path_array[0].asString(); - path_array.erase(0); - - // Grab the parameters - mAppPath = path_array; - // and the query - mAppQuery = slurl_uri.query(); - mAppQueryMap = slurl_uri.queryMap(); - return; - } - else if(mType == LOCATION) - { - // at this point, head of the path array should be [ <region>, <x>, <y>, <z> ] where x, y and z - // are collectively optional - // are optional - - mRegion = LLURI::unescape(path_array[0].asString()); - - if(LLStringUtil::containsNonprintable(mRegion)) - { - LLStringUtil::stripNonprintable(mRegion); - } - - path_array.erase(0); - - // parse the x, y, and optionally z - if(path_array.size() >= 2) - { - - mPosition = LLVector3(path_array); // this construction handles LLSD without all components (values default to 0.f) - if((F32(mPosition[VX]) < 0.f) || - (mPosition[VX] > REGION_WIDTH_METERS) || - (F32(mPosition[VY]) < 0.f) || - (mPosition[VY] > REGION_WIDTH_METERS) || - (F32(mPosition[VZ]) < 0.f) || - (mPosition[VZ] > REGION_HEIGHT_METERS)) - { - mType = INVALID; - return; - } - - } - else - { - // if x, y and z were not fully passed in, go to the middle of the region. - // teleport will adjust the actual location to make sure you're on the ground - // and such - mPosition = LLVector3(REGION_WIDTH_METERS/2, REGION_WIDTH_METERS/2, 0); - } - } - } -} + // As it's a Standalone grid/open, we will always have a hostname, as Standalone/open style + // urls are properly formed, unlike the stinky maingrid style + mGrid = slurl_uri.hostName(); + } + if (path_array.size() == 0) + { + // um, we need a path... + return; + } + + // we need to normalize the urls so + // the path portion starts with the 'command' that we want to do + // it can either be region or app. + if ((path_array[0].asString() == LLSLURL::SLURL_REGION_PATH) || + (path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH)) + { + // strip off 'region' or 'secondlife' + path_array.erase(0); + // it's a location + mType = LOCATION; + } + else if (path_array[0].asString() == LLSLURL::SLURL_APP_PATH) + { + mType = APP; + path_array.erase(0); + // leave app appended. + } + else + { + // not a valid https/http/x-grid-location-info slurl, so it'll likely just be a URL + return; + } + } + else + { + // invalid scheme, so bail + return; + } + + if (path_array.size() == 0) + { + // we gotta have some stuff after the specifier as to whether it's a region or command + return; + } + + // now that we know whether it's an app slurl or a location slurl, + // parse the slurl into the proper data structures. + if (mType == APP) + { + // grab the app command type and strip it (could be a command to jump somewhere, + // or whatever ) + mAppCmd = path_array[0].asString(); + path_array.erase(0); + + // Grab the parameters + mAppPath = path_array; + // and the query + mAppQuery = slurl_uri.query(); + mAppQueryMap = slurl_uri.queryMap(); + return; + } + else if (mType == LOCATION) + { + // at this point, head of the path array should be [ <region>, <x>, <y>, <z> ] where x, y and z + // are collectively optional + // are optional + + mRegion = LLURI::unescape(path_array[0].asString()); + + if (LLStringUtil::containsNonprintable(mRegion)) + { + LLStringUtil::stripNonprintable(mRegion); + } + + path_array.erase(0); + + // parse the x, y, and optionally z + if (path_array.size() >= 2) + { + mPosition = LLVector3(path_array); // this construction handles LLSD without all components (values default to 0.f) + if ((F32(mPosition[VX]) < 0.f) || (mPosition[VX] > REGION_WIDTH_METERS) || + (F32(mPosition[VY]) < 0.f) || (mPosition[VY] > REGION_WIDTH_METERS) || + (F32(mPosition[VZ]) < 0.f) || (mPosition[VZ] > REGION_HEIGHT_METERS)) + { + mType = INVALID; + return; + } + } + else + { + // if x, y and z were not fully passed in, go to the middle of the region. + // teleport will adjust the actual location to make sure you're on the ground + // and such + mPosition = LLVector3(REGION_WIDTH_METERS / 2, REGION_WIDTH_METERS / 2, 0); + } + } + } +} // Create a slurl for the middle of the region -LLSLURL::LLSLURL(const std::string& grid, - const std::string& region) +LLSLURL::LLSLURL(const std::string& grid, const std::string& region) { - mGrid = grid; - mRegion = region; - mType = LOCATION; - mPosition = LLVector3((F64)REGION_WIDTH_METERS/2, (F64)REGION_WIDTH_METERS/2, 0); + mGrid = grid; + mRegion = region; + mType = LOCATION; + mPosition = LLVector3((F64)REGION_WIDTH_METERS / 2, (F64)REGION_WIDTH_METERS / 2, 0); } - - // create a slurl given the position. The position will be modded with the region // width handling global positions as well -LLSLURL::LLSLURL(const std::string& grid, - const std::string& region, - const LLVector3& position) +LLSLURL::LLSLURL(const std::string& grid, + const std::string& region, + const LLVector3& position) { - mGrid = grid; - mRegion = region; - S32 x = ll_round( (F32)fmod( position[VX], (F32)REGION_WIDTH_METERS ) ); - S32 y = ll_round( (F32)fmod( position[VY], (F32)REGION_WIDTH_METERS ) ); - S32 z = ll_round( (F32)position[VZ] ); - mType = LOCATION; - mPosition = LLVector3(x, y, z); + mGrid = grid; + mRegion = region; + S32 x = ll_round((F32)fmod(position[VX], (F32)REGION_WIDTH_METERS)); + S32 y = ll_round((F32)fmod(position[VY], (F32)REGION_WIDTH_METERS)); + S32 z = ll_round((F32)position[VZ]); + mType = LOCATION; + mPosition = LLVector3(x, y, z); } - // create a simstring -LLSLURL::LLSLURL(const std::string& region, - const LLVector3& position) +LLSLURL::LLSLURL(const std::string& region, + const LLVector3& position) { - *this = LLSLURL(LLGridManager::getInstance()->getGridId(), - region, position); + *this = LLSLURL(LLGridManager::getInstance()->getGridId(), region, position); } // create a slurl from a global position -LLSLURL::LLSLURL(const std::string& grid, - const std::string& region, - const LLVector3d& global_position) +LLSLURL::LLSLURL(const std::string& grid, + const std::string& region, + const LLVector3d& global_position) { - *this = LLSLURL(LLGridManager::getInstance()->getGridId(grid), - region, LLVector3(global_position.mdV[VX], - global_position.mdV[VY], - global_position.mdV[VZ])); + *this = LLSLURL(LLGridManager::getInstance()->getGridId(grid), region, + LLVector3(global_position.mdV[VX], global_position.mdV[VY], global_position.mdV[VZ])); } // create a slurl from a global position -LLSLURL::LLSLURL(const std::string& region, - const LLVector3d& global_position) +LLSLURL::LLSLURL(const std::string& region, + const LLVector3d& global_position) { - *this = LLSLURL(LLGridManager::getInstance()->getGridId(), - region, global_position); + *this = LLSLURL(LLGridManager::getInstance()->getGridId(), + region, global_position); } LLSLURL::LLSLURL(const std::string& command, const LLUUID&id, const std::string& verb) { - mType = APP; - mAppCmd = command; - mAppPath = LLSD::emptyArray(); - mAppPath.append(LLSD(id)); - mAppPath.append(LLSD(verb)); + mType = APP; + mAppCmd = command; + mAppPath = LLSD::emptyArray(); + mAppPath.append(LLSD(id)); + mAppPath.append(LLSD(verb)); } - std::string LLSLURL::getSLURLString() const { - switch(mType) - { - case HOME_LOCATION: - return SIM_LOCATION_HOME; - case LAST_LOCATION: - return SIM_LOCATION_LAST; - case LOCATION: - { - // lookup the grid - S32 x = ll_round( (F32)mPosition[VX] ); - S32 y = ll_round( (F32)mPosition[VY] ); - S32 z = ll_round( (F32)mPosition[VZ] ); - return LLGridManager::getInstance()->getSLURLBase(mGrid) + - LLURI::escape(mRegion) + llformat("/%d/%d/%d",x,y,z); - } - case APP: - { - std::ostringstream app_url; - app_url << LLGridManager::getInstance()->getAppSLURLBase() << "/" << mAppCmd; - for(LLSD::array_const_iterator i = mAppPath.beginArray(); - i != mAppPath.endArray(); - i++) - { - app_url << "/" << i->asString(); - } - if(mAppQuery.length() > 0) - { - app_url << "?" << mAppQuery; - } - return app_url.str(); - } - default: - LL_WARNS("AppInit") << "Unexpected SLURL type for SLURL string" << (int)mType << LL_ENDL; - return std::string(); - } + switch (mType) + { + case HOME_LOCATION: + return SIM_LOCATION_HOME; + case LAST_LOCATION: + return SIM_LOCATION_LAST; + case LOCATION: + { + // lookup the grid + S32 x = ll_round((F32)mPosition[VX]); + S32 y = ll_round((F32)mPosition[VY]); + S32 z = ll_round((F32)mPosition[VZ]); + return LLGridManager::getInstance()->getSLURLBase(mGrid) + + LLURI::escape(mRegion) + llformat("/%d/%d/%d", x, y, z); + } + case APP: + { + std::ostringstream app_url; + app_url << LLGridManager::getInstance()->getAppSLURLBase() << "/" << mAppCmd; + for (LLSD::array_const_iterator i = mAppPath.beginArray(); + i != mAppPath.endArray(); + i++) + { + app_url << "/" << i->asString(); + } + if (mAppQuery.length() > 0) + { + app_url << "?" << mAppQuery; + } + return app_url.str(); + } + default: + LL_WARNS("AppInit") << "Unexpected SLURL type for SLURL string" << (int)mType << LL_ENDL; + return std::string(); + } } std::string LLSLURL::getLoginString() const { - - std::stringstream unescaped_start; - switch(mType) - { - case LOCATION: - unescaped_start << "uri:" - << mRegion << "&" - << ll_round(mPosition[0]) << "&" - << ll_round(mPosition[1]) << "&" - << ll_round(mPosition[2]); - break; - case HOME_LOCATION: - unescaped_start << "home"; - break; - case LAST_LOCATION: - unescaped_start << "last"; - break; - default: - LL_WARNS("AppInit") << "Unexpected SLURL type ("<<(int)mType <<")for login string"<< LL_ENDL; - break; - } - return xml_escape_string(unescaped_start.str()); + std::stringstream unescaped_start; + switch (mType) + { + case LOCATION: + unescaped_start << "uri:" + << mRegion << "&" + << ll_round(mPosition[0]) << "&" + << ll_round(mPosition[1]) << "&" + << ll_round(mPosition[2]); + break; + case HOME_LOCATION: + unescaped_start << "home"; + break; + case LAST_LOCATION: + unescaped_start << "last"; + break; + default: + LL_WARNS("AppInit") << "Unexpected SLURL type (" << (int)mType << ")for login string" << LL_ENDL; + break; + } + return xml_escape_string(unescaped_start.str()); } -bool LLSLURL::operator==(const LLSLURL& rhs) +bool LLSLURL::operator ==(const LLSLURL& rhs) { - if(rhs.mType != mType) return false; - switch(mType) - { - case LOCATION: - return ((mGrid == rhs.mGrid) && - (mRegion == rhs.mRegion) && - (mPosition == rhs.mPosition)); - case APP: - return getSLURLString() == rhs.getSLURLString(); - - case HOME_LOCATION: - case LAST_LOCATION: - return true; - default: - return false; - } + if (rhs.mType != mType) + return false; + + switch (mType) + { + case LOCATION: + return (mGrid == rhs.mGrid) && + (mRegion == rhs.mRegion) && + (mPosition == rhs.mPosition); + + case APP: + return getSLURLString() == rhs.getSLURLString(); + + case HOME_LOCATION: + case LAST_LOCATION: + return true; + } + + return false; } bool LLSLURL::operator !=(const LLSLURL& rhs) { - return !(*this == rhs); + return !(*this == rhs); } std::string LLSLURL::getLocationString() const { - return llformat("%s/%d/%d/%d", - mRegion.c_str(), - (int)ll_round(mPosition[0]), - (int)ll_round(mPosition[1]), - (int)ll_round(mPosition[2])); + return llformat("%s/%d/%d/%d", + mRegion.c_str(), + (int)ll_round(mPosition[0]), + (int)ll_round(mPosition[1]), + (int)ll_round(mPosition[2])); } // static -const std::string LLSLURL::typeName[NUM_SLURL_TYPES] = +const std::string LLSLURL::typeName[NUM_SLURL_TYPES] = { - "INVALID", - "LOCATION", - "HOME_LOCATION", - "LAST_LOCATION", - "APP", - "HELP" + "INVALID", + "LOCATION", + "HOME_LOCATION", + "LAST_LOCATION", + "APP", + "HELP", + "EMPTY" }; - + std::string LLSLURL::getTypeString(SLURL_TYPE type) { - std::string name; - if ( type >= INVALID && type < NUM_SLURL_TYPES ) - { - name = LLSLURL::typeName[type]; - } - else - { - name = llformat("Out of Range (%d)",type); - } - return name; + std::string name; + if (type >= INVALID && type < NUM_SLURL_TYPES) + { + name = LLSLURL::typeName[type]; + } + else + { + name = llformat("Out of Range (%d)", type); + } + return name; } - std::string LLSLURL::asString() const { std::ostringstream result; result - << " mType: " << LLSLURL::getTypeString(mType) - << " mGrid: " + getGrid() - << " mRegion: " + getRegion() - << " mPosition: " << mPosition - << " mAppCmd:" << getAppCmd() - << " mAppPath:" + getAppPath().asString() - << " mAppQueryMap:" + getAppQueryMap().asString() - << " mAppQuery: " + getAppQuery() - ; - + << " mType: " << LLSLURL::getTypeString(mType) + << " mGrid: " + getGrid() + << " mRegion: " + getRegion() + << " mPosition: " << mPosition + << " mAppCmd:" << getAppCmd() + << " mAppPath:" + getAppPath().asString() + << " mAppQueryMap:" + getAppQueryMap().asString() + << " mAppQuery: " + getAppQuery() + ; + return result.str(); } - diff --git a/indra/newview/tests/llslurl_test.cpp b/indra/newview/tests/llslurl_test.cpp index eabf922875..8d21b6ed69 100644 --- a/indra/newview/tests/llslurl_test.cpp +++ b/indra/newview/tests/llslurl_test.cpp @@ -187,6 +187,12 @@ namespace tut ensure_equals("maps.secondlife.com slurl, region + coords", slurl.getSLURLString(), "http://maps.secondlife.com/secondlife/myregion/1/2/3"); + slurl = LLSLURL("secondlife://"); + ensure_equals("secondlife: slurl, empty - type", slurl.getType(), LLSLURL::EMPTY); + + slurl = LLSLURL("secondlife:///"); + ensure_equals("secondlife: slurl, root - type", slurl.getType(), LLSLURL::EMPTY); + slurl = LLSLURL("secondlife://myregion"); ensure_equals("secondlife: slurl, region only - type", slurl.getType(), LLSLURL::LOCATION); ensure_equals("secondlife: slurl, region only", slurl.getSLURLString(), |