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 "llfloaterhtmlhelp.h"
00041
00042 #include "llpanellogin.h"
00043 #include "llstartup.h"
00044 #include "llurlsimstring.h"
00045 #include "llviewerwindow.h"
00046 #include "llworldmap.h"
00047
00048
00049 #include "llsd.h"
00050
00051
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
00070
00071 static bool dispatchRightClick(const std::string& url);
00072
00073 private:
00074 static bool dispatchCore(const std::string& url, 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 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 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
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
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
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
00135 bool LLURLDispatcherImpl::dispatch(const std::string& url)
00136 {
00137 llinfos << "url: " << url << llendl;
00138 return dispatchCore(url, false);
00139 }
00140
00141
00142 bool LLURLDispatcherImpl::dispatchRightClick(const std::string& url)
00143 {
00144 llinfos << "url: " << url << llendl;
00145 return dispatchCore(url, true);
00146 }
00147
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
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
00170
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
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
00196 std::map<std::string, std::string> args;
00197 args["[SLURL]"] = url;
00198 gViewerWindow->alertXml("BadURL", args);
00199
00200
00201 return true;
00202 }
00203
00204
00205 bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, BOOL right_mouse)
00206 {
00207 if (!isSLURL(url))
00208 {
00209 return false;
00210 }
00211
00212
00213
00214 if (LLStartUp::getStartupState() < STATE_CLEANUP)
00215 {
00216
00217
00218 LLURLSimString::setString(url);
00219
00220
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, ®ion_name, &x, &y, &z);
00231
00232 LLFloaterURLDisplay* url_displayp = LLFloaterURLDisplay::getInstance(LLSD());
00233 url_displayp->setName(region_name);
00234
00235
00236 gWorldMap->sendNamedRegionRequest(region_name,
00237 LLURLDispatcherImpl::regionHandleCallback,
00238 url,
00239 false);
00240 return true;
00241 }
00242
00243
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, ®ion_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
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
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
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
00312
00313 class LLTeleportHandler : public LLCommandHandler
00314 {
00315 public:
00316 LLTeleportHandler() : LLCommandHandler("teleport") { }
00317 bool handle(const std::vector<std::string>& tokens)
00318 {
00319
00320
00321 if (tokens.size() < 1) return false;
00322
00323
00324 std::string region_name = LLURLSimString::unescapeRegionName(tokens[0]);
00325
00326
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);
00336 return true;
00337 }
00338 };
00339 LLTeleportHandler gTeleportHandler;
00340
00341
00342
00343
00344 bool LLURLDispatcher::isSLURL(const std::string& url)
00345 {
00346 return LLURLDispatcherImpl::isSLURL(url);
00347 }
00348
00349
00350 bool LLURLDispatcher::isSLURLCommand(const std::string& url)
00351 {
00352 return LLURLDispatcherImpl::isSLURLCommand(url);
00353 }
00354
00355
00356 bool LLURLDispatcher::dispatch(const std::string& url)
00357 {
00358 return LLURLDispatcherImpl::dispatch(url);
00359 }
00360
00361 bool LLURLDispatcher::dispatchRightClick(const std::string& url)
00362 {
00363 return LLURLDispatcherImpl::dispatchRightClick(url);
00364 }