diff options
author | Jacek Antonelli | 2008-08-15 23:45:11 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:45:11 -0500 |
commit | 215f423cbe18fe9ca14a26caef918d303bad28ff (patch) | |
tree | 0743442b286216cc8e19aa487c26f4e9345ffd64 /linden/indra/newview/llurldispatcher.cpp | |
parent | Second Life viewer sources 1.18.3.5-RC (diff) | |
download | meta-impy-215f423cbe18fe9ca14a26caef918d303bad28ff.zip meta-impy-215f423cbe18fe9ca14a26caef918d303bad28ff.tar.gz meta-impy-215f423cbe18fe9ca14a26caef918d303bad28ff.tar.bz2 meta-impy-215f423cbe18fe9ca14a26caef918d303bad28ff.tar.xz |
Second Life viewer sources 1.18.4.0-RC
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/llurldispatcher.cpp | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/linden/indra/newview/llurldispatcher.cpp b/linden/indra/newview/llurldispatcher.cpp new file mode 100644 index 0000000..7344206 --- /dev/null +++ b/linden/indra/newview/llurldispatcher.cpp | |||
@@ -0,0 +1,326 @@ | |||
1 | /** | ||
2 | * @file llurldispatcher.cpp | ||
3 | * @brief Central registry for all URL handlers | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2007&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2007, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at http://secondlife.com/developers/opensource/flossexception | ||
21 | * | ||
22 | * By copying, modifying or distributing this software, you acknowledge | ||
23 | * that you have read and understood your obligations described above, | ||
24 | * and agree to abide by those obligations. | ||
25 | * | ||
26 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
27 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
28 | * COMPLETENESS OR PERFORMANCE. | ||
29 | * $/LicenseInfo$ | ||
30 | */ | ||
31 | #include "llviewerprecompiledheaders.h" | ||
32 | |||
33 | #include "llurldispatcher.h" | ||
34 | |||
35 | // viewer includes | ||
36 | #include "llagent.h" // teleportViaLocation() | ||
37 | #include "llcommandhandler.h" | ||
38 | // *FIX: code in merge sl-search-8 | ||
39 | //#include "llfloaterurldisplay.h" | ||
40 | #include "llfloaterdirectory.h" | ||
41 | #include "llfloaterhtmlhelp.h" | ||
42 | #include "llfloaterworldmap.h" | ||
43 | #include "llpanellogin.h" | ||
44 | #include "llstartup.h" // gStartupState | ||
45 | #include "llurlsimstring.h" | ||
46 | #include "llviewerwindow.h" // alertXml() | ||
47 | #include "llworldmap.h" | ||
48 | |||
49 | // library includes | ||
50 | #include "llsd.h" | ||
51 | |||
52 | // system includes | ||
53 | #include <boost/tokenizer.hpp> | ||
54 | |||
55 | const std::string SLURL_SL_HELP_PREFIX = "secondlife://app."; | ||
56 | const std::string SLURL_SL_PREFIX = "sl://"; | ||
57 | const std::string SLURL_SECONDLIFE_PREFIX = "secondlife://"; | ||
58 | const std::string SLURL_SLURL_PREFIX = "http://slurl.com/secondlife/"; | ||
59 | |||
60 | const std::string SLURL_APP_TOKEN = "app/"; | ||
61 | |||
62 | class LLURLDispatcherImpl | ||
63 | { | ||
64 | public: | ||
65 | static bool isSLURL(const std::string& url); | ||
66 | |||
67 | static bool isSLURLCommand(const std::string& url); | ||
68 | |||
69 | static bool dispatch(const std::string& url); | ||
70 | // returns true if handled | ||
71 | |||
72 | static bool dispatchRightClick(const std::string& url); | ||
73 | |||
74 | private: | ||
75 | static bool dispatchCore(const std::string& url, bool right_mouse); | ||
76 | // handles both left and right click | ||
77 | |||
78 | static bool dispatchHelp(const std::string& url, BOOL right_mouse); | ||
79 | // Handles sl://app.floater.html.help by showing Help floater. | ||
80 | // Returns true if handled. | ||
81 | |||
82 | static bool dispatchApp(const std::string& url, BOOL right_mouse); | ||
83 | // Handles secondlife://app/agent/<agent_id>/about and similar | ||
84 | // by showing panel in Search floater. | ||
85 | // Returns true if handled. | ||
86 | |||
87 | static bool dispatchRegion(const std::string& url, BOOL right_mouse); | ||
88 | // handles secondlife://Ahern/123/45/67/ | ||
89 | // Returns true if handled. | ||
90 | |||
91 | // *FIX: code in merge sl-search-8 | ||
92 | // static void regionHandleCallback(U64 handle, const std::string& url, | ||
93 | // const LLUUID& snapshot_id, bool teleport); | ||
94 | // // Called by LLWorldMap when a region name has been resolved to a | ||
95 | // // location in-world, used by places-panel display. | ||
96 | |||
97 | static bool matchPrefix(const std::string& url, const std::string& prefix); | ||
98 | |||
99 | static std::string stripProtocol(const std::string& url); | ||
100 | |||
101 | friend class LLTeleportHandler; | ||
102 | }; | ||
103 | |||
104 | // static | ||
105 | bool LLURLDispatcherImpl::isSLURL(const std::string& url) | ||
106 | { | ||
107 | if (matchPrefix(url, SLURL_SL_HELP_PREFIX)) return true; | ||
108 | if (matchPrefix(url, SLURL_SL_PREFIX)) return true; | ||
109 | if (matchPrefix(url, SLURL_SECONDLIFE_PREFIX)) return true; | ||
110 | if (matchPrefix(url, SLURL_SLURL_PREFIX)) return true; | ||
111 | return false; | ||
112 | } | ||
113 | |||
114 | // static | ||
115 | bool LLURLDispatcherImpl::isSLURLCommand(const std::string& url) | ||
116 | { | ||
117 | if (matchPrefix(url, SLURL_SL_PREFIX + SLURL_APP_TOKEN) | ||
118 | || matchPrefix(url, SLURL_SECONDLIFE_PREFIX + SLURL_APP_TOKEN) | ||
119 | || matchPrefix(url, SLURL_SLURL_PREFIX + SLURL_APP_TOKEN) ) | ||
120 | { | ||
121 | return true; | ||
122 | } | ||
123 | return false; | ||
124 | } | ||
125 | |||
126 | // static | ||
127 | bool LLURLDispatcherImpl::dispatchCore(const std::string& url, bool right_mouse) | ||
128 | { | ||
129 | if (url.empty()) return false; | ||
130 | if (dispatchHelp(url, right_mouse)) return true; | ||
131 | if (dispatchApp(url, right_mouse)) return true; | ||
132 | if (dispatchRegion(url, right_mouse)) return true; | ||
133 | return false; | ||
134 | } | ||
135 | |||
136 | // static | ||
137 | bool LLURLDispatcherImpl::dispatch(const std::string& url) | ||
138 | { | ||
139 | llinfos << "url: " << url << llendl; | ||
140 | return dispatchCore(url, false); // not right click | ||
141 | } | ||
142 | |||
143 | // static | ||
144 | bool LLURLDispatcherImpl::dispatchRightClick(const std::string& url) | ||
145 | { | ||
146 | llinfos << "url: " << url << llendl; | ||
147 | return dispatchCore(url, true); // yes right click | ||
148 | } | ||
149 | // static | ||
150 | bool LLURLDispatcherImpl::dispatchHelp(const std::string& url, BOOL right_mouse) | ||
151 | { | ||
152 | if (matchPrefix(url, SLURL_SL_HELP_PREFIX)) | ||
153 | { | ||
154 | gViewerHtmlHelp.show(); | ||
155 | return true; | ||
156 | } | ||
157 | return false; | ||
158 | } | ||
159 | |||
160 | // static | ||
161 | bool LLURLDispatcherImpl::dispatchApp(const std::string& url, BOOL right_mouse) | ||
162 | { | ||
163 | if (!isSLURL(url)) | ||
164 | { | ||
165 | return false; | ||
166 | } | ||
167 | std::string s = stripProtocol(url); | ||
168 | |||
169 | // At this point, "secondlife://app/foo/bar/baz/" should be left | ||
170 | // as: "app/foo/bar/baz/" | ||
171 | typedef boost::tokenizer<boost::char_separator<char> > tokenizer; | ||
172 | boost::char_separator<char> sep("/", "", boost::drop_empty_tokens); | ||
173 | tokenizer tokens(s, sep); | ||
174 | tokenizer::iterator it = tokens.begin(); | ||
175 | tokenizer::iterator end = tokens.end(); | ||
176 | |||
177 | // Build parameter list suitable for LLDispatcher dispatch | ||
178 | if (it == end) return false; | ||
179 | if (*it != "app") return false; | ||
180 | ++it; | ||
181 | |||
182 | if (it == end) return false; | ||
183 | std::string cmd = *it; | ||
184 | ++it; | ||
185 | |||
186 | std::vector<std::string> params; | ||
187 | for ( ; it != end; ++it) | ||
188 | { | ||
189 | params.push_back(*it); | ||
190 | } | ||
191 | |||
192 | bool handled = LLCommandDispatcher::dispatch(cmd, params); | ||
193 | if (handled) return true; | ||
194 | |||
195 | // Inform the user we can't handle this | ||
196 | std::map<std::string, std::string> args; | ||
197 | args["[SLURL]"] = url; | ||
198 | gViewerWindow->alertXml("BadURL", args); | ||
199 | return false; | ||
200 | } | ||
201 | |||
202 | // static | ||
203 | bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, BOOL right_mouse) | ||
204 | { | ||
205 | if (!isSLURL(url)) | ||
206 | { | ||
207 | return false; | ||
208 | } | ||
209 | |||
210 | // Before we're logged in, need to update the startup screen | ||
211 | // to tell the user where they are going. | ||
212 | if (LLStartUp::getStartupState() < STATE_CLEANUP) | ||
213 | { | ||
214 | // Parse it and stash in globals, it will be dispatched in | ||
215 | // STATE_CLEANUP. | ||
216 | LLURLSimString::setString(url); | ||
217 | // We're at the login screen, so make sure user can see | ||
218 | // the login location box to know where they are going. | ||
219 | LLPanelLogin::refreshLocation( true ); | ||
220 | return true; | ||
221 | } | ||
222 | |||
223 | std::string sim_string = stripProtocol(url); | ||
224 | std::string region_name; | ||
225 | S32 x = 128; | ||
226 | S32 y = 128; | ||
227 | S32 z = 0; | ||
228 | LLURLSimString::parse(sim_string, ®ion_name, &x, &y, &z); | ||
229 | if (gFloaterWorldMap) | ||
230 | { | ||
231 | llinfos << "Opening map to " << region_name << llendl; | ||
232 | gFloaterWorldMap->trackURL( region_name.c_str(), x, y, z ); | ||
233 | LLFloaterWorldMap::show(NULL, TRUE); | ||
234 | } | ||
235 | return true; | ||
236 | } | ||
237 | |||
238 | // static | ||
239 | bool LLURLDispatcherImpl::matchPrefix(const std::string& url, const std::string& prefix) | ||
240 | { | ||
241 | std::string test_prefix = url.substr(0, prefix.length()); | ||
242 | LLString::toLower(test_prefix); | ||
243 | return test_prefix == prefix; | ||
244 | } | ||
245 | |||
246 | // static | ||
247 | std::string LLURLDispatcherImpl::stripProtocol(const std::string& url) | ||
248 | { | ||
249 | std::string stripped = url; | ||
250 | if (matchPrefix(stripped, SLURL_SL_HELP_PREFIX)) | ||
251 | { | ||
252 | stripped.erase(0, SLURL_SL_HELP_PREFIX.length()); | ||
253 | } | ||
254 | else if (matchPrefix(stripped, SLURL_SL_PREFIX)) | ||
255 | { | ||
256 | stripped.erase(0, SLURL_SL_PREFIX.length()); | ||
257 | } | ||
258 | else if (matchPrefix(stripped, SLURL_SECONDLIFE_PREFIX)) | ||
259 | { | ||
260 | stripped.erase(0, SLURL_SECONDLIFE_PREFIX.length()); | ||
261 | } | ||
262 | else if (matchPrefix(stripped, SLURL_SLURL_PREFIX)) | ||
263 | { | ||
264 | stripped.erase(0, SLURL_SLURL_PREFIX.length()); | ||
265 | } | ||
266 | return stripped; | ||
267 | } | ||
268 | |||
269 | // *FIX: code in merge sl-search-8 | ||
270 | // | ||
271 | ////--------------------------------------------------------------------------- | ||
272 | //// Teleportation links are handled here because they are tightly coupled | ||
273 | //// to URL parsing and sim-fragment parsing | ||
274 | //class LLTeleportHandler : public LLCommandHandler | ||
275 | //{ | ||
276 | //public: | ||
277 | // LLTeleportHandler() : LLCommandHandler("teleport") { } | ||
278 | // bool handle(const std::vector<std::string>& tokens) | ||
279 | // { | ||
280 | // // construct a "normal" SLURL, resolve the region to | ||
281 | // // a global position, and teleport to it | ||
282 | // if (tokens.size() < 1) return false; | ||
283 | // | ||
284 | // // Region names may be %20 escaped. | ||
285 | // std::string region_name = LLURLSimString::unescapeRegionName(tokens[0]); | ||
286 | // | ||
287 | // // build secondlife://De%20Haro/123/45/67 for use in callback | ||
288 | // std::string url = SLURL_SECONDLIFE_PREFIX; | ||
289 | // for (size_t i = 0; i < tokens.size(); ++i) | ||
290 | // { | ||
291 | // url += tokens[i] + "/"; | ||
292 | // } | ||
293 | // gWorldMap->sendNamedRegionRequest(region_name, | ||
294 | // LLURLDispatcherImpl::regionHandleCallback, | ||
295 | // url, | ||
296 | // true); // teleport | ||
297 | // return true; | ||
298 | // } | ||
299 | //}; | ||
300 | //LLTeleportHandler gTeleportHandler; | ||
301 | |||
302 | //--------------------------------------------------------------------------- | ||
303 | |||
304 | // static | ||
305 | bool LLURLDispatcher::isSLURL(const std::string& url) | ||
306 | { | ||
307 | return LLURLDispatcherImpl::isSLURL(url); | ||
308 | } | ||
309 | |||
310 | // static | ||
311 | bool LLURLDispatcher::isSLURLCommand(const std::string& url) | ||
312 | { | ||
313 | return LLURLDispatcherImpl::isSLURLCommand(url); | ||
314 | } | ||
315 | |||
316 | // static | ||
317 | bool LLURLDispatcher::dispatch(const std::string& url) | ||
318 | { | ||
319 | return LLURLDispatcherImpl::dispatch(url); | ||
320 | } | ||
321 | // static | ||
322 | bool LLURLDispatcher::dispatchRightClick(const std::string& url) | ||
323 | { | ||
324 | return LLURLDispatcherImpl::dispatchRightClick(url); | ||
325 | } | ||
326 | |||