OSDN Git Service

Added a more robust Secondlife URI parser to all RichTextBoxPrinters.
[radegast/radegast.git] / Radegast / Core / SlUriParser.cs
1 using System;
2 using System.Text.RegularExpressions;
3 using System.Threading;
4 using System.Web;
5 using OpenMetaverse;
6
7 namespace Radegast
8 {
9     public class SlUriParser
10     {
11         private enum ResolveType
12         {
13             /// <summary>
14             /// Display (first.last)
15             /// </summary>
16             AgentCompleteName,
17             /// <summary>
18             /// Display
19             /// </summary>
20             AgentDisplayName,
21             /// <summary>
22             /// first.last
23             /// </summary>
24             AgentUsername,
25             /// <summary>
26             /// Group name
27             /// </summary>
28             Group,
29             /// <summary>
30             /// Parcel name
31             /// </summary>
32             Parcel
33         };
34
35         // Regular expression created by following the majority of http://wiki.secondlife.com/wiki/Viewer_URI_Name_Space (excluding support for secondlife:///app/login).
36         //  This is a nasty one and should really only be used on single links to minimize processing time.
37         private readonly Regex patternUri = new Regex(
38             @"(?<startingbrace>\[)?(" +
39                 @"(?<regionuri>secondlife://(?<region_name>[^\]/ ]+)(/(?<local_x>[0-9]+))?(/(?<local_y>[0-9]+))?(/(?<local_z>[0-9]+))?)|" +
40                 @"(?<appuri>secondlife:///app/(" +
41                     @"(?<appcommand>agent)/(?<agent_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/(?<action>[a-z]+)|" +
42                     @"(?<appcommand>apperance)/show|" +
43                     @"(?<appcommand>balance)/request|" +
44                     @"(?<appcommand>chat)/(?<channel>\d+)/(?<text>[^\] ]+)|" + 
45                     @"(?<appcommand>classified)/(?<classified_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/about|" +
46                     @"(?<appcommand>event)/(?<event_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/about|" +
47                     @"(?<appcommand>group)/(" +
48                         @"(?<group_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/(?<action>[a-z]+)|" +
49                         @"(?<action>create)|" +
50                         @"(?<action>list/show))|" +
51                     @"(?<appcommand>help)/?<help_query>([^\] ]+)|" +
52                     @"(?<appcommand>inventory)/(" +
53                         @"(?<inventory_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/(?<action>select)/?" +
54                             @"([?&](" +
55                                 @"name=(?<name>[^& ]+)" +
56                             @"))*|" +
57                         @"(?<action>show))|" +
58                     @"(?<appcommand>maptrackavatar)/(?<friend_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})|" +
59                     @"(?<appcommand>objectim)/(?<object_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/?" +
60                         @"([?&](" +
61                             @"name=(?<name>[^& ]+)|" +
62                             @"owner=(?<owner>[^& ]+)|" +
63                             @"groupowned=(?<groupowned>true)|" +
64                             @"slurl=(?<region_name>[^\]/ ]+)(/(?<x>[0-9]+\.?[0-9]*))?(/(?<y>[0-9]+\.?[0-9]*))?(/(?<z>[0-9]+\.?[0-9]*))?" +
65                         @"))*|" +
66                     @"(?<appcommand>parcel)/(?<parcel_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/about|" +
67                     @"(?<appcommand>search)/(?<category>[a-z]+)/(?<search_term>[^\]/ ]+)|" +
68                     @"(?<appcommand>sharewithavatar)/(?<agent_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})|" +
69                     @"(?<appcommand>teleport)/(?<region_name>[^\]/ ]+)(/(?<local_x>[0-9]+))?(/(?<local_y>[0-9]+))?(/(?<local_z>[0-9]+))?|" +
70                     @"(?<appcommand>voicecallavatar)/(?<agent_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})|" +
71                     @"(?<appcommand>wear_folder)/?folder_id=(?<inventory_folder_uuid>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})|" +
72                     @"(?<appcommand>worldmap)/(?<region_name>[^\]/ ]+)(/(?<local_x>[0-9]+))?(/(?<local_y>[0-9]+))?(/(?<local_z>[0-9]+))?)))" +
73             @"( (?<endingbrace>[^\]]*)\])?", RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
74
75         /// <summary>
76         /// Gets the display text for the specified URI
77         /// </summary>
78         /// <param name="uri">URI to get the display text of</param>
79         /// <returns>Display text for URI</returns>
80         public string GetLinkName(string uri)
81         {
82             Match match = patternUri.Match(uri);
83             if (!match.Success)
84             {
85                 return uri;
86             }
87
88             // Custom named links in the form of [secondlife://<truncated> Custom%20Link%20Name] will
89             //   result in a link named 'Custom Link Name' regardless of the previous secondlife URI.
90             if (match.Groups["startingbrace"].Success && match.Groups["endingbrace"].Length > 0)
91             {
92                 return HttpUtility.UrlDecode(match.Groups["endingbrace"].Value);
93             }
94
95             if (match.Groups["regionuri"].Success)
96             {
97                 return GetLinkNameRegionUri(match);
98             }
99
100             if (match.Groups["appuri"].Success)
101             {
102                 string appcommand = match.Groups["appcommand"].Value;
103
104                 switch (appcommand)
105                 {
106                     case "agent":
107                         return GetLinkNameAgent(match);
108                     case "appearance":
109                         return match.ToString();
110                     case "balance":
111                         return match.ToString();
112                     case "chat":
113                         return GetLinkNameChat(match);
114                     case "classified":
115                         return GetLinkNameClassified(match);
116                     case "event":
117                         return GetLinkNameEvent(match);
118                     case "group":
119                         return GetLinkNameGroup(match);
120                     case "help":
121                         return GetLinkNameHelp(match);
122                     case "inventory":
123                         return GetLinkNameInventory(match);
124                     case "maptrackavatar":
125                         return GetLinkNameTrackAvatar(match);
126                     case "objectim":
127                         return GetLinkNameObjectIm(match);
128                     case "parcel":
129                         return GetLinkNameParcel(match);
130                     case "search":
131                         return GetLinkNameSearch(match);
132                     case "sharewithavatar":
133                         return GetLinkNameShareWithAvatar(match);
134                     case "teleport":
135                         return GetLinkNameTeleport(match);
136                     case "voicecallavatar":
137                         return GetLinkNameVoiceCallAvatar(match);
138                     case "wear_folder":
139                         return GetLinkNameWearFolder(match);
140                     case "worldmap":
141                         return GetLinkNameWorldMap(match);
142                     default:
143                         return match.ToString();
144                 }
145             }
146
147             return match.ToString();
148         }
149
150         /// <summary>
151         /// Parses and executes the specified SecondLife URI if valid
152         /// </summary>
153         /// <param name="uri">URI to parse and execute</param>
154         public void ExecuteLink(string uri)
155         {
156             Match match = patternUri.Match(uri);
157             if (!match.Success)
158             {
159                 return;
160             }
161
162             if (match.Groups["regionuri"].Success)
163             {
164                 ExecuteLinkRegionUri(match);
165             }
166             else if (match.Groups["appuri"].Success)
167             {
168                 string appcommand = match.Groups["appcommand"].Value;
169
170                 switch (appcommand)
171                 {
172                     case "agent":
173                         ExecuteLinkAgent(match);
174                         return;
175                     case "appearance":
176                         ExecuteLinkShowApperance();
177                         return;
178                     case "balance":
179                         ExecuteLinkShowBalance();
180                         return;
181                     case "chat":
182                         ExecuteLinkChat(match);
183                         return;
184                     case "classified":
185                         ExecuteLinkClassified(match);
186                         return;
187                     case "event":
188                         ExecuteLinkEvent(match);
189                         return;
190                     case "group":
191                         ExecuteLinkGroup(match);
192                         return;
193                     case "help":
194                         ExecuteLinkHelp(match);
195                         return;
196                     case "inventory":
197                         ExecuteLinkInventory(match);
198                         return;
199                     case "maptrackavatar":
200                         ExecuteLinkTrackAvatar(match);
201                         return;
202                     case "objectim":
203                         ExecuteLinkObjectIm(match);
204                         return;
205                     case "parcel":
206                         ExecuteLinkParcel(match);
207                         return;
208                     case "search":
209                         ExecuteLinkSearch(match);
210                         return;
211                     case "sharewithavatar":
212                         ExecuteLinkShareWithAvatar(match);
213                         return;
214                     case "teleport":
215                         ExecuteLinkTeleport(match);
216                         return;
217                     case "voicecallavatar":
218                         ExecuteLinkVoiceCallAvatar(match);
219                         return;
220                     case "wear_folder":
221                         ExecuteLinkWearFolder(match);
222                         return;
223                     case "worldmap":
224                         ExecuteLinkWorldMap(match);
225                         return;
226                 }
227             }
228         }
229
230         #region Name Resolution
231
232         /// <summary>
233         /// Amount of time in milliseconds to wait before giving up on name resolution
234         /// </summary>
235         private const int NameResolveTimeoutInMs = 150;
236
237         /// <summary>
238         /// Gets the name of an agent by UUID. Will block for a short period of time to allow for name resolution.
239         /// </summary>
240         /// <param name="agentID">Agent UUID</param>
241         /// <param name="nameType">Type of name resolution. See ResolveType</param>
242         /// <returns>Name of agent on success, INCOMPLETE_NAME on failure or timeout</returns>
243         private string GetAgentName(UUID agentID, ResolveType nameType)
244         {
245             RadegastInstance instance = RadegastInstance.GlobalInstance;
246             string name = RadegastInstance.INCOMPLETE_NAME;
247
248             using (ManualResetEvent gotName = new ManualResetEvent(false))
249             {
250                 EventHandler<UUIDNameReplyEventArgs> handler = (object sender, UUIDNameReplyEventArgs e) =>
251                 {
252                     if (e.Names.ContainsKey(agentID))
253                     {
254                         name = e.Names[agentID];
255                         try
256                         {
257                             gotName.Set();
258                         }
259                         catch (ObjectDisposedException) { }
260                     }
261                 };
262
263                 instance.Names.NameUpdated += handler;
264
265                 if (nameType == ResolveType.AgentCompleteName)
266                 {
267                     name = instance.Names.GetLegacyName(agentID);
268                 }
269                 else if (nameType == ResolveType.AgentUsername)
270                 {
271                     name = instance.Names.GetUserName(agentID);
272                 }
273                 else if (nameType == ResolveType.AgentDisplayName)
274                 {
275                     name = instance.Names.GetDisplayName(agentID);
276                 }
277                 else
278                 {
279                     return agentID.ToString();
280                 }
281
282                 if (name == RadegastInstance.INCOMPLETE_NAME)
283                 {
284                     gotName.WaitOne(NameResolveTimeoutInMs, false);
285                 }
286
287                 instance.Names.NameUpdated -= handler;
288             }
289
290             return name;
291         }
292
293         /// <summary>
294         /// Gets the name of a group by UUID. Will block for a short period of time to allow for name resolution.
295         /// </summary>
296         /// <param name="groupID">Group UUID</param>
297         /// <returns>Name of the group on success, INCOMPLETE_NAME on failure or timeout</returns>
298         private string GetGroupName(UUID groupID)
299         {
300             RadegastInstance instance = RadegastInstance.GlobalInstance;
301             string name = RadegastInstance.INCOMPLETE_NAME;
302
303             using (ManualResetEvent gotName = new ManualResetEvent(false))
304             {
305                 EventHandler<GroupNamesEventArgs> handler = (object sender, GroupNamesEventArgs e) =>
306                 {
307                     if (e.GroupNames.ContainsKey(groupID))
308                     {
309                         name = e.GroupNames[groupID];
310                         try
311                         {
312                             gotName.Set();
313                         }
314                         catch (ObjectDisposedException) { }
315                     }
316                 };
317
318                 instance.Client.Groups.GroupNamesReply += handler;
319                 instance.Client.Groups.RequestGroupName(groupID);
320                 if (name == RadegastInstance.INCOMPLETE_NAME)
321                 {
322                     gotName.WaitOne(NameResolveTimeoutInMs, false);
323                 }
324
325                 instance.Client.Groups.GroupNamesReply -= handler;
326             }
327
328             return name;
329         }
330
331         /// <summary>
332         /// Gets the name of a parcel by UUID. Will block for a short period of time to allow for name resolution.
333         /// </summary>
334         /// <param name="parcelID">Parcel UUID</param>
335         /// <returns>Name of the parcel on success, INCOMPLETE_NAME on failure or timeout</returns>
336         private string GetParcelName(UUID parcelID)
337         {
338             RadegastInstance instance = RadegastInstance.GlobalInstance;
339             string name = RadegastInstance.INCOMPLETE_NAME;
340             
341             using (ManualResetEvent gotName = new ManualResetEvent(false))
342             {
343                 EventHandler<ParcelInfoReplyEventArgs> handler = (object sender, ParcelInfoReplyEventArgs e) =>
344                 {
345                     if (e.Parcel.ID == parcelID)
346                     {
347                         name = e.Parcel.Name;
348                         try
349                         {
350                             gotName.Set();
351                         }
352                         catch (ObjectDisposedException) { }
353                     }
354                 };
355
356                 instance.Client.Parcels.ParcelInfoReply += handler;
357                 instance.Client.Parcels.RequestParcelInfo(parcelID);
358                 if (name == RadegastInstance.INCOMPLETE_NAME)
359                 {
360                     gotName.WaitOne(NameResolveTimeoutInMs, false);
361                 }
362
363                 instance.Client.Parcels.ParcelInfoReply -= handler;
364             }
365
366             return name;
367         }
368         #endregion
369
370         /// <summary>
371         /// Attempts to resolve the name of a given key by type (Agent, Group, Parce, etc)
372         /// </summary>
373         /// <param name="id">UUID of object to resolve</param>
374         /// <param name="type">Type of object</param>
375         /// <returns>Revoled name</returns>
376         private string Resolve(UUID id, ResolveType type)
377         {
378             switch (type)
379             {
380                 case ResolveType.AgentCompleteName:
381                 case ResolveType.AgentDisplayName:
382                 case ResolveType.AgentUsername:
383                     return GetAgentName(id, type);
384                 case ResolveType.Group:
385                     return GetGroupName(id);
386                 case ResolveType.Parcel:
387                     return GetParcelName(id);
388                 default:
389                     return id.ToString();
390             }
391         }
392
393         #region Link name resolution
394
395         private string GetLinkNameRegionUri(Match match)
396         {
397             string name = HttpUtility.UrlDecode(match.Groups["region_name"].Value);
398
399             string coordinateString = "";
400             if (match.Groups["local_x"].Success)
401             {
402                 coordinateString += " (" + match.Groups["local_x"].Value;
403             }
404             if (match.Groups["local_y"].Success)
405             {
406                 coordinateString += "," + match.Groups["local_y"].Value;
407             }
408             if (match.Groups["local_z"].Success)
409             {
410                 coordinateString += "," + match.Groups["local_z"].Value;
411             }
412             if (coordinateString != "")
413             {
414                 coordinateString += ")";
415             }
416
417             return string.Format("{0}{1}", name, coordinateString);
418         }
419
420         private string GetLinkNameAgent(Match match)
421         {
422             UUID agentID = new UUID(match.Groups["agent_id"].Value);
423             string action = match.Groups["action"].Value;
424
425             switch (action)
426             {
427                 case "about":
428                 case "inspect":
429                 case "completename":
430                     return Resolve(agentID, ResolveType.AgentCompleteName);
431                 case "displayname":
432                     return Resolve(agentID, ResolveType.AgentDisplayName);
433                 case "username":
434                     return Resolve(agentID, ResolveType.AgentUsername);
435                 case "im":
436                     return "IM " + Resolve(agentID, ResolveType.AgentCompleteName);
437                 case "offerteleport":
438                     return "Offer Teleport to " + Resolve(agentID, ResolveType.AgentCompleteName);
439                 case "pay":
440                     return "Pay " + Resolve(agentID, ResolveType.AgentCompleteName);
441                 case "requestfriend":
442                     return "Friend Request " + Resolve(agentID, ResolveType.AgentCompleteName);
443                 case "mute":
444                     return "Mute " + Resolve(agentID, ResolveType.AgentCompleteName);
445                 case "unmute":
446                     return "Unmute " + Resolve(agentID, ResolveType.AgentCompleteName);
447                 default:
448                     return match.ToString();
449             }
450         }
451
452         private string GetLinkNameChat(Match match)
453         {
454             //string channel = match.Groups["channel"].Value;
455             //string text = System.Web.HttpUtility.UrlDecode(match.Groups["text"].Value);
456
457             return match.ToString();
458         }
459
460         private string GetLinkNameClassified(Match match)
461         {
462             //UUID classifiedID = new UUID(match.Groups["classified_id"].Value);
463
464             return match.ToString();
465         }
466
467         private string GetLinkNameEvent(Match match)
468         {
469             //UUID eventID = new UUID(match.Groups["event_id"].Value);
470
471             return match.ToString();
472         }
473
474         private string GetLinkNameGroup(Match match)
475         {
476             string action = match.Groups["action"].Value;
477
478             switch (action)
479             {
480                 case "about":
481                 case "inspect":
482                 {
483                     UUID groupID = new UUID(match.Groups["group_id"].Value);
484                     return Resolve(groupID, ResolveType.Group);
485                 }
486                 case "create":
487                 case "list/show":
488                     return match.ToString();
489             }
490
491             return match.ToString();
492         }
493
494         private string GetLinkNameHelp(Match match)
495         {
496             //string helpQuery = HttpUtility.UrlDecode(match.Groups["help_query"].Value);
497
498             return match.ToString();
499         }
500
501         private string GetLinkNameInventory(Match match)
502         {
503             //UUID inventoryID = new UUID(match.Groups["agent_id"].Value);
504             string action = match.Groups["action"].Value;
505
506             if (action == "select" && match.Groups["name"].Success)
507             {
508                 return HttpUtility.UrlDecode(match.Groups["name"].Value);
509             }
510
511             return match.ToString();
512         }
513
514         private string GetLinkNameTrackAvatar(Match match)
515         {
516             //UUID agentID = new UUID(match.Groups["friend_id"].Value);
517
518             return match.ToString();
519         }
520
521         private string GetLinkNameObjectIm(Match match)
522         {
523             //UUID objectID = new UUID(match.Groups["object_id"].Value);
524             string name = HttpUtility.UrlDecode(match.Groups["name"].Value);
525             //UUID ownerID = new UUID(match.Groups["owner"].Value);
526             //string groupowned = match.Groups["groupowned"].Value;
527             //string slurl = match.Groups["slurl"].Value;
528
529             if (name != string.Empty)
530             {
531                 return name;
532             }
533
534             return match.ToString();
535         }
536
537         private string GetLinkNameParcel(Match match)
538         {
539             UUID parcelID = new UUID(match.Groups["parcel_id"].Value);
540             return Resolve(parcelID, ResolveType.Parcel);
541         }
542
543         private string GetLinkNameSearch(Match match)
544         {
545             //string category = match.Groups["category"].Value;
546             //string searchTerm = HttpUtility.UrlDecode(match.Groups["search_term"].Value);
547
548             return match.ToString();
549         }
550
551         private string GetLinkNameShareWithAvatar(Match match)
552         {
553             //UUID agentID = new UUID(match.Groups["agent_id"].Value);
554
555             return match.ToString();
556         }
557
558         private string GetLinkNameTeleport(Match match)
559         {
560             string name = HttpUtility.UrlDecode(match.Groups["region_name"].Value);
561
562             string coordinateString = "";
563             if (match.Groups["local_x"].Success)
564             {
565                 coordinateString += " (" + match.Groups["local_x"].Value;
566             }
567             if (match.Groups["local_y"].Success)
568             {
569                 coordinateString += "," + match.Groups["local_y"].Value;
570             }
571             if (match.Groups["local_z"].Success)
572             {
573                 coordinateString += "," + match.Groups["local_z"].Value;
574             }
575             if (coordinateString != "")
576             {
577                 coordinateString += ")";
578             }
579
580             return string.Format("Teleport to {0}{1}", name, coordinateString);
581         }
582
583         private string GetLinkNameVoiceCallAvatar(Match match)
584         {
585             //UUID agentID = new UUID(match.Groups["agent_id"].Value);
586
587             return match.ToString();
588         }
589
590         private string GetLinkNameWearFolder(Match match)
591         {
592             //UUID folderID = new UUID(match.Groups["inventory_folder_uuid"].Value);
593
594             return match.ToString();
595         }
596
597         private string GetLinkNameWorldMap(Match match)
598         {
599             string name = HttpUtility.UrlDecode(match.Groups["region_name"].Value);
600             string x = match.Groups["local_x"].Success ? match.Groups["local_x"].Value : "128";
601             string y = match.Groups["local_y"].Success ? match.Groups["local_y"].Value : "128";
602             string z = match.Groups["local_z"].Success ? match.Groups["local_z"].Value : "0";
603
604             return string.Format("Show Map for {0} ({1},{2},{3})", name, x, y, z);
605         }
606         #endregion
607
608         #region Link Execution
609         private void ExecuteLinkRegionUri(Match match)
610         {
611             RadegastInstance instance = RadegastInstance.GlobalInstance;
612
613             string name = HttpUtility.UrlDecode(match.Groups["region_name"].Value);
614             int x = match.Groups["local_x"].Success ? int.Parse(match.Groups["local_x"].Value) : 128;
615             int y = match.Groups["local_y"].Success ? int.Parse(match.Groups["local_y"].Value) : 128;
616             int z = match.Groups["local_z"].Success ? int.Parse(match.Groups["local_z"].Value) : 0;
617
618             instance.MainForm.MapTab.Select();
619             instance.MainForm.WorldMap.DisplayLocation(name, x, y, z);
620         }
621
622         private void ExecuteLinkAgent(Match match)
623         {
624             RadegastInstance instance = RadegastInstance.GlobalInstance;
625             UUID agentID = new UUID(match.Groups["agent_id"].Value);
626             //string action = match.Groups["action"].Value;
627
628             RadegastInstance.GlobalInstance.MainForm.ShowAgentProfile(instance.Names.Get(agentID), agentID);
629         }
630
631         private void ExecuteLinkShowApperance()
632         {
633
634         }
635
636         private void ExecuteLinkShowBalance()
637         {
638
639         }
640
641         private void ExecuteLinkChat(Match match)
642         {
643             //string channel = match.Groups["channel"].Value;
644             //string text = System.Web.HttpUtility.UrlDecode(match.Groups["text"].Value);
645         }
646
647         private void ExecuteLinkClassified(Match match)
648         {
649             //UUID classifiedID = new UUID(match.Groups["classified_id"].Value);
650         }
651
652         private void ExecuteLinkEvent(Match match)
653         {
654             //UUID eventID = new UUID(match.Groups["event_id"].Value);
655         }
656
657         private void ExecuteLinkGroup(Match match)
658         {
659             RadegastInstance instance = RadegastInstance.GlobalInstance;
660             string action = match.Groups["action"].Value;
661
662             switch (action)
663             {
664                 case "about":
665                 case "inspect":
666                 {
667                     UUID groupID = new UUID(match.Groups["group_id"].Value);
668                     instance.MainForm.ShowGroupProfile(groupID);
669                     return;
670                 }
671                 case "create":
672                     return;
673                 case "list/show":
674                     return;
675             }
676         }
677
678         private void ExecuteLinkHelp(Match match)
679         {
680             //string helpQuery = HttpUtility.UrlDecode(match.Groups["help_query"].Value);
681         }
682
683         private void ExecuteLinkInventory(Match match)
684         {
685             //UUID inventoryID = new UUID(match.Groups["agent_id"].Value);
686             //string action = match.Groups["action"].Value;
687         }
688
689         private void ExecuteLinkTrackAvatar(Match match)
690         {
691             //UUID agentID = new UUID(match.Groups["friend_id"].Value);
692         }
693
694         private void ExecuteLinkObjectIm(Match match)
695         {
696             //UUID objectID = new UUID(match.Groups["object_id"].Value);
697             //string name = HttpUtility.UrlDecode(match.Groups["name"].Value);
698             //UUID ownerID = new UUID(match.Groups["owner"].Value);
699             //string groupowned = match.Groups["groupowned"].Value;
700             //string slurl = match.Groups["slurl"].Value;
701         }
702
703         private void ExecuteLinkParcel(Match match)
704         {
705             //UUID parcelID = new UUID(match.Groups["parcel_id"].Value);
706         }
707
708         private void ExecuteLinkSearch(Match match)
709         {
710             //string category = match.Groups["category"].Value;
711             //string searchTerm = HttpUtility.UrlDecode(match.Groups["search_term"].Value);
712         }
713
714         private void ExecuteLinkShareWithAvatar(Match match)
715         {
716             //UUID agentID = new UUID(match.Groups["agent_id"].Value);
717         }
718
719         private void ExecuteLinkTeleport(Match match)
720         {
721             //string name = HttpUtility.UrlDecode(match.Groups["region_name"].Value);
722             //string x = match.Groups["local_x"].Success ? match.Groups["local_x"].Value : "128";
723             //string y = match.Groups["local_y"].Success ? match.Groups["local_y"].Value : "128";
724             //string z = match.Groups["local_z"].Success ? match.Groups["local_z"].Value : "0";
725         }
726
727         private void ExecuteLinkVoiceCallAvatar(Match match)
728         {
729             //UUID agentID = new UUID(match.Groups["agent_id"].Value);
730         }
731
732         private void ExecuteLinkWearFolder(Match match)
733         {
734             //UUID folderID = new UUID(match.Groups["inventory_folder_uuid"].Value);
735         }
736
737         private void ExecuteLinkWorldMap(Match match)
738         {
739             RadegastInstance instance = RadegastInstance.GlobalInstance;
740
741             string name = HttpUtility.UrlDecode(match.Groups["region_name"].Value);
742             int x = match.Groups["local_x"].Success ? int.Parse(match.Groups["local_x"].Value) : 128;
743             int y = match.Groups["local_y"].Success ? int.Parse(match.Groups["local_y"].Value) : 128;
744             int z = match.Groups["local_z"].Success ? int.Parse(match.Groups["local_z"].Value) : 0;
745
746             instance.MainForm.MapTab.Select();
747             instance.MainForm.WorldMap.DisplayLocation(name, x, y, z);
748         }
749         #endregion
750     }
751 }