00001
00031 #include "llviewerprecompiledheaders.h"
00032
00033 #include "llurldispatcher.h"
00034
00035
00036 #include "llagent.h"
00037 #include "llcommandhandler.h"
00038 #include "llfloaterurldisplay.h"
00039 #include "llfloaterdirectory.h"
00040 #include "llfloaterhtml.h"
00041 #include "llfloaterworldmap.h"
00042 #include "llfloaterhtmlhelp.h"
00043 #include "llpanellogin.h"
00044 #include "llstartup.h"
00045 #include "llurlsimstring.h"
00046 #include "llviewerwindow.h"
00047 #include "llweb.h"
00048 #include "llworldmap.h"
00049
00050
00051 #include "llsd.h"
00052
00053 const std::string SLURL_SL_HELP_PREFIX = "secondlife://app.";
00054 const std::string SLURL_SL_PREFIX = "sl://";
00055 const std::string SLURL_SECONDLIFE_PREFIX = "secondlife://";
00056 const std::string SLURL_SLURL_PREFIX = "http://slurl.com/secondlife/";
00057
00058 const std::string SLURL_APP_TOKEN = "app/";
00059
00060 class LLURLDispatcherImpl
00061 {
00062 public:
00063 static bool isSLURL(const std::string& url);
00064
00065 static bool isSLURLCommand(const std::string& url);
00066
00067 static bool dispatch(const std::string& url, bool from_external_browser);
00068
00069
00070 static bool dispatchRightClick(const std::string& url);
00071
00072 private:
00073 static bool dispatchCore(const std::string& url,
00074 bool from_external_browser, bool right_mouse);
00075
00076
00077 static bool dispatchHelp(const std::string& url, BOOL right_mouse);
00078
00079
00080
00081 static bool dispatchApp(const std::string& url, bool from_external_browser, BOOL right_mouse);
00082
00083
00084
00085
00086 static bool dispatchRegion(const std::string& url, BOOL right_mouse);
00087
00088
00089
00090 static void regionHandleCallback(U64 handle, const std::string& url,
00091 const LLUUID& snapshot_id, bool teleport);
00092
00093
00094
00095 static void regionNameCallback(U64 handle, const std::string& url,
00096 const LLUUID& snapshot_id, bool teleport);
00097
00098
00099
00100 static bool matchPrefix(const std::string& url, const std::string& prefix);
00101
00102 static std::string stripProtocol(const std::string& url);
00103
00104 friend class LLTeleportHandler;
00105 };
00106
00107
00108 bool LLURLDispatcherImpl::isSLURL(const std::string& url)
00109 {
00110 if (matchPrefix(url, SLURL_SL_HELP_PREFIX)) return true;
00111 if (matchPrefix(url, SLURL_SL_PREFIX)) return true;
00112 if (matchPrefix(url, SLURL_SECONDLIFE_PREFIX)) return true;
00113 if (matchPrefix(url, SLURL_SLURL_PREFIX)) return true;
00114 return false;
00115 }
00116
00117
00118 bool LLURLDispatcherImpl::isSLURLCommand(const std::string& url)
00119 {
00120 if (matchPrefix(url, SLURL_SL_PREFIX + SLURL_APP_TOKEN)
00121 || matchPrefix(url, SLURL_SECONDLIFE_PREFIX + "/" + SLURL_APP_TOKEN)
00122 || matchPrefix(url, SLURL_SLURL_PREFIX + SLURL_APP_TOKEN) )
00123 {
00124 return true;
00125 }
00126 return false;
00127 }
00128
00129
00130 bool LLURLDispatcherImpl::dispatchCore(const std::string& url, bool from_external_browser, bool right_mouse)
00131 {
00132 if (url.empty()) return false;
00133 if (dispatchHelp(url, right_mouse)) return true;
00134 if (dispatchApp(url, from_external_browser, right_mouse)) return true;
00135 if (dispatchRegion(url, right_mouse)) return true;
00136
00137
00138
00139
00140
00141
00142
00143
00144 return false;
00145 }
00146
00147
00148 bool LLURLDispatcherImpl::dispatch(const std::string& url, bool from_external_browser)
00149 {
00150 llinfos << "url: " << url << llendl;
00151 const bool right_click = false;
00152 return dispatchCore(url, from_external_browser, right_click);
00153 }
00154
00155
00156 bool LLURLDispatcherImpl::dispatchRightClick(const std::string& url)
00157 {
00158 llinfos << "url: " << url << llendl;
00159 const bool from_external_browser = false;
00160 const bool right_click = true;
00161 return dispatchCore(url, from_external_browser, right_click);
00162 }
00163
00164 bool LLURLDispatcherImpl::dispatchHelp(const std::string& url, BOOL right_mouse)
00165 {
00166 if (matchPrefix(url, SLURL_SL_HELP_PREFIX))
00167 {
00168 gViewerHtmlHelp.show();
00169 return true;
00170 }
00171 return false;
00172 }
00173
00174
00175 bool LLURLDispatcherImpl::dispatchApp(const std::string& url,
00176 bool from_external_browser,
00177 BOOL right_mouse)
00178 {
00179 if (!isSLURL(url))
00180 {
00181 return false;
00182 }
00183
00184 LLURI uri(url);
00185 LLSD pathArray = uri.pathArray();
00186 pathArray.erase(0);
00187 std::string cmd = pathArray.get(0);
00188 pathArray.erase(0);
00189 bool handled = LLCommandDispatcher::dispatch(
00190 cmd, from_external_browser, pathArray, uri.queryMap());
00191 return handled;
00192 }
00193
00194
00195 bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, BOOL right_mouse)
00196 {
00197 if (!isSLURL(url))
00198 {
00199 return false;
00200 }
00201
00202
00203
00204 if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP)
00205 {
00206
00207
00208 LLURLSimString::setString(url);
00209
00210
00211
00212 LLPanelLogin::refreshLocation( true );
00213 return true;
00214 }
00215
00216 std::string sim_string = stripProtocol(url);
00217 std::string region_name;
00218 S32 x = 128;
00219 S32 y = 128;
00220 S32 z = 0;
00221 LLURLSimString::parse(sim_string, ®ion_name, &x, &y, &z);
00222
00223 LLFloaterURLDisplay* url_displayp = LLFloaterURLDisplay::getInstance(LLSD());
00224 url_displayp->setName(region_name);
00225
00226
00227 LLWorldMap::getInstance()->sendNamedRegionRequest(region_name,
00228 LLURLDispatcherImpl::regionNameCallback,
00229 url,
00230 false);
00231 return true;
00232 }
00233
00234
00235 void LLURLDispatcherImpl::regionNameCallback(U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport)
00236 {
00237 std::string sim_string = stripProtocol(url);
00238 std::string region_name;
00239 S32 x = 128;
00240 S32 y = 128;
00241 S32 z = 0;
00242 LLURLSimString::parse(sim_string, ®ion_name, &x, &y, &z);
00243
00244 LLVector3 local_pos;
00245 local_pos.mV[VX] = (F32)x;
00246 local_pos.mV[VY] = (F32)y;
00247 local_pos.mV[VZ] = (F32)z;
00248
00249
00250
00251 if ((x >= 0) && (x < REGION_WIDTH_UNITS) &&
00252 (y >= 0) && (y < REGION_WIDTH_UNITS))
00253 {
00254
00255 regionHandleCallback(region_handle, url, snapshot_id, teleport);
00256 }
00257
00258 else
00259 {
00260
00261
00262
00263 LLVector3d global_pos = from_region_handle(region_handle) + LLVector3d(local_pos);
00264
00265 U64 new_region_handle = to_region_handle(global_pos);
00266 LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle,
00267 LLURLDispatcherImpl::regionHandleCallback,
00268 url, teleport);
00269 }
00270 }
00271
00272
00273 void LLURLDispatcherImpl::regionHandleCallback(U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport)
00274 {
00275 std::string sim_string = stripProtocol(url);
00276 std::string region_name;
00277 S32 x = 128;
00278 S32 y = 128;
00279 S32 z = 0;
00280 LLURLSimString::parse(sim_string, ®ion_name, &x, &y, &z);
00281
00282
00283 S32 local_x = x % REGION_WIDTH_UNITS;
00284 S32 local_y = y % REGION_WIDTH_UNITS;
00285 if (local_x < 0)
00286 local_x += REGION_WIDTH_UNITS;
00287 if (local_y < 0)
00288 local_y += REGION_WIDTH_UNITS;
00289
00290 LLVector3 local_pos;
00291 local_pos.mV[VX] = (F32)local_x;
00292 local_pos.mV[VY] = (F32)local_y;
00293 local_pos.mV[VZ] = (F32)z;
00294
00295
00296
00297 if (teleport)
00298 {
00299 LLVector3d global_pos = from_region_handle(region_handle);
00300 global_pos += LLVector3d(local_pos);
00301 gAgent.teleportViaLocation(global_pos);
00302 if(gFloaterWorldMap)
00303 {
00304 gFloaterWorldMap->trackLocation(global_pos);
00305 }
00306 }
00307 else
00308 {
00309
00310 LLFloaterURLDisplay* url_displayp = LLFloaterURLDisplay::getInstance(LLSD());
00311
00312
00313 url_displayp->displayParcelInfo(region_handle, local_pos);
00314 if(snapshot_id.notNull())
00315 {
00316 url_displayp->setSnapshotDisplay(snapshot_id);
00317 }
00318 std::string locationString = llformat("%s %d, %d, %d", region_name.c_str(), x, y, z);
00319 url_displayp->setLocationString(locationString);
00320 }
00321 }
00322
00323
00324 bool LLURLDispatcherImpl::matchPrefix(const std::string& url, const std::string& prefix)
00325 {
00326 std::string test_prefix = url.substr(0, prefix.length());
00327 LLString::toLower(test_prefix);
00328 return test_prefix == prefix;
00329 }
00330
00331
00332 std::string LLURLDispatcherImpl::stripProtocol(const std::string& url)
00333 {
00334 std::string stripped = url;
00335 if (matchPrefix(stripped, SLURL_SL_HELP_PREFIX))
00336 {
00337 stripped.erase(0, SLURL_SL_HELP_PREFIX.length());
00338 }
00339 else if (matchPrefix(stripped, SLURL_SL_PREFIX))
00340 {
00341 stripped.erase(0, SLURL_SL_PREFIX.length());
00342 }
00343 else if (matchPrefix(stripped, SLURL_SECONDLIFE_PREFIX))
00344 {
00345 stripped.erase(0, SLURL_SECONDLIFE_PREFIX.length());
00346 }
00347 else if (matchPrefix(stripped, SLURL_SLURL_PREFIX))
00348 {
00349 stripped.erase(0, SLURL_SLURL_PREFIX.length());
00350 }
00351 return stripped;
00352 }
00353
00354
00355
00356
00357 class LLTeleportHandler : public LLCommandHandler
00358 {
00359 public:
00360
00361 LLTeleportHandler() : LLCommandHandler("teleport", false) { }
00362
00363 bool handle(const LLSD& tokens, const LLSD& queryMap)
00364 {
00365
00366
00367 if (tokens.size() < 1) return false;
00368
00369
00370 std::string region_name = LLURLSimString::unescapeRegionName(tokens[0]);
00371
00372
00373 std::string url = SLURL_SECONDLIFE_PREFIX;
00374 for (int i = 0; i < tokens.size(); ++i)
00375 {
00376 url += tokens[i].asString() + "/";
00377 }
00378 LLWorldMap::getInstance()->sendNamedRegionRequest(region_name,
00379 LLURLDispatcherImpl::regionHandleCallback,
00380 url,
00381 true);
00382 return true;
00383 }
00384 };
00385 LLTeleportHandler gTeleportHandler;
00386
00387
00388
00389
00390 bool LLURLDispatcher::isSLURL(const std::string& url)
00391 {
00392 return LLURLDispatcherImpl::isSLURL(url);
00393 }
00394
00395
00396 bool LLURLDispatcher::isSLURLCommand(const std::string& url)
00397 {
00398 return LLURLDispatcherImpl::isSLURLCommand(url);
00399 }
00400
00401
00402 bool LLURLDispatcher::dispatch(const std::string& url, bool from_external_browser)
00403 {
00404 return LLURLDispatcherImpl::dispatch(url, from_external_browser);
00405 }
00406
00407 bool LLURLDispatcher::dispatchRightClick(const std::string& url)
00408 {
00409 return LLURLDispatcherImpl::dispatchRightClick(url);
00410 }
00411
00412
00413 bool LLURLDispatcher::dispatchFromTextEditor(const std::string& url)
00414 {
00415
00416 const bool from_external_browser = false;
00417 return LLURLDispatcherImpl::dispatch(url, from_external_browser);
00418 }
00419
00420
00421 std::string LLURLDispatcher::buildSLURL(const std::string& regionname, S32 x, S32 y, S32 z)
00422 {
00423 std::string slurl = SLURL_SLURL_PREFIX + regionname + llformat("/%d/%d/%d",x,y,z);
00424 slurl = LLWeb::escapeURL( slurl );
00425 return slurl;
00426 }