llurldispatcher.cpp

Go to the documentation of this file.
00001 
00031 #include "llviewerprecompiledheaders.h"
00032 
00033 #include "llurldispatcher.h"
00034 
00035 // viewer includes
00036 #include "llagent.h"                    // teleportViaLocation()
00037 #include "llcommandhandler.h"
00038 #include "llfloaterurldisplay.h"
00039 #include "llfloaterdirectory.h"
00040 #include "llfloaterhtmlhelp.h"
00041 //#include "llfloaterworldmap.h"
00042 #include "llpanellogin.h"
00043 #include "llstartup.h"                  // gStartupState
00044 #include "llurlsimstring.h"
00045 #include "llviewerwindow.h"             // alertXml()
00046 #include "llworldmap.h"
00047 
00048 // library includes
00049 #include "llsd.h"
00050 
00051 // system includes
00052 #include <boost/tokenizer.hpp>
00053 
00054 const std::string SLURL_SL_HELP_PREFIX          = "secondlife://app.";
00055 const std::string SLURL_SL_PREFIX                       = "sl://";
00056 const std::string SLURL_SECONDLIFE_PREFIX       = "secondlife://";
00057 const std::string SLURL_SLURL_PREFIX            = "http://slurl.com/secondlife/";
00058 
00059 const std::string SLURL_APP_TOKEN = "app/";
00060 
00061 class LLURLDispatcherImpl
00062 {
00063 public:
00064         static bool isSLURL(const std::string& url);
00065 
00066         static bool isSLURLCommand(const std::string& url);
00067 
00068         static bool dispatch(const std::string& url);
00069                 // returns true if handled
00070 
00071         static bool dispatchRightClick(const std::string& url);
00072 
00073 private:
00074         static bool dispatchCore(const std::string& url, bool right_mouse);
00075                 // handles both left and right click
00076 
00077         static bool dispatchHelp(const std::string& url, BOOL right_mouse);
00078                 // Handles sl://app.floater.html.help by showing Help floater.
00079                 // Returns true if handled.
00080 
00081         static bool dispatchApp(const std::string& url, BOOL right_mouse);
00082                 // Handles secondlife://app/agent/<agent_id>/about and similar
00083                 // by showing panel in Search floater.
00084                 // Returns true if handled.
00085 
00086         static bool dispatchRegion(const std::string& url, BOOL right_mouse);
00087                 // handles secondlife://Ahern/123/45/67/
00088                 // Returns true if handled.
00089 
00090         static void regionHandleCallback(U64 handle, const std::string& url,
00091                 const LLUUID& snapshot_id, bool teleport);
00092                 // Called by LLWorldMap when a region name has been resolved to a
00093                 // location in-world, used by places-panel display.
00094 
00095         static bool matchPrefix(const std::string& url, const std::string& prefix);
00096         
00097         static std::string stripProtocol(const std::string& url);
00098 
00099         friend class LLTeleportHandler;
00100 };
00101 
00102 // static
00103 bool LLURLDispatcherImpl::isSLURL(const std::string& url)
00104 {
00105         if (matchPrefix(url, SLURL_SL_HELP_PREFIX)) return true;
00106         if (matchPrefix(url, SLURL_SL_PREFIX)) return true;
00107         if (matchPrefix(url, SLURL_SECONDLIFE_PREFIX)) return true;
00108         if (matchPrefix(url, SLURL_SLURL_PREFIX)) return true;
00109         return false;
00110 }
00111 
00112 // static
00113 bool LLURLDispatcherImpl::isSLURLCommand(const std::string& url)
00114 {
00115         if (matchPrefix(url, SLURL_SL_PREFIX + SLURL_APP_TOKEN)
00116                 || matchPrefix(url, SLURL_SECONDLIFE_PREFIX + "/" + SLURL_APP_TOKEN)
00117                 || matchPrefix(url, SLURL_SLURL_PREFIX + SLURL_APP_TOKEN) )
00118         {
00119                 return true;
00120         }
00121         return false;
00122 }
00123 
00124 // static
00125 bool LLURLDispatcherImpl::dispatchCore(const std::string& url, bool right_mouse)
00126 {
00127         if (url.empty()) return false;
00128         if (dispatchHelp(url, right_mouse)) return true;
00129         if (dispatchApp(url, right_mouse)) return true;
00130         if (dispatchRegion(url, right_mouse)) return true;
00131         return false;
00132 }
00133 
00134 // static
00135 bool LLURLDispatcherImpl::dispatch(const std::string& url)
00136 {
00137         llinfos << "url: " << url << llendl;
00138         return dispatchCore(url, false);        // not right click
00139 }
00140 
00141 // static
00142 bool LLURLDispatcherImpl::dispatchRightClick(const std::string& url)
00143 {
00144         llinfos << "url: " << url << llendl;
00145         return dispatchCore(url, true); // yes right click
00146 }
00147 // static
00148 bool LLURLDispatcherImpl::dispatchHelp(const std::string& url, BOOL right_mouse)
00149 {
00150         if (matchPrefix(url, SLURL_SL_HELP_PREFIX))
00151         {
00152 #if LL_LIBXUL_ENABLED
00153                 gViewerHtmlHelp.show();
00154 #endif // LL_LIBXUL_ENABLED
00155                 return true;
00156         }
00157         return false;
00158 }
00159 
00160 // static
00161 bool LLURLDispatcherImpl::dispatchApp(const std::string& url, BOOL right_mouse)
00162 {
00163         if (!isSLURL(url))
00164         {
00165                 return false;
00166         }
00167         std::string s = stripProtocol(url);
00168 
00169         // At this point, "secondlife://app/foo/bar/baz/" should be left
00170         // as:  "app/foo/bar/baz/"
00171         typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
00172         boost::char_separator<char> sep("/", "", boost::drop_empty_tokens);
00173         tokenizer tokens(s, sep);
00174         tokenizer::iterator it = tokens.begin();
00175         tokenizer::iterator end = tokens.end();
00176 
00177         // Build parameter list suitable for LLDispatcher dispatch
00178         if (it == end) return false;
00179         if (*it != "app") return false;
00180         ++it;
00181 
00182         if (it == end) return false;
00183         std::string cmd = *it;
00184         ++it;
00185 
00186         std::vector<std::string> params;
00187         for ( ; it != end; ++it)
00188         {
00189                 params.push_back(*it);
00190         }
00191 
00192         bool handled = LLCommandDispatcher::dispatch(cmd, params);
00193         if (handled) return true;
00194 
00195         // Inform the user we can't handle this
00196         std::map<std::string, std::string> args;
00197         args["[SLURL]"] = url;
00198         gViewerWindow->alertXml("BadURL", args);
00199         // This was a SLURL with a /app prefix, and we "handled" it by displaying an error dialog,
00200         // so return true.  It doesn't need to be parsed any further.
00201         return true;
00202 }
00203 
00204 // static
00205 bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, BOOL right_mouse)
00206 {
00207         if (!isSLURL(url))
00208         {
00209                 return false;
00210         }
00211 
00212         // Before we're logged in, need to update the startup screen
00213         // to tell the user where they are going.
00214         if (LLStartUp::getStartupState() < STATE_CLEANUP)
00215         {
00216                 // Parse it and stash in globals, it will be dispatched in
00217                 // STATE_CLEANUP.
00218                 LLURLSimString::setString(url);
00219                 // We're at the login screen, so make sure user can see
00220                 // the login location box to know where they are going.
00221                 LLPanelLogin::refreshLocation( true );
00222                 return true;
00223         }
00224 
00225         std::string sim_string = stripProtocol(url);
00226         std::string region_name;
00227         S32 x = 128;
00228         S32 y = 128;
00229         S32 z = 0;
00230         LLURLSimString::parse(sim_string, &region_name, &x, &y, &z);
00231 
00232         LLFloaterURLDisplay* url_displayp = LLFloaterURLDisplay::getInstance(LLSD());
00233         url_displayp->setName(region_name);
00234 
00235         // Request a region handle by name
00236         gWorldMap->sendNamedRegionRequest(region_name,
00237                 LLURLDispatcherImpl::regionHandleCallback,
00238                 url,
00239                 false); // don't teleport
00240         return true;
00241 }
00242 
00243 /*static*/
00244 void LLURLDispatcherImpl::regionHandleCallback(U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport)
00245 {
00246         std::string sim_string = stripProtocol(url);
00247         std::string region_name;
00248         S32 x = 128;
00249         S32 y = 128;
00250         S32 z = 0;
00251         LLURLSimString::parse(sim_string, &region_name, &x, &y, &z);
00252 
00253         LLVector3 local_pos;
00254         local_pos.mV[VX] = (F32)x;
00255         local_pos.mV[VY] = (F32)y;
00256         local_pos.mV[VZ] = (F32)z;
00257 
00258         if (teleport)
00259         {
00260                 LLVector3d global_pos = from_region_handle(region_handle);
00261                 global_pos += LLVector3d(local_pos);
00262                 gAgent.teleportViaLocation(global_pos);
00263         }
00264         else
00265         {
00266                 // display informational floater, allow user to click teleport btn
00267                 LLFloaterURLDisplay* url_displayp = LLFloaterURLDisplay::getInstance(LLSD());
00268 
00269                 url_displayp->displayParcelInfo(region_handle, local_pos);
00270                 if(snapshot_id.notNull())
00271                 {
00272                         url_displayp->setSnapshotDisplay(snapshot_id);
00273                 }
00274                 std::string locationString = llformat("%s %d, %d, %d", region_name.c_str(), x, y, z);
00275                 url_displayp->setLocationString(locationString);
00276         }
00277 }
00278 
00279 // static
00280 bool LLURLDispatcherImpl::matchPrefix(const std::string& url, const std::string& prefix)
00281 {
00282         std::string test_prefix = url.substr(0, prefix.length());
00283         LLString::toLower(test_prefix);
00284         return test_prefix == prefix;
00285 }
00286 
00287 // static
00288 std::string LLURLDispatcherImpl::stripProtocol(const std::string& url)
00289 {
00290         std::string stripped = url;
00291         if (matchPrefix(stripped, SLURL_SL_HELP_PREFIX))
00292         {
00293                 stripped.erase(0, SLURL_SL_HELP_PREFIX.length());
00294         }
00295         else if (matchPrefix(stripped, SLURL_SL_PREFIX))
00296         {
00297                 stripped.erase(0, SLURL_SL_PREFIX.length());
00298         }
00299         else if (matchPrefix(stripped, SLURL_SECONDLIFE_PREFIX))
00300         {
00301                 stripped.erase(0, SLURL_SECONDLIFE_PREFIX.length());
00302         }
00303         else if (matchPrefix(stripped, SLURL_SLURL_PREFIX))
00304         {
00305                 stripped.erase(0, SLURL_SLURL_PREFIX.length());
00306         }
00307         return stripped;
00308 }
00309 
00310 //---------------------------------------------------------------------------
00311 // Teleportation links are handled here because they are tightly coupled
00312 // to URL parsing and sim-fragment parsing
00313 class LLTeleportHandler : public LLCommandHandler
00314 {
00315 public:
00316         LLTeleportHandler() : LLCommandHandler("teleport") { }
00317         bool handle(const std::vector<std::string>& tokens)
00318         {
00319                 // construct a "normal" SLURL, resolve the region to
00320                 // a global position, and teleport to it
00321                 if (tokens.size() < 1) return false;
00322 
00323                 // Region names may be %20 escaped.
00324                 std::string region_name = LLURLSimString::unescapeRegionName(tokens[0]);
00325 
00326                 // build secondlife://De%20Haro/123/45/67 for use in callback
00327                 std::string url = SLURL_SECONDLIFE_PREFIX;
00328                 for (size_t i = 0; i < tokens.size(); ++i)
00329                 {
00330                         url += tokens[i] + "/";
00331                 }
00332                 gWorldMap->sendNamedRegionRequest(region_name,
00333                         LLURLDispatcherImpl::regionHandleCallback,
00334                         url,
00335                         true);  // teleport
00336                 return true;
00337         }
00338 };
00339 LLTeleportHandler gTeleportHandler;
00340 
00341 //---------------------------------------------------------------------------
00342 
00343 // static
00344 bool LLURLDispatcher::isSLURL(const std::string& url)
00345 {
00346         return LLURLDispatcherImpl::isSLURL(url);
00347 }
00348 
00349 // static
00350 bool LLURLDispatcher::isSLURLCommand(const std::string& url)
00351 {
00352         return LLURLDispatcherImpl::isSLURLCommand(url);
00353 }
00354 
00355 // static
00356 bool LLURLDispatcher::dispatch(const std::string& url)
00357 {
00358         return LLURLDispatcherImpl::dispatch(url);
00359 }
00360 // static
00361 bool LLURLDispatcher::dispatchRightClick(const std::string& url)
00362 {
00363         return LLURLDispatcherImpl::dispatchRightClick(url);
00364 }

Generated on Thu Jul 1 06:09:24 2010 for Second Life Viewer by  doxygen 1.4.7