clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27  
28 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.IO;
32 using System.Reflection;
33 using System.Runtime.Remoting.Lifetime;
34 using System.Text;
35 using System.Net;
36 using System.Threading;
37 using System.Xml;
38 using log4net;
39 using OpenMetaverse;
40 using OpenMetaverse.StructuredData;
41 using Nini.Config;
42 using OpenSim;
43 using OpenSim.Framework;
44  
45 using OpenSim.Framework.Console;
46 using OpenSim.Region.Framework.Interfaces;
47 using OpenSim.Region.Framework.Scenes;
48 using OpenSim.Region.ScriptEngine.Shared;
49 using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
50 using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
51 using OpenSim.Region.ScriptEngine.Interfaces;
52 using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
53 using TPFlags = OpenSim.Framework.Constants.TeleportFlags;
54 using OpenSim.Services.Interfaces;
55 using GridRegion = OpenSim.Services.Interfaces.GridRegion;
56 using System.Text.RegularExpressions;
57  
58 using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
59 using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
60 using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
61 using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
62 using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
63 using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
64 using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
65 using PermissionMask = OpenSim.Framework.PermissionMask;
66  
67 namespace OpenSim.Region.ScriptEngine.Shared.Api
68 {
69 //////////////////////////////////////////////////////////////
70 //
71 // Level description
72 //
73 // None - Function is no threat at all. It doesn't constitute
74 // an threat to either users or the system and has no
75 // known side effects
76 //
77 // Nuisance - Abuse of this command can cause a nuisance to the
78 // region operator, such as log message spew
79 //
80 // VeryLow - Extreme levels ob abuse of this function can cause
81 // impaired functioning of the region, or very gullible
82 // users can be tricked into experiencing harmless effects
83 //
84 // Low - Intentional abuse can cause crashes or malfunction
85 // under certain circumstances, which can easily be rectified,
86 // or certain users can be tricked into certain situations
87 // in an avoidable manner.
88 //
89 // Moderate - Intentional abuse can cause denial of service and crashes
90 // with potential of data or state loss, or trusting users
91 // can be tricked into embarrassing or uncomfortable
92 // situationsa.
93 //
94 // High - Casual abuse can cause impaired functionality or temporary
95 // denial of service conditions. Intentional abuse can easily
96 // cause crashes with potential data loss, or can be used to
97 // trick experienced and cautious users into unwanted situations,
98 // or changes global data permanently and without undo ability
99 // Malicious scripting can allow theft of content
100 //
101 // VeryHigh - Even normal use may, depending on the number of instances,
102 // or frequency of use, result in severe service impairment
103 // or crash with loss of data, or can be used to cause
104 // unwanted or harmful effects on users without giving the
105 // user a means to avoid it.
106 //
107 // Severe - Even casual use is a danger to region stability, or function
108 // allows console or OS command execution, or function allows
109 // taking money without consent, or allows deletion or
110 // modification of user data, or allows the compromise of
111 // sensitive data by design.
112  
113 class FunctionPerms
114 {
115 public List<UUID> AllowedCreators;
116 public List<UUID> AllowedOwners;
117 public List<string> AllowedOwnerClasses;
118  
119 public FunctionPerms()
120 {
121 AllowedCreators = new List<UUID>();
122 AllowedOwners = new List<UUID>();
123 AllowedOwnerClasses = new List<string>();
124 }
125 }
126  
127 [Serializable]
128 public class OSSL_Api : MarshalByRefObject, IOSSL_Api, IScriptApi
129 {
130 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
131  
132 public const string GridInfoServiceConfigSectionName = "GridInfoService";
133  
134 internal IScriptEngine m_ScriptEngine;
135 internal ILSL_Api m_LSL_Api = null; // get a reference to the LSL API so we can call methods housed there
136 internal SceneObjectPart m_host;
137 internal TaskInventoryItem m_item;
138 internal bool m_OSFunctionsEnabled = false;
139 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow;
140 internal float m_ScriptDelayFactor = 1.0f;
141 internal float m_ScriptDistanceFactor = 1.0f;
142 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >();
143  
144 protected IUrlModule m_UrlModule = null;
145  
146 public void Initialize(
147 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
148 {
149 m_ScriptEngine = scriptEngine;
150 m_host = host;
151 m_item = item;
152  
153 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
154  
155 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false))
156 m_OSFunctionsEnabled = true;
157  
158 m_ScriptDelayFactor =
159 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
160 m_ScriptDistanceFactor =
161 m_ScriptEngine.Config.GetFloat("ScriptDistanceLimitFactor", 1.0f);
162  
163 string risk = m_ScriptEngine.Config.GetString("OSFunctionThreatLevel", "VeryLow");
164 switch (risk)
165 {
166 case "NoAccess":
167 m_MaxThreatLevel = ThreatLevel.NoAccess;
168 break;
169 case "None":
170 m_MaxThreatLevel = ThreatLevel.None;
171 break;
172 case "VeryLow":
173 m_MaxThreatLevel = ThreatLevel.VeryLow;
174 break;
175 case "Low":
176 m_MaxThreatLevel = ThreatLevel.Low;
177 break;
178 case "Moderate":
179 m_MaxThreatLevel = ThreatLevel.Moderate;
180 break;
181 case "High":
182 m_MaxThreatLevel = ThreatLevel.High;
183 break;
184 case "VeryHigh":
185 m_MaxThreatLevel = ThreatLevel.VeryHigh;
186 break;
187 case "Severe":
188 m_MaxThreatLevel = ThreatLevel.Severe;
189 break;
190 default:
191 break;
192 }
193 }
194  
195 public override Object InitializeLifetimeService()
196 {
197 ILease lease = (ILease)base.InitializeLifetimeService();
198  
199 if (lease.CurrentState == LeaseState.Initial)
200 {
201 lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
202 // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
203 // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
204 }
205 return lease;
206 }
207  
208 public Scene World
209 {
210 get { return m_ScriptEngine.World; }
211 }
212  
213 internal void OSSLError(string msg)
214 {
215 throw new ScriptException("OSSL Runtime Error: " + msg);
216 }
217  
218 /// <summary>
219 /// Initialize the LSL interface.
220 /// </summary>
221 /// <remarks>
222 /// FIXME: This is an abomination. We should be able to set this up earlier but currently we have no
223 /// guarantee the interface is present on Initialize(). There needs to be another post initialize call from
224 /// ScriptInstance.
225 /// </remarks>
226 private void InitLSL()
227 {
228 if (m_LSL_Api != null)
229 return;
230  
231 m_LSL_Api = (ILSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "LSL");
232 }
233  
234 //
235 //Dumps an error message on the debug console.
236 //
237  
238 internal void OSSLShoutError(string message)
239 {
240 if (message.Length > 1023)
241 message = message.Substring(0, 1023);
242  
243 World.SimChat(Utils.StringToBytes(message),
244 ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
245  
246 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
247 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message);
248 }
249  
250 // Returns of the function is allowed. Throws a script exception if not allowed.
251 public void CheckThreatLevel(ThreatLevel level, string function)
252 {
253 if (!m_OSFunctionsEnabled)
254 OSSLError(String.Format("{0} permission denied. All OS functions are disabled.", function)); // throws
255  
256 string reasonWhyNot = CheckThreatLevelTest(level, function);
257 if (!String.IsNullOrEmpty(reasonWhyNot))
258 {
259 OSSLError(reasonWhyNot);
260 }
261 }
262  
263 // Check to see if function is allowed. Returns an empty string if function permitted
264 // or a string explaining why this function can't be used.
265 private string CheckThreatLevelTest(ThreatLevel level, string function)
266 {
267 if (!m_FunctionPerms.ContainsKey(function))
268 {
269 FunctionPerms perms = new FunctionPerms();
270 m_FunctionPerms[function] = perms;
271  
272 string ownerPerm = m_ScriptEngine.Config.GetString("Allow_" + function, "");
273 string creatorPerm = m_ScriptEngine.Config.GetString("Creators_" + function, "");
274 if (ownerPerm == "" && creatorPerm == "")
275 {
276 // Default behavior
277 perms.AllowedOwners = null;
278 perms.AllowedCreators = null;
279 perms.AllowedOwnerClasses = null;
280 }
281 else
282 {
283 bool allowed;
284  
285 if (bool.TryParse(ownerPerm, out allowed))
286 {
287 // Boolean given
288 if (allowed)
289 {
290 // Allow globally
291 perms.AllowedOwners.Add(UUID.Zero);
292 }
293 }
294 else
295 {
296 string[] ids = ownerPerm.Split(new char[] {','});
297 foreach (string id in ids)
298 {
299 string current = id.Trim();
300 if (current.ToUpper() == "PARCEL_GROUP_MEMBER" || current.ToUpper() == "PARCEL_OWNER" || current.ToUpper() == "ESTATE_MANAGER" || current.ToUpper() == "ESTATE_OWNER")
301 {
302 if (!perms.AllowedOwnerClasses.Contains(current))
303 perms.AllowedOwnerClasses.Add(current.ToUpper());
304 }
305 else
306 {
307 UUID uuid;
308  
309 if (UUID.TryParse(current, out uuid))
310 {
311 if (uuid != UUID.Zero)
312 perms.AllowedOwners.Add(uuid);
313 }
314 }
315 }
316  
317 ids = creatorPerm.Split(new char[] {','});
318 foreach (string id in ids)
319 {
320 string current = id.Trim();
321 UUID uuid;
322  
323 if (UUID.TryParse(current, out uuid))
324 {
325 if (uuid != UUID.Zero)
326 perms.AllowedCreators.Add(uuid);
327 }
328 }
329 }
330 }
331 }
332  
333 // If the list is null, then the value was true / undefined
334 // Threat level governs permissions in this case
335 //
336 // If the list is non-null, then it is a list of UUIDs allowed
337 // to use that particular function. False causes an empty
338 // list and therefore means "no one"
339 //
340 // To allow use by anyone, the list contains UUID.Zero
341 //
342 if (m_FunctionPerms[function].AllowedOwners == null)
343 {
344 // Allow / disallow by threat level
345 if (level > m_MaxThreatLevel)
346 return
347 String.Format(
348 "{0} permission denied. Allowed threat level is {1} but function threat level is {2}.",
349 function, m_MaxThreatLevel, level);
350 }
351 else
352 {
353 if (!m_FunctionPerms[function].AllowedOwners.Contains(UUID.Zero))
354 {
355 // Not anyone. Do detailed checks
356 if (m_FunctionPerms[function].AllowedOwners.Contains(m_host.OwnerID))
357 {
358 // prim owner is in the list of allowed owners
359 return String.Empty;
360 }
361  
362 UUID ownerID = m_item.OwnerID;
363  
364 //OSSL only may be used if object is in the same group as the parcel
365 if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("PARCEL_GROUP_MEMBER"))
366 {
367 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
368  
369 if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero)
370 {
371 return String.Empty;
372 }
373 }
374  
375 //Only Parcelowners may use the function
376 if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("PARCEL_OWNER"))
377 {
378 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
379  
380 if (land.LandData.OwnerID == ownerID)
381 {
382 return String.Empty;
383 }
384 }
385  
386 //Only Estate Managers may use the function
387 if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("ESTATE_MANAGER"))
388 {
389 //Only Estate Managers may use the function
390 if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID)
391 {
392 return String.Empty;
393 }
394 }
395  
396 //Only regionowners may use the function
397 if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("ESTATE_OWNER"))
398 {
399 if (World.RegionInfo.EstateSettings.EstateOwner == ownerID)
400 {
401 return String.Empty;
402 }
403 }
404  
405 if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID))
406 return(
407 String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.",
408 function));
409  
410 if (m_item.CreatorID != ownerID)
411 {
412 if ((m_item.CurrentPermissions & (uint)PermissionMask.Modify) != 0)
413 return String.Format("{0} permission denied. Script permissions error.", function);
414  
415 }
416 }
417 }
418 return String.Empty;
419 }
420  
421 internal void OSSLDeprecated(string function, string replacement)
422 {
423 OSSLShoutError(string.Format("Use of function {0} is deprecated. Use {1} instead.", function, replacement));
424 }
425  
426 protected void ScriptSleep(int delay)
427 {
428 delay = (int)((float)delay * m_ScriptDelayFactor);
429 if (delay == 0)
430 return;
431 System.Threading.Thread.Sleep(delay);
432 }
433  
434 public LSL_Integer osSetTerrainHeight(int x, int y, double val)
435 {
436 CheckThreatLevel(ThreatLevel.High, "osSetTerrainHeight");
437  
438 return SetTerrainHeight(x, y, val);
439 }
440  
441 public LSL_Integer osTerrainSetHeight(int x, int y, double val)
442 {
443 CheckThreatLevel(ThreatLevel.High, "osTerrainSetHeight");
444 OSSLDeprecated("osTerrainSetHeight", "osSetTerrainHeight");
445  
446 return SetTerrainHeight(x, y, val);
447 }
448  
449 private LSL_Integer SetTerrainHeight(int x, int y, double val)
450 {
451 m_host.AddScriptLPS(1);
452  
453 if (x > (World.RegionInfo.RegionSizeX - 1) || x < 0 || y > (World.RegionInfo.RegionSizeY - 1) || y < 0)
454 OSSLError("osSetTerrainHeight: Coordinate out of bounds");
455  
456 if (World.Permissions.CanTerraformLand(m_host.OwnerID, new Vector3(x, y, 0)))
457 {
458 World.Heightmap[x, y] = val;
459 return 1;
460 }
461 else
462 {
463 return 0;
464 }
465 }
466  
467 public LSL_Float osGetTerrainHeight(int x, int y)
468 {
469 CheckThreatLevel(ThreatLevel.None, "osGetTerrainHeight");
470 return GetTerrainHeight(x, y);
471 }
472  
473 public LSL_Float osTerrainGetHeight(int x, int y)
474 {
475 CheckThreatLevel(ThreatLevel.None, "osTerrainGetHeight");
476 OSSLDeprecated("osTerrainGetHeight", "osGetTerrainHeight");
477 return GetTerrainHeight(x, y);
478 }
479  
480 private LSL_Float GetTerrainHeight(int x, int y)
481 {
482 m_host.AddScriptLPS(1);
483 if (x > (World.RegionInfo.RegionSizeX - 1) || x < 0 || y > (World.RegionInfo.RegionSizeY - 1) || y < 0)
484 OSSLError("osGetTerrainHeight: Coordinate out of bounds");
485  
486 return World.Heightmap[x, y];
487 }
488  
489 public void osTerrainFlush()
490 {
491 CheckThreatLevel(ThreatLevel.VeryLow, "osTerrainFlush");
492 m_host.AddScriptLPS(1);
493  
494 ITerrainModule terrainModule = World.RequestModuleInterface<ITerrainModule>();
495 if (terrainModule != null) terrainModule.TaintTerrain();
496 }
497  
498 public int osRegionRestart(double seconds)
499 {
500 // This is High here because region restart is not reliable
501 // it may result in the region staying down or becoming
502 // unstable. This should be changed to Low or VeryLow once
503 // The underlying functionality is fixed, since the security
504 // as such is sound
505 //
506 CheckThreatLevel(ThreatLevel.High, "osRegionRestart");
507  
508 IRestartModule restartModule = World.RequestModuleInterface<IRestartModule>();
509 m_host.AddScriptLPS(1);
510 if (World.Permissions.CanIssueEstateCommand(m_host.OwnerID, false) && (restartModule != null))
511 {
512 if (seconds < 15)
513 {
514 restartModule.AbortRestart("Restart aborted");
515 return 1;
516 }
517  
518 List<int> times = new List<int>();
519 while (seconds > 0)
520 {
521 times.Add((int)seconds);
522 if (seconds > 300)
523 seconds -= 120;
524 else if (seconds > 30)
525 seconds -= 30;
526 else
527 seconds -= 15;
528 }
529  
530 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), true);
531 return 1;
532 }
533 else
534 {
535 return 0;
536 }
537 }
538  
539 public void osRegionNotice(string msg)
540 {
541 // This implementation provides absolutely no security
542 // It's high griefing potential makes this classification
543 // necessary
544 //
545 CheckThreatLevel(ThreatLevel.VeryHigh, "osRegionNotice");
546  
547 m_host.AddScriptLPS(1);
548  
549 IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
550  
551 if (dm != null)
552 dm.SendGeneralAlert(msg);
553 }
554  
555 public void osSetRot(UUID target, Quaternion rotation)
556 {
557 // This function has no security. It can be used to destroy
558 // arbitrary builds the user would normally have no rights to
559 //
560 CheckThreatLevel(ThreatLevel.VeryHigh, "osSetRot");
561  
562 m_host.AddScriptLPS(1);
563 if (World.Entities.ContainsKey(target))
564 {
565 EntityBase entity;
566 if (World.Entities.TryGetValue(target, out entity))
567 {
568 if (entity is SceneObjectGroup)
569 ((SceneObjectGroup)entity).UpdateGroupRotationR(rotation);
570 else if (entity is ScenePresence)
571 ((ScenePresence)entity).Rotation = rotation;
572 }
573 }
574 else
575 {
576 OSSLError("osSetRot: Invalid target");
577 }
578 }
579  
580 public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams,
581 int timer)
582 {
583 // This may be upgraded depending on the griefing or DOS
584 // potential, or guarded with a delay
585 //
586 CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureURL");
587  
588 m_host.AddScriptLPS(1);
589 if (dynamicID == String.Empty)
590 {
591 IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
592 UUID createdTexture =
593 textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url,
594 extraParams, timer);
595 return createdTexture.ToString();
596 }
597 else
598 {
599 //TODO update existing dynamic textures
600 }
601  
602 return UUID.Zero.ToString();
603 }
604  
605 public string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams,
606 int timer, int alpha)
607 {
608 CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureURLBlend");
609  
610 m_host.AddScriptLPS(1);
611 if (dynamicID == String.Empty)
612 {
613 IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
614 UUID createdTexture =
615 textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url,
616 extraParams, timer, true, (byte) alpha);
617 return createdTexture.ToString();
618 }
619 else
620 {
621 //TODO update existing dynamic textures
622 }
623  
624 return UUID.Zero.ToString();
625 }
626  
627 public string osSetDynamicTextureURLBlendFace(string dynamicID, string contentType, string url, string extraParams,
628 bool blend, int disp, int timer, int alpha, int face)
629 {
630 CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureURLBlendFace");
631  
632 m_host.AddScriptLPS(1);
633 if (dynamicID == String.Empty)
634 {
635 IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
636 UUID createdTexture =
637 textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url,
638 extraParams, timer, blend, disp, (byte) alpha, face);
639 return createdTexture.ToString();
640 }
641 else
642 {
643 //TODO update existing dynamic textures
644 }
645  
646 return UUID.Zero.ToString();
647 }
648  
649 public string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams,
650 int timer)
651 {
652 CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureData");
653  
654 m_host.AddScriptLPS(1);
655 if (dynamicID == String.Empty)
656 {
657 IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
658 if (textureManager != null)
659 {
660 if (extraParams == String.Empty)
661 {
662 extraParams = "256";
663 }
664 UUID createdTexture =
665 textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data,
666 extraParams, timer);
667 return createdTexture.ToString();
668 }
669 }
670 else
671 {
672 //TODO update existing dynamic textures
673 }
674  
675 return UUID.Zero.ToString();
676 }
677  
678 public string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams,
679 int timer, int alpha)
680 {
681 CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureDataBlend");
682  
683 m_host.AddScriptLPS(1);
684 if (dynamicID == String.Empty)
685 {
686 IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
687 if (textureManager != null)
688 {
689 if (extraParams == String.Empty)
690 {
691 extraParams = "256";
692 }
693 UUID createdTexture =
694 textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data,
695 extraParams, timer, true, (byte) alpha);
696 return createdTexture.ToString();
697 }
698 }
699 else
700 {
701 //TODO update existing dynamic textures
702 }
703  
704 return UUID.Zero.ToString();
705 }
706  
707 public string osSetDynamicTextureDataBlendFace(string dynamicID, string contentType, string data, string extraParams,
708 bool blend, int disp, int timer, int alpha, int face)
709 {
710 CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureDataBlendFace");
711  
712 m_host.AddScriptLPS(1);
713 if (dynamicID == String.Empty)
714 {
715 IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
716 if (textureManager != null)
717 {
718 if (extraParams == String.Empty)
719 {
720 extraParams = "256";
721 }
722 UUID createdTexture =
723 textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data,
724 extraParams, timer, blend, disp, (byte) alpha, face);
725 return createdTexture.ToString();
726 }
727 }
728 else
729 {
730 //TODO update existing dynamic textures
731 }
732  
733 return UUID.Zero.ToString();
734 }
735  
736 public bool osConsoleCommand(string command)
737 {
738 CheckThreatLevel(ThreatLevel.Severe, "osConsoleCommand");
739  
740 m_host.AddScriptLPS(1);
741  
742 // For safety, we add another permission check here, and don't rely only on the standard OSSL permissions
743 if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID))
744 {
745 MainConsole.Instance.RunCommand(command);
746 return true;
747 }
748  
749 return false;
750 }
751  
752 public void osSetPrimFloatOnWater(int floatYN)
753 {
754 CheckThreatLevel(ThreatLevel.VeryLow, "osSetPrimFloatOnWater");
755  
756 m_host.AddScriptLPS(1);
757  
758 m_host.ParentGroup.RootPart.SetFloatOnWater(floatYN);
759 }
760  
761 // Teleport functions
762 public void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat)
763 {
764 // High because there is no security check. High griefer potential
765 //
766 CheckThreatLevel(ThreatLevel.Severe, "osTeleportAgent");
767  
768 TeleportAgent(agent, regionName, position, lookat, false);
769 }
770  
771 private void TeleportAgent(string agent, string regionName,
772 LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions)
773 {
774 m_host.AddScriptLPS(1);
775 UUID agentId = new UUID();
776 if (UUID.TryParse(agent, out agentId))
777 {
778 ScenePresence presence = World.GetScenePresence(agentId);
779 if (presence != null)
780 {
781 // For osTeleportAgent, agent must be over owners land to avoid abuse
782 // For osTeleportOwner, this restriction isn't necessary
783  
784 // commented out because its redundant and uneeded please remove eventually.
785 // if (relaxRestrictions ||
786 // m_host.OwnerID
787 // == World.LandChannel.GetLandObject(
788 // presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
789 // {
790  
791 // We will launch the teleport on a new thread so that when the script threads are terminated
792 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
793 Util.FireAndForget(o => World.RequestTeleportLocation(
794 presence.ControllingClient, regionName, position,
795 lookat, (uint)TPFlags.ViaLocation));
796  
797 ScriptSleep(5000);
798  
799 // }
800  
801 }
802 }
803 }
804  
805 public void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat)
806 {
807 // High because there is no security check. High griefer potential
808 //
809 CheckThreatLevel(ThreatLevel.Severe, "osTeleportAgent");
810  
811 TeleportAgent(agent, regionX, regionY, position, lookat, false);
812 }
813  
814 private void TeleportAgent(string agent, int regionX, int regionY,
815 LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions)
816 {
817 // ulong regionHandle = Util.UIntsToLong(((uint)regionX * (uint)Constants.RegionSize), ((uint)regionY * (uint)Constants.RegionSize));
818 ulong regionHandle = Util.RegionLocToHandle((uint)regionX, (uint)regionY);
819  
820 m_host.AddScriptLPS(1);
821 UUID agentId = new UUID();
822 if (UUID.TryParse(agent, out agentId))
823 {
824 ScenePresence presence = World.GetScenePresence(agentId);
825 if (presence != null)
826 {
827 // For osTeleportAgent, agent must be over owners land to avoid abuse
828 // For osTeleportOwner, this restriction isn't necessary
829  
830 // commented out because its redundant and uneeded please remove eventually.
831 // if (relaxRestrictions ||
832 // m_host.OwnerID
833 // == World.LandChannel.GetLandObject(
834 // presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
835 // {
836  
837 // We will launch the teleport on a new thread so that when the script threads are terminated
838 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
839 Util.FireAndForget(o => World.RequestTeleportLocation(
840 presence.ControllingClient, regionHandle,
841 position, lookat, (uint)TPFlags.ViaLocation));
842  
843 ScriptSleep(5000);
844  
845 // }
846  
847 }
848 }
849 }
850  
851 public void osTeleportAgent(string agent, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat)
852 {
853 osTeleportAgent(agent, World.RegionInfo.RegionName, position, lookat);
854 }
855  
856 public void osTeleportOwner(string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat)
857 {
858 // Threat level None because this is what can already be done with the World Map in the viewer
859 CheckThreatLevel(ThreatLevel.None, "osTeleportOwner");
860  
861 TeleportAgent(m_host.OwnerID.ToString(), regionName, position, lookat, true);
862 }
863  
864 public void osTeleportOwner(LSL_Types.Vector3 position, LSL_Types.Vector3 lookat)
865 {
866 osTeleportOwner(World.RegionInfo.RegionName, position, lookat);
867 }
868  
869 public void osTeleportOwner(int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat)
870 {
871 CheckThreatLevel(ThreatLevel.None, "osTeleportOwner");
872  
873 TeleportAgent(m_host.OwnerID.ToString(), regionX, regionY, position, lookat, true);
874 }
875  
876 // Functions that get information from the agent itself.
877 //
878 // osGetAgentIP - this is used to determine the IP address of
879 //the client. This is needed to help configure other in world
880 //resources based on the IP address of the clients connected.
881 //I think High is a good risk level for this, as it is an
882 //information leak.
883 public string osGetAgentIP(string agent)
884 {
885 CheckThreatLevel(ThreatLevel.High, "osGetAgentIP");
886  
887 UUID avatarID = (UUID)agent;
888  
889 m_host.AddScriptLPS(1);
890 if (World.Entities.ContainsKey((UUID)agent) && World.Entities[avatarID] is ScenePresence)
891 {
892 ScenePresence target = (ScenePresence)World.Entities[avatarID];
893 return target.ControllingClient.RemoteEndPoint.Address.ToString();
894 }
895  
896 // fall through case, just return nothing
897 return "";
898 }
899  
900 // Get a list of all the avatars/agents in the region
901 public LSL_List osGetAgents()
902 {
903 // threat level is None as we could get this information with an
904 // in-world script as well, just not as efficient
905 CheckThreatLevel(ThreatLevel.None, "osGetAgents");
906 m_host.AddScriptLPS(1);
907  
908 LSL_List result = new LSL_List();
909 World.ForEachRootScenePresence(delegate(ScenePresence sp)
910 {
911 result.Add(new LSL_String(sp.Name));
912 });
913 return result;
914 }
915  
916 // Adam's super super custom animation functions
917 public void osAvatarPlayAnimation(string avatar, string animation)
918 {
919 CheckThreatLevel(ThreatLevel.VeryHigh, "osAvatarPlayAnimation");
920  
921 AvatarPlayAnimation(avatar, animation);
922 }
923  
924 private void AvatarPlayAnimation(string avatar, string animation)
925 {
926 UUID avatarID = (UUID)avatar;
927  
928 m_host.AddScriptLPS(1);
929 if (World.Entities.ContainsKey((UUID)avatar) && World.Entities[avatarID] is ScenePresence)
930 {
931 ScenePresence target = (ScenePresence)World.Entities[avatarID];
932 if (target != null)
933 {
934 UUID animID=UUID.Zero;
935 lock (m_host.TaskInventory)
936 {
937 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
938 {
939 if (inv.Value.Name == animation)
940 {
941 if (inv.Value.Type == (int)AssetType.Animation)
942 animID = inv.Value.AssetID;
943 continue;
944 }
945 }
946 }
947 if (animID == UUID.Zero)
948 target.Animator.AddAnimation(animation, m_host.UUID);
949 else
950 target.Animator.AddAnimation(animID, m_host.UUID);
951 }
952 }
953 }
954  
955 public void osAvatarStopAnimation(string avatar, string animation)
956 {
957 CheckThreatLevel(ThreatLevel.VeryHigh, "osAvatarStopAnimation");
958  
959 AvatarStopAnimation(avatar, animation);
960 }
961  
962 private void AvatarStopAnimation(string avatar, string animation)
963 {
964 UUID avatarID = (UUID)avatar;
965  
966 m_host.AddScriptLPS(1);
967  
968 // FIXME: What we really want to do here is factor out the similar code in llStopAnimation() to a common
969 // method (though see that doesn't do the is animation check, which is probably a bug) and have both
970 // these functions call that common code. However, this does mean navigating the brain-dead requirement
971 // of calling InitLSL()
972 if (World.Entities.ContainsKey(avatarID) && World.Entities[avatarID] is ScenePresence)
973 {
974 ScenePresence target = (ScenePresence)World.Entities[avatarID];
975 if (target != null)
976 {
977 UUID animID;
978  
979 if (!UUID.TryParse(animation, out animID))
980 {
981 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(animation);
982 if (item != null && item.Type == (int)AssetType.Animation)
983 animID = item.AssetID;
984 else
985 animID = UUID.Zero;
986 }
987  
988 if (animID == UUID.Zero)
989 target.Animator.RemoveAnimation(animation);
990 else
991 target.Animator.RemoveAnimation(animID, true);
992 }
993 }
994 }
995  
996 //Texture draw functions
997 public string osMovePen(string drawList, int x, int y)
998 {
999 CheckThreatLevel(ThreatLevel.None, "osMovePen");
1000  
1001 m_host.AddScriptLPS(1);
1002 drawList += "MoveTo " + x + "," + y + ";";
1003 return drawList;
1004 }
1005  
1006 public string osDrawLine(string drawList, int startX, int startY, int endX, int endY)
1007 {
1008 CheckThreatLevel(ThreatLevel.None, "osDrawLine");
1009  
1010 m_host.AddScriptLPS(1);
1011 drawList += "MoveTo "+ startX+","+ startY +"; LineTo "+endX +","+endY +"; ";
1012 return drawList;
1013 }
1014  
1015 public string osDrawLine(string drawList, int endX, int endY)
1016 {
1017 CheckThreatLevel(ThreatLevel.None, "osDrawLine");
1018  
1019 m_host.AddScriptLPS(1);
1020 drawList += "LineTo " + endX + "," + endY + "; ";
1021 return drawList;
1022 }
1023  
1024 public string osDrawText(string drawList, string text)
1025 {
1026 CheckThreatLevel(ThreatLevel.None, "osDrawText");
1027  
1028 m_host.AddScriptLPS(1);
1029 drawList += "Text " + text + "; ";
1030 return drawList;
1031 }
1032  
1033 public string osDrawEllipse(string drawList, int width, int height)
1034 {
1035 CheckThreatLevel(ThreatLevel.None, "osDrawEllipse");
1036  
1037 m_host.AddScriptLPS(1);
1038 drawList += "Ellipse " + width + "," + height + "; ";
1039 return drawList;
1040 }
1041  
1042 public string osDrawRectangle(string drawList, int width, int height)
1043 {
1044 CheckThreatLevel(ThreatLevel.None, "osDrawRectangle");
1045  
1046 m_host.AddScriptLPS(1);
1047 drawList += "Rectangle " + width + "," + height + "; ";
1048 return drawList;
1049 }
1050  
1051 public string osDrawFilledRectangle(string drawList, int width, int height)
1052 {
1053 CheckThreatLevel(ThreatLevel.None, "osDrawFilledRectangle");
1054  
1055 m_host.AddScriptLPS(1);
1056 drawList += "FillRectangle " + width + "," + height + "; ";
1057 return drawList;
1058 }
1059  
1060 public string osDrawFilledPolygon(string drawList, LSL_List x, LSL_List y)
1061 {
1062 CheckThreatLevel(ThreatLevel.None, "osDrawFilledPolygon");
1063  
1064 m_host.AddScriptLPS(1);
1065  
1066 if (x.Length != y.Length || x.Length < 3)
1067 {
1068 return "";
1069 }
1070 drawList += "FillPolygon " + x.GetLSLStringItem(0) + "," + y.GetLSLStringItem(0);
1071 for (int i = 1; i < x.Length; i++)
1072 {
1073 drawList += "," + x.GetLSLStringItem(i) + "," + y.GetLSLStringItem(i);
1074 }
1075 drawList += "; ";
1076 return drawList;
1077 }
1078  
1079 public string osDrawPolygon(string drawList, LSL_List x, LSL_List y)
1080 {
1081 CheckThreatLevel(ThreatLevel.None, "osDrawPolygon");
1082  
1083 m_host.AddScriptLPS(1);
1084  
1085 if (x.Length != y.Length || x.Length < 3)
1086 {
1087 return "";
1088 }
1089 drawList += "Polygon " + x.GetLSLStringItem(0) + "," + y.GetLSLStringItem(0);
1090 for (int i = 1; i < x.Length; i++)
1091 {
1092 drawList += "," + x.GetLSLStringItem(i) + "," + y.GetLSLStringItem(i);
1093 }
1094 drawList += "; ";
1095 return drawList;
1096 }
1097  
1098 public string osSetFontSize(string drawList, int fontSize)
1099 {
1100 CheckThreatLevel(ThreatLevel.None, "osSetFontSize");
1101  
1102 m_host.AddScriptLPS(1);
1103 drawList += "FontSize "+ fontSize +"; ";
1104 return drawList;
1105 }
1106  
1107 public string osSetFontName(string drawList, string fontName)
1108 {
1109 CheckThreatLevel(ThreatLevel.None, "osSetFontName");
1110  
1111 m_host.AddScriptLPS(1);
1112 drawList += "FontName "+ fontName +"; ";
1113 return drawList;
1114 }
1115  
1116 public string osSetPenSize(string drawList, int penSize)
1117 {
1118 CheckThreatLevel(ThreatLevel.None, "osSetPenSize");
1119  
1120 m_host.AddScriptLPS(1);
1121 drawList += "PenSize " + penSize + "; ";
1122 return drawList;
1123 }
1124  
1125 public string osSetPenColor(string drawList, string color)
1126 {
1127 CheckThreatLevel(ThreatLevel.None, "osSetPenColor");
1128  
1129 m_host.AddScriptLPS(1);
1130 drawList += "PenColor " + color + "; ";
1131 return drawList;
1132 }
1133  
1134 // Deprecated
1135 public string osSetPenColour(string drawList, string colour)
1136 {
1137 CheckThreatLevel(ThreatLevel.None, "osSetPenColour");
1138 OSSLDeprecated("osSetPenColour", "osSetPenColor");
1139  
1140 m_host.AddScriptLPS(1);
1141 drawList += "PenColour " + colour + "; ";
1142 return drawList;
1143 }
1144  
1145 public string osSetPenCap(string drawList, string direction, string type)
1146 {
1147 CheckThreatLevel(ThreatLevel.None, "osSetPenCap");
1148  
1149 m_host.AddScriptLPS(1);
1150 drawList += "PenCap " + direction + "," + type + "; ";
1151 return drawList;
1152 }
1153  
1154 public string osDrawImage(string drawList, int width, int height, string imageUrl)
1155 {
1156 CheckThreatLevel(ThreatLevel.None, "osDrawImage");
1157  
1158 m_host.AddScriptLPS(1);
1159 drawList +="Image " +width + "," + height+ ","+ imageUrl +"; " ;
1160 return drawList;
1161 }
1162  
1163 public LSL_Vector osGetDrawStringSize(string contentType, string text, string fontName, int fontSize)
1164 {
1165 CheckThreatLevel(ThreatLevel.VeryLow, "osGetDrawStringSize");
1166 m_host.AddScriptLPS(1);
1167  
1168 LSL_Vector vec = new LSL_Vector(0,0,0);
1169 IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
1170 if (textureManager != null)
1171 {
1172 double xSize, ySize;
1173 textureManager.GetDrawStringSize(contentType, text, fontName, fontSize,
1174 out xSize, out ySize);
1175 vec.x = xSize;
1176 vec.y = ySize;
1177 }
1178 return vec;
1179 }
1180  
1181 public void osSetStateEvents(int events)
1182 {
1183 // This function is a hack. There is no reason for it's existence
1184 // anymore, since state events now work properly.
1185 // It was probably added as a crutch or debugging aid, and
1186 // should be removed
1187 //
1188 CheckThreatLevel(ThreatLevel.High, "osSetStateEvents");
1189 m_host.AddScriptLPS(1);
1190  
1191 m_host.SetScriptEvents(m_item.ItemID, events);
1192 }
1193  
1194 public void osSetRegionWaterHeight(double height)
1195 {
1196 CheckThreatLevel(ThreatLevel.High, "osSetRegionWaterHeight");
1197  
1198 m_host.AddScriptLPS(1);
1199  
1200 World.EventManager.TriggerRequestChangeWaterHeight((float)height);
1201 }
1202  
1203 /// <summary>
1204 /// Changes the Region Sun Settings, then Triggers a Sun Update
1205 /// </summary>
1206 /// <param name="useEstateSun">True to use Estate Sun instead of Region Sun</param>
1207 /// <param name="sunFixed">True to keep the sun stationary</param>
1208 /// <param name="sunHour">The "Sun Hour" that is desired, 0...24, with 0 just after SunRise</param>
1209 public void osSetRegionSunSettings(bool useEstateSun, bool sunFixed, double sunHour)
1210 {
1211 CheckThreatLevel(ThreatLevel.High, "osSetRegionSunSettings");
1212  
1213 m_host.AddScriptLPS(1);
1214  
1215 while (sunHour > 24.0)
1216 sunHour -= 24.0;
1217  
1218 while (sunHour < 0)
1219 sunHour += 24.0;
1220  
1221 World.RegionInfo.RegionSettings.UseEstateSun = useEstateSun;
1222 World.RegionInfo.RegionSettings.SunPosition = sunHour + 6; // LL Region Sun Hour is 6 to 30
1223 World.RegionInfo.RegionSettings.FixedSun = sunFixed;
1224 World.RegionInfo.RegionSettings.Save();
1225  
1226 World.EventManager.TriggerEstateToolsSunUpdate(World.RegionInfo.RegionHandle);
1227 }
1228  
1229 /// <summary>
1230 /// Changes the Estate Sun Settings, then Triggers a Sun Update
1231 /// </summary>
1232 /// <param name="sunFixed">True to keep the sun stationary, false to use global time</param>
1233 /// <param name="sunHour">The "Sun Hour" that is desired, 0...24, with 0 just after SunRise</param>
1234 public void osSetEstateSunSettings(bool sunFixed, double sunHour)
1235 {
1236 CheckThreatLevel(ThreatLevel.High, "osSetEstateSunSettings");
1237  
1238 m_host.AddScriptLPS(1);
1239  
1240 while (sunHour > 24.0)
1241 sunHour -= 24.0;
1242  
1243 while (sunHour < 0)
1244 sunHour += 24.0;
1245  
1246 World.RegionInfo.EstateSettings.UseGlobalTime = !sunFixed;
1247 World.RegionInfo.EstateSettings.SunPosition = sunHour;
1248 World.RegionInfo.EstateSettings.FixedSun = sunFixed;
1249 World.EstateDataService.StoreEstateSettings(World.RegionInfo.EstateSettings);
1250  
1251 World.EventManager.TriggerEstateToolsSunUpdate(World.RegionInfo.RegionHandle);
1252 }
1253  
1254 /// <summary>
1255 /// Return the current Sun Hour 0...24, with 0 being roughly sun-rise
1256 /// </summary>
1257 /// <returns></returns>
1258 public double osGetCurrentSunHour()
1259 {
1260 CheckThreatLevel(ThreatLevel.None, "osGetCurrentSunHour");
1261  
1262 m_host.AddScriptLPS(1);
1263  
1264 // Must adjust for the fact that Region Sun Settings are still LL offset
1265 double sunHour = World.RegionInfo.RegionSettings.SunPosition - 6;
1266  
1267 // See if the sun module has registered itself, if so it's authoritative
1268 ISunModule module = World.RequestModuleInterface<ISunModule>();
1269 if (module != null)
1270 {
1271 sunHour = module.GetCurrentSunHour();
1272 }
1273  
1274 return sunHour;
1275 }
1276  
1277 public double osSunGetParam(string param)
1278 {
1279 CheckThreatLevel(ThreatLevel.None, "osSunGetParam");
1280 OSSLDeprecated("osSunGetParam", "osGetSunParam");
1281 return GetSunParam(param);
1282 }
1283  
1284 public double osGetSunParam(string param)
1285 {
1286 CheckThreatLevel(ThreatLevel.None, "osGetSunParam");
1287 return GetSunParam(param);
1288 }
1289  
1290 private double GetSunParam(string param)
1291 {
1292 m_host.AddScriptLPS(1);
1293  
1294 double value = 0.0;
1295  
1296 ISunModule module = World.RequestModuleInterface<ISunModule>();
1297 if (module != null)
1298 {
1299 value = module.GetSunParameter(param);
1300 }
1301  
1302 return value;
1303 }
1304  
1305 public void osSunSetParam(string param, double value)
1306 {
1307 CheckThreatLevel(ThreatLevel.None, "osSunSetParam");
1308 OSSLDeprecated("osSunSetParam", "osSetSunParam");
1309 SetSunParam(param, value);
1310 }
1311  
1312 public void osSetSunParam(string param, double value)
1313 {
1314 CheckThreatLevel(ThreatLevel.None, "osSetSunParam");
1315 SetSunParam(param, value);
1316 }
1317  
1318 private void SetSunParam(string param, double value)
1319 {
1320 m_host.AddScriptLPS(1);
1321  
1322 ISunModule module = World.RequestModuleInterface<ISunModule>();
1323 if (module != null)
1324 {
1325 module.SetSunParameter(param, value);
1326 }
1327 }
1328  
1329 public string osWindActiveModelPluginName()
1330 {
1331 CheckThreatLevel(ThreatLevel.None, "osWindActiveModelPluginName");
1332 m_host.AddScriptLPS(1);
1333  
1334 IWindModule module = World.RequestModuleInterface<IWindModule>();
1335 if (module != null)
1336 {
1337 return module.WindActiveModelPluginName;
1338 }
1339  
1340 return String.Empty;
1341 }
1342  
1343 public void osSetWindParam(string plugin, string param, LSL_Float value)
1344 {
1345 CheckThreatLevel(ThreatLevel.VeryLow, "osSetWindParam");
1346 m_host.AddScriptLPS(1);
1347  
1348 IWindModule module = World.RequestModuleInterface<IWindModule>();
1349 if (module != null)
1350 {
1351 try
1352 {
1353 module.WindParamSet(plugin, param, (float)value);
1354 }
1355 catch (Exception) { }
1356 }
1357 }
1358  
1359 public LSL_Float osGetWindParam(string plugin, string param)
1360 {
1361 CheckThreatLevel(ThreatLevel.VeryLow, "osGetWindParam");
1362 m_host.AddScriptLPS(1);
1363  
1364 IWindModule module = World.RequestModuleInterface<IWindModule>();
1365 if (module != null)
1366 {
1367 return module.WindParamGet(plugin, param);
1368 }
1369  
1370 return 0.0f;
1371 }
1372  
1373 // Routines for creating and managing parcels programmatically
1374 public void osParcelJoin(LSL_Vector pos1, LSL_Vector pos2)
1375 {
1376 CheckThreatLevel(ThreatLevel.High, "osParcelJoin");
1377 m_host.AddScriptLPS(1);
1378  
1379 int startx = (int)(pos1.x < pos2.x ? pos1.x : pos2.x);
1380 int starty = (int)(pos1.y < pos2.y ? pos1.y : pos2.y);
1381 int endx = (int)(pos1.x > pos2.x ? pos1.x : pos2.x);
1382 int endy = (int)(pos1.y > pos2.y ? pos1.y : pos2.y);
1383  
1384 World.LandChannel.Join(startx,starty,endx,endy,m_host.OwnerID);
1385 }
1386  
1387 public void osParcelSubdivide(LSL_Vector pos1, LSL_Vector pos2)
1388 {
1389 CheckThreatLevel(ThreatLevel.High, "osParcelSubdivide");
1390 m_host.AddScriptLPS(1);
1391  
1392 int startx = (int)(pos1.x < pos2.x ? pos1.x : pos2.x);
1393 int starty = (int)(pos1.y < pos2.y ? pos1.y : pos2.y);
1394 int endx = (int)(pos1.x > pos2.x ? pos1.x : pos2.x);
1395 int endy = (int)(pos1.y > pos2.y ? pos1.y : pos2.y);
1396  
1397 World.LandChannel.Subdivide(startx,starty,endx,endy,m_host.OwnerID);
1398 }
1399  
1400 public void osParcelSetDetails(LSL_Vector pos, LSL_List rules)
1401 {
1402 const string functionName = "osParcelSetDetails";
1403 CheckThreatLevel(ThreatLevel.High, functionName);
1404 OSSLDeprecated(functionName, "osSetParcelDetails");
1405 SetParcelDetails(pos, rules, functionName);
1406 }
1407  
1408 public void osSetParcelDetails(LSL_Vector pos, LSL_List rules)
1409 {
1410 const string functionName = "osSetParcelDetails";
1411 CheckThreatLevel(ThreatLevel.High, functionName);
1412 SetParcelDetails(pos, rules, functionName);
1413 }
1414  
1415 private void SetParcelDetails(LSL_Vector pos, LSL_List rules, string functionName)
1416 {
1417 m_host.AddScriptLPS(1);
1418  
1419 // Get a reference to the land data and make sure the owner of the script
1420 // can modify it
1421  
1422 ILandObject startLandObject = World.LandChannel.GetLandObject((int)pos.x, (int)pos.y);
1423 if (startLandObject == null)
1424 {
1425 OSSLShoutError("There is no land at that location");
1426 return;
1427 }
1428  
1429 if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, startLandObject, GroupPowers.LandOptions))
1430 {
1431 OSSLShoutError("You do not have permission to modify the parcel");
1432 return;
1433 }
1434  
1435 // Create a new land data object we can modify
1436 LandData newLand = startLandObject.LandData.Copy();
1437 UUID uuid;
1438  
1439 // Process the rules, not sure what the impact would be of changing owner or group
1440 for (int idx = 0; idx < rules.Length;)
1441 {
1442 int code = rules.GetLSLIntegerItem(idx++);
1443 string arg = rules.GetLSLStringItem(idx++);
1444 switch (code)
1445 {
1446 case ScriptBaseClass.PARCEL_DETAILS_NAME:
1447 newLand.Name = arg;
1448 break;
1449  
1450 case ScriptBaseClass.PARCEL_DETAILS_DESC:
1451 newLand.Description = arg;
1452 break;
1453  
1454 case ScriptBaseClass.PARCEL_DETAILS_OWNER:
1455 CheckThreatLevel(ThreatLevel.VeryHigh, functionName);
1456 if (UUID.TryParse(arg, out uuid))
1457 newLand.OwnerID = uuid;
1458 break;
1459  
1460 case ScriptBaseClass.PARCEL_DETAILS_GROUP:
1461 CheckThreatLevel(ThreatLevel.VeryHigh, functionName);
1462 if (UUID.TryParse(arg, out uuid))
1463 newLand.GroupID = uuid;
1464 break;
1465  
1466 case ScriptBaseClass.PARCEL_DETAILS_CLAIMDATE:
1467 CheckThreatLevel(ThreatLevel.VeryHigh, functionName);
1468 newLand.ClaimDate = Convert.ToInt32(arg);
1469 if (newLand.ClaimDate == 0)
1470 newLand.ClaimDate = Util.UnixTimeSinceEpoch();
1471 break;
1472 }
1473 }
1474  
1475 World.LandChannel.UpdateLandObject(newLand.LocalID,newLand);
1476 }
1477  
1478 public double osList2Double(LSL_Types.list src, int index)
1479 {
1480 // There is really no double type in OSSL. C# and other
1481 // have one, but the current implementation of LSL_Types.list
1482 // is not allowed to contain any.
1483 // This really should be removed.
1484 //
1485 CheckThreatLevel(ThreatLevel.None, "osList2Double");
1486  
1487 m_host.AddScriptLPS(1);
1488 if (index < 0)
1489 {
1490 index = src.Length + index;
1491 }
1492 if (index >= src.Length)
1493 {
1494 return 0.0;
1495 }
1496 return Convert.ToDouble(src.Data[index]);
1497 }
1498  
1499 public void osSetParcelMediaURL(string url)
1500 {
1501 // What actually is the difference to the LL function?
1502 //
1503 CheckThreatLevel(ThreatLevel.VeryLow, "osSetParcelMediaURL");
1504  
1505 m_host.AddScriptLPS(1);
1506  
1507 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
1508  
1509 if (land.LandData.OwnerID != m_host.OwnerID)
1510 return;
1511  
1512 land.SetMediaUrl(url);
1513 }
1514  
1515 public void osSetParcelSIPAddress(string SIPAddress)
1516 {
1517 // What actually is the difference to the LL function?
1518 //
1519 CheckThreatLevel(ThreatLevel.VeryLow, "osSetParcelSIPAddress");
1520  
1521 m_host.AddScriptLPS(1);
1522  
1523 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
1524  
1525 if (land.LandData.OwnerID != m_host.OwnerID)
1526 {
1527 OSSLError("osSetParcelSIPAddress: Sorry, you need to own the land to use this function");
1528 return;
1529 }
1530  
1531 // get the voice module
1532 IVoiceModule voiceModule = World.RequestModuleInterface<IVoiceModule>();
1533  
1534 if (voiceModule != null)
1535 voiceModule.setLandSIPAddress(SIPAddress,land.LandData.GlobalID);
1536 else
1537 OSSLError("osSetParcelSIPAddress: No voice module enabled for this land");
1538 }
1539  
1540 public string osGetScriptEngineName()
1541 {
1542 // This gets a "high" because knowing the engine may be used
1543 // to exploit engine-specific bugs or induce usage patterns
1544 // that trigger engine-specific failures.
1545 // Besides, public grid users aren't supposed to know.
1546 //
1547 CheckThreatLevel(ThreatLevel.High, "osGetScriptEngineName");
1548  
1549 m_host.AddScriptLPS(1);
1550  
1551 int scriptEngineNameIndex = 0;
1552  
1553 if (!String.IsNullOrEmpty(m_ScriptEngine.ScriptEngineName))
1554 {
1555 // parse off the "ScriptEngine."
1556 scriptEngineNameIndex = m_ScriptEngine.ScriptEngineName.IndexOf(".", scriptEngineNameIndex);
1557 scriptEngineNameIndex++; // get past delimiter
1558  
1559 int scriptEngineNameLength = m_ScriptEngine.ScriptEngineName.Length - scriptEngineNameIndex;
1560  
1561 // create char array then a string that is only the script engine name
1562 Char[] scriptEngineNameCharArray = m_ScriptEngine.ScriptEngineName.ToCharArray(scriptEngineNameIndex, scriptEngineNameLength);
1563 String scriptEngineName = new String(scriptEngineNameCharArray);
1564  
1565 return scriptEngineName;
1566 }
1567 else
1568 {
1569 return String.Empty;
1570 }
1571 }
1572  
1573 public string osGetPhysicsEngineType()
1574 {
1575 // High because it can be used to target attacks to known weaknesses
1576 // This would allow a new class of griefer scripts that don't even
1577 // require their user to know what they are doing (see script
1578 // kiddie)
1579 // Because it would be nice if scripts didn't blow up if the information
1580 // about the physics engine, this function returns an empty string if
1581 // the user does not have permission to see it. This as opposed to
1582 // throwing an exception.
1583 m_host.AddScriptLPS(1);
1584 string ret = String.Empty;
1585 if (String.IsNullOrEmpty(CheckThreatLevelTest(ThreatLevel.High, "osGetPhysicsEngineType")))
1586 {
1587 if (m_ScriptEngine.World.PhysicsScene != null)
1588 {
1589 ret = m_ScriptEngine.World.PhysicsScene.EngineType;
1590 // An old physics engine might have an uninitialized engine type
1591 if (ret == null)
1592 ret = "unknown";
1593 }
1594 }
1595  
1596 return ret;
1597 }
1598  
1599 public string osGetSimulatorVersion()
1600 {
1601 // High because it can be used to target attacks to known weaknesses
1602 // This would allow a new class of griefer scripts that don't even
1603 // require their user to know what they are doing (see script
1604 // kiddie)
1605 //
1606 CheckThreatLevel(ThreatLevel.High,"osGetSimulatorVersion");
1607 m_host.AddScriptLPS(1);
1608  
1609 return m_ScriptEngine.World.GetSimulatorVersion();
1610 }
1611  
1612 private Hashtable osdToHashtable(OSDMap map)
1613 {
1614 Hashtable result = new Hashtable();
1615 foreach (KeyValuePair<string, OSD> item in map) {
1616 result.Add(item.Key, osdToObject(item.Value));
1617 }
1618 return result;
1619 }
1620  
1621 private ArrayList osdToArray(OSDArray list)
1622 {
1623 ArrayList result = new ArrayList();
1624 foreach ( OSD item in list ) {
1625 result.Add(osdToObject(item));
1626 }
1627 return result;
1628 }
1629  
1630 private Object osdToObject(OSD decoded)
1631 {
1632 if ( decoded is OSDString ) {
1633 return (string) decoded.AsString();
1634 } else if ( decoded is OSDInteger ) {
1635 return (int) decoded.AsInteger();
1636 } else if ( decoded is OSDReal ) {
1637 return (float) decoded.AsReal();
1638 } else if ( decoded is OSDBoolean ) {
1639 return (bool) decoded.AsBoolean();
1640 } else if ( decoded is OSDMap ) {
1641 return osdToHashtable((OSDMap) decoded);
1642 } else if ( decoded is OSDArray ) {
1643 return osdToArray((OSDArray) decoded);
1644 } else {
1645 return null;
1646 }
1647 }
1648  
1649 public Object osParseJSONNew(string JSON)
1650 {
1651 CheckThreatLevel(ThreatLevel.None, "osParseJSONNew");
1652  
1653 m_host.AddScriptLPS(1);
1654  
1655 try
1656 {
1657 OSD decoded = OSDParser.DeserializeJson(JSON);
1658 return osdToObject(decoded);
1659 }
1660 catch(Exception e)
1661 {
1662 OSSLError("osParseJSONNew: Problems decoding JSON string " + JSON + " : " + e.Message) ;
1663 return null;
1664 }
1665 }
1666  
1667 public Hashtable osParseJSON(string JSON)
1668 {
1669 CheckThreatLevel(ThreatLevel.None, "osParseJSON");
1670  
1671 m_host.AddScriptLPS(1);
1672  
1673 Object decoded = osParseJSONNew(JSON);
1674  
1675 if ( decoded is Hashtable ) {
1676 return (Hashtable) decoded;
1677 } else if ( decoded is ArrayList ) {
1678 ArrayList decoded_list = (ArrayList) decoded;
1679 Hashtable fakearray = new Hashtable();
1680 int i = 0;
1681 for ( i = 0; i < decoded_list.Count ; i++ ) {
1682 fakearray.Add(i, decoded_list[i]);
1683 }
1684 return fakearray;
1685 } else {
1686 OSSLError("osParseJSON: unable to parse JSON string " + JSON);
1687 return null;
1688 }
1689 }
1690  
1691 /// <summary>
1692 /// Send a message to to object identified by the given UUID
1693 /// </summary>
1694 /// <remarks>
1695 /// A script in the object must implement the dataserver function
1696 /// the dataserver function is passed the ID of the calling function and a string message
1697 /// </remarks>
1698 /// <param name="objectUUID"></param>
1699 /// <param name="message"></param>
1700 public void osMessageObject(LSL_Key objectUUID, string message)
1701 {
1702 CheckThreatLevel(ThreatLevel.Low, "osMessageObject");
1703 m_host.AddScriptLPS(1);
1704  
1705 UUID objUUID;
1706 if (!UUID.TryParse(objectUUID, out objUUID)) // prior to patching, a thrown exception regarding invalid GUID format would be shouted instead.
1707 {
1708 OSSLShoutError("osMessageObject() cannot send messages to objects with invalid UUIDs");
1709 return;
1710 }
1711  
1712 MessageObject(objUUID, message);
1713 }
1714  
1715 private void MessageObject(UUID objUUID, string message)
1716 {
1717 object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) };
1718  
1719 SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID);
1720  
1721 if (sceneOP == null) // prior to patching, PostObjectEvent() would cause a throw exception to be shouted instead.
1722 {
1723 OSSLShoutError("osMessageObject() cannot send message to " + objUUID.ToString() + ", object was not found in scene.");
1724 return;
1725 }
1726  
1727 m_ScriptEngine.PostObjectEvent(
1728 sceneOP.LocalId, new EventParams(
1729 "dataserver", resobj, new DetectParams[0]));
1730 }
1731  
1732 /// <summary>
1733 /// Write a notecard directly to the prim's inventory.
1734 /// </summary>
1735 /// <remarks>
1736 /// This needs ThreatLevel high. It is an excellent griefer tool,
1737 /// In a loop, it can cause asset bloat and DOS levels of asset
1738 /// writes.
1739 /// </remarks>
1740 /// <param name="notecardName">The name of the notecard to write.</param>
1741 /// <param name="contents">The contents of the notecard.</param>
1742 public void osMakeNotecard(string notecardName, LSL_Types.list contents)
1743 {
1744 CheckThreatLevel(ThreatLevel.High, "osMakeNotecard");
1745 m_host.AddScriptLPS(1);
1746  
1747 StringBuilder notecardData = new StringBuilder();
1748  
1749 for (int i = 0; i < contents.Length; i++)
1750 notecardData.Append((string)(contents.GetLSLStringItem(i) + "\n"));
1751  
1752 SaveNotecard(notecardName, "Script generated notecard", notecardData.ToString(), false);
1753 }
1754  
1755 /// <summary>
1756 /// Save a notecard to prim inventory.
1757 /// </summary>
1758 /// <param name="name"></param>
1759 /// <param name="description">Description of notecard</param>
1760 /// <param name="notecardData"></param>
1761 /// <param name="forceSameName">
1762 /// If true, then if an item exists with the same name, it is replaced.
1763 /// If false, then a new item is created witha slightly different name (e.g. name 1)
1764 /// </param>
1765 /// <returns>Prim inventory item created.</returns>
1766 protected TaskInventoryItem SaveNotecard(string name, string description, string data, bool forceSameName)
1767 {
1768 // Create new asset
1769 AssetBase asset = new AssetBase(UUID.Random(), name, (sbyte)AssetType.Notecard, m_host.OwnerID.ToString());
1770 asset.Description = description;
1771  
1772 int textLength = data.Length;
1773 data
1774 = "Linden text version 2\n{\nLLEmbeddedItems version 1\n{\ncount 0\n}\nText length "
1775 + textLength.ToString() + "\n" + data + "}\n";
1776  
1777 asset.Data = Util.UTF8.GetBytes(data);
1778 World.AssetService.Store(asset);
1779  
1780 // Create Task Entry
1781 TaskInventoryItem taskItem = new TaskInventoryItem();
1782  
1783 taskItem.ResetIDs(m_host.UUID);
1784 taskItem.ParentID = m_host.UUID;
1785 taskItem.CreationDate = (uint)Util.UnixTimeSinceEpoch();
1786 taskItem.Name = asset.Name;
1787 taskItem.Description = asset.Description;
1788 taskItem.Type = (int)AssetType.Notecard;
1789 taskItem.InvType = (int)InventoryType.Notecard;
1790 taskItem.OwnerID = m_host.OwnerID;
1791 taskItem.CreatorID = m_host.OwnerID;
1792 taskItem.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1793 taskItem.CurrentPermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1794 taskItem.EveryonePermissions = 0;
1795 taskItem.NextPermissions = (uint)PermissionMask.All;
1796 taskItem.GroupID = m_host.GroupID;
1797 taskItem.GroupPermissions = 0;
1798 taskItem.Flags = 0;
1799 taskItem.PermsGranter = UUID.Zero;
1800 taskItem.PermsMask = 0;
1801 taskItem.AssetID = asset.FullID;
1802  
1803 if (forceSameName)
1804 m_host.Inventory.AddInventoryItemExclusive(taskItem, false);
1805 else
1806 m_host.Inventory.AddInventoryItem(taskItem, false);
1807  
1808 return taskItem;
1809 }
1810  
1811 /// <summary>
1812 /// Load the notecard data found at the given prim inventory item name or asset uuid.
1813 /// </summary>
1814 /// <param name="notecardNameOrUuid"></param>
1815 /// <returns>The text loaded. Null if no notecard was found.</returns>
1816 protected string LoadNotecard(string notecardNameOrUuid)
1817 {
1818 UUID assetID = CacheNotecard(notecardNameOrUuid);
1819  
1820 if (assetID != UUID.Zero)
1821 {
1822 StringBuilder notecardData = new StringBuilder();
1823  
1824 for (int count = 0; count < NotecardCache.GetLines(assetID); count++)
1825 {
1826 string line = NotecardCache.GetLine(assetID, count) + "\n";
1827  
1828 // m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line);
1829  
1830 notecardData.Append(line);
1831 }
1832  
1833 return notecardData.ToString();
1834 }
1835  
1836 return null;
1837 }
1838  
1839 /// <summary>
1840 /// Cache a notecard's contents.
1841 /// </summary>
1842 /// <param name="notecardNameOrUuid"></param>
1843 /// <returns>
1844 /// The asset id of the notecard, which is used for retrieving the cached data.
1845 /// UUID.Zero if no asset could be found.
1846 /// </returns>
1847 protected UUID CacheNotecard(string notecardNameOrUuid)
1848 {
1849 UUID assetID = UUID.Zero;
1850  
1851 if (!UUID.TryParse(notecardNameOrUuid, out assetID))
1852 {
1853 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1854 {
1855 if (item.Type == 7 && item.Name == notecardNameOrUuid)
1856 {
1857 assetID = item.AssetID;
1858 }
1859 }
1860 }
1861  
1862 if (assetID == UUID.Zero)
1863 return UUID.Zero;
1864  
1865 if (!NotecardCache.IsCached(assetID))
1866 {
1867 AssetBase a = World.AssetService.Get(assetID.ToString());
1868  
1869 if (a == null)
1870 return UUID.Zero;
1871  
1872 string data = Encoding.UTF8.GetString(a.Data);
1873 NotecardCache.Cache(assetID, data);
1874 };
1875  
1876 return assetID;
1877 }
1878  
1879 /// <summary>
1880 /// Directly get an entire notecard at once.
1881 /// </summary>
1882 /// <remarks>
1883 /// Instead of using the LSL Dataserver event to pull notecard data
1884 /// this will simply read the entire notecard and return its data as a string.
1885 ///
1886 /// Warning - due to the synchronous method this function uses to fetch assets, its use
1887 /// may be dangerous and unreliable while running in grid mode.
1888 /// </remarks>
1889 /// <param name="name">Name of the notecard or its asset id</param>
1890 /// <param name="line">The line number to read. The first line is line 0</param>
1891 /// <returns>Notecard line</returns>
1892 public string osGetNotecardLine(string name, int line)
1893 {
1894 CheckThreatLevel(ThreatLevel.VeryHigh, "osGetNotecardLine");
1895 m_host.AddScriptLPS(1);
1896  
1897 UUID assetID = CacheNotecard(name);
1898  
1899 if (assetID == UUID.Zero)
1900 {
1901 OSSLShoutError("Notecard '" + name + "' could not be found.");
1902 return "ERROR!";
1903 }
1904  
1905 return NotecardCache.GetLine(assetID, line);
1906 }
1907  
1908 /// <summary>
1909 /// Get an entire notecard at once.
1910 /// </summary>
1911 /// <remarks>
1912 /// Instead of using the LSL Dataserver event to pull notecard data line by line,
1913 /// this will simply read the entire notecard and return its data as a string.
1914 ///
1915 /// Warning - due to the synchronous method this function uses to fetch assets, its use
1916 /// may be dangerous and unreliable while running in grid mode.
1917 /// </remarks>
1918 /// <param name="name">Name of the notecard or its asset id</param>
1919 /// <returns>Notecard text</returns>
1920 public string osGetNotecard(string name)
1921 {
1922 CheckThreatLevel(ThreatLevel.VeryHigh, "osGetNotecard");
1923 m_host.AddScriptLPS(1);
1924  
1925 string text = LoadNotecard(name);
1926  
1927 if (text == null)
1928 {
1929 OSSLShoutError("Notecard '" + name + "' could not be found.");
1930 return "ERROR!";
1931 }
1932 else
1933 {
1934 return text;
1935 }
1936 }
1937  
1938 /// <summary>
1939 /// Get the number of lines in the given notecard.
1940 /// </summary>
1941 /// <remarks>
1942 /// Instead of using the LSL Dataserver event to pull notecard data,
1943 /// this will simply read the number of note card lines and return this data as an integer.
1944 ///
1945 /// Warning - due to the synchronous method this function uses to fetch assets, its use
1946 /// may be dangerous and unreliable while running in grid mode.
1947 /// </remarks>
1948 /// <param name="name">Name of the notecard or its asset id</param>
1949 /// <returns></returns>
1950 public int osGetNumberOfNotecardLines(string name)
1951 {
1952 CheckThreatLevel(ThreatLevel.VeryHigh, "osGetNumberOfNotecardLines");
1953 m_host.AddScriptLPS(1);
1954  
1955 UUID assetID = CacheNotecard(name);
1956  
1957 if (assetID == UUID.Zero)
1958 {
1959 OSSLShoutError("Notecard '" + name + "' could not be found.");
1960 return -1;
1961 }
1962  
1963 return NotecardCache.GetLines(assetID);
1964 }
1965  
1966 public string osAvatarName2Key(string firstname, string lastname)
1967 {
1968 CheckThreatLevel(ThreatLevel.Low, "osAvatarName2Key");
1969 m_host.AddScriptLPS(1);
1970  
1971 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, firstname, lastname);
1972 if (null == account)
1973 {
1974 return UUID.Zero.ToString();
1975 }
1976 else
1977 {
1978 return account.PrincipalID.ToString();
1979 }
1980 }
1981  
1982 public string osKey2Name(string id)
1983 {
1984 CheckThreatLevel(ThreatLevel.Low, "osKey2Name");
1985 m_host.AddScriptLPS(1);
1986  
1987 UUID key = new UUID();
1988  
1989 if (UUID.TryParse(id, out key))
1990 {
1991 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, key);
1992 if (null == account)
1993 {
1994 return "";
1995 }
1996 else
1997 {
1998 return account.Name;
1999 }
2000 }
2001 else
2002 {
2003 return "";
2004 }
2005 }
2006  
2007 private enum InfoType
2008 {
2009 Nick,
2010 Name,
2011 Login,
2012 Home,
2013 Custom
2014 };
2015  
2016 private string GridUserInfo(InfoType type)
2017 {
2018 return GridUserInfo(type, "");
2019 }
2020  
2021 private string GridUserInfo(InfoType type, string key)
2022 {
2023 string retval = String.Empty;
2024 IConfigSource config = m_ScriptEngine.ConfigSource;
2025 string url = null;
2026  
2027 IConfig gridInfoConfig = config.Configs["GridInfo"];
2028  
2029 if (gridInfoConfig != null)
2030 url = gridInfoConfig.GetString("GridInfoURI", String.Empty);
2031  
2032 if (String.IsNullOrEmpty(url))
2033 return "Configuration Error!";
2034  
2035 string verb ="/json_grid_info";
2036 OSDMap json = new OSDMap();
2037  
2038 OSDMap info = WebUtil.GetFromService(String.Format("{0}{1}",url,verb), 3000);
2039  
2040 if (info["Success"] != true)
2041 return "Get GridInfo Failed!";
2042  
2043 json = (OSDMap)OSDParser.DeserializeJson(info["_RawResult"].AsString());
2044  
2045 switch (type)
2046 {
2047 case InfoType.Nick:
2048 retval = json["gridnick"];
2049 break;
2050  
2051 case InfoType.Name:
2052 retval = json["gridname"];
2053 break;
2054  
2055 case InfoType.Login:
2056 retval = json["login"];
2057 break;
2058  
2059 case InfoType.Home:
2060 retval = json["home"];
2061 break;
2062  
2063 case InfoType.Custom:
2064 retval = json[key];
2065 break;
2066  
2067 default:
2068 retval = "error";
2069 break;
2070 }
2071  
2072 return retval;
2073 }
2074  
2075 /// <summary>
2076 /// Get the nickname of this grid, as set in the [GridInfo] config section.
2077 /// </summary>
2078 /// <remarks>
2079 /// Threat level is Moderate because intentional abuse, for instance
2080 /// scripts that are written to be malicious only on one grid,
2081 /// for instance in a HG scenario, are a distinct possibility.
2082 /// </remarks>
2083 /// <returns></returns>
2084 public string osGetGridNick()
2085 {
2086 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridNick");
2087 m_host.AddScriptLPS(1);
2088  
2089 string nick = String.Empty;
2090 IConfigSource config = m_ScriptEngine.ConfigSource;
2091  
2092 if (config.Configs[GridInfoServiceConfigSectionName] != null)
2093 nick = config.Configs[GridInfoServiceConfigSectionName].GetString("gridnick", nick);
2094  
2095 if (String.IsNullOrEmpty(nick))
2096 nick = GridUserInfo(InfoType.Nick);
2097  
2098 return nick;
2099 }
2100  
2101 public string osGetGridName()
2102 {
2103 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridName");
2104 m_host.AddScriptLPS(1);
2105  
2106 string name = String.Empty;
2107 IConfigSource config = m_ScriptEngine.ConfigSource;
2108  
2109 if (config.Configs[GridInfoServiceConfigSectionName] != null)
2110 name = config.Configs[GridInfoServiceConfigSectionName].GetString("gridname", name);
2111  
2112 if (String.IsNullOrEmpty(name))
2113 name = GridUserInfo(InfoType.Name);
2114  
2115 return name;
2116 }
2117  
2118 public string osGetGridLoginURI()
2119 {
2120 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridLoginURI");
2121 m_host.AddScriptLPS(1);
2122  
2123 string loginURI = String.Empty;
2124 IConfigSource config = m_ScriptEngine.ConfigSource;
2125  
2126 if (config.Configs[GridInfoServiceConfigSectionName] != null)
2127 loginURI = config.Configs[GridInfoServiceConfigSectionName].GetString("login", loginURI);
2128  
2129 if (String.IsNullOrEmpty(loginURI))
2130 loginURI = GridUserInfo(InfoType.Login);
2131  
2132 return loginURI;
2133 }
2134  
2135 public string osGetGridHomeURI()
2136 {
2137 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridHomeURI");
2138 m_host.AddScriptLPS(1);
2139  
2140 IConfigSource config = m_ScriptEngine.ConfigSource;
2141 string HomeURI = Util.GetConfigVarFromSections<string>(config, "HomeURI",
2142 new string[] { "Startup", "Hypergrid" }, String.Empty);
2143  
2144 if (!string.IsNullOrEmpty(HomeURI))
2145 return HomeURI;
2146  
2147 // Legacy. Remove soon!
2148 if (config.Configs["LoginService"] != null)
2149 HomeURI = config.Configs["LoginService"].GetString("SRV_HomeURI", HomeURI);
2150  
2151 if (String.IsNullOrEmpty(HomeURI))
2152 HomeURI = GridUserInfo(InfoType.Home);
2153  
2154 return HomeURI;
2155 }
2156  
2157 public string osGetGridGatekeeperURI()
2158 {
2159 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridGatekeeperURI");
2160 m_host.AddScriptLPS(1);
2161  
2162 IConfigSource config = m_ScriptEngine.ConfigSource;
2163 string gatekeeperURI = Util.GetConfigVarFromSections<string>(config, "GatekeeperURI",
2164 new string[] { "Startup", "Hypergrid" }, String.Empty);
2165  
2166 if (!string.IsNullOrEmpty(gatekeeperURI))
2167 return gatekeeperURI;
2168  
2169 // Legacy. Remove soon!
2170 if (config.Configs["GridService"] != null)
2171 gatekeeperURI = config.Configs["GridService"].GetString("Gatekeeper", gatekeeperURI);
2172  
2173 return gatekeeperURI;
2174 }
2175  
2176 public string osGetGridCustom(string key)
2177 {
2178 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridCustom");
2179 m_host.AddScriptLPS(1);
2180  
2181 string retval = String.Empty;
2182 IConfigSource config = m_ScriptEngine.ConfigSource;
2183  
2184 if (config.Configs[GridInfoServiceConfigSectionName] != null)
2185 retval = config.Configs[GridInfoServiceConfigSectionName].GetString(key, retval);
2186  
2187 if (String.IsNullOrEmpty(retval))
2188 retval = GridUserInfo(InfoType.Custom, key);
2189  
2190 return retval;
2191 }
2192  
2193 public LSL_String osFormatString(string str, LSL_List strings)
2194 {
2195 CheckThreatLevel(ThreatLevel.VeryLow, "osFormatString");
2196 m_host.AddScriptLPS(1);
2197  
2198 return String.Format(str, strings.Data);
2199 }
2200  
2201 public LSL_List osMatchString(string src, string pattern, int start)
2202 {
2203 CheckThreatLevel(ThreatLevel.VeryLow, "osMatchString");
2204 m_host.AddScriptLPS(1);
2205  
2206 LSL_List result = new LSL_List();
2207  
2208 // Normalize indices (if negative).
2209 // After normlaization they may still be
2210 // negative, but that is now relative to
2211 // the start, rather than the end, of the
2212 // sequence.
2213 if (start < 0)
2214 {
2215 start = src.Length + start;
2216 }
2217  
2218 if (start < 0 || start >= src.Length)
2219 {
2220 return result; // empty list
2221 }
2222  
2223 // Find matches beginning at start position
2224 Regex matcher = new Regex(pattern);
2225 Match match = matcher.Match(src, start);
2226 while (match.Success)
2227 {
2228 foreach (System.Text.RegularExpressions.Group g in match.Groups)
2229 {
2230 if (g.Success)
2231 {
2232 result.Add(new LSL_String(g.Value));
2233 result.Add(new LSL_Integer(g.Index));
2234 }
2235 }
2236  
2237 match = match.NextMatch();
2238 }
2239  
2240 return result;
2241 }
2242  
2243 public LSL_String osReplaceString(string src, string pattern, string replace, int count, int start)
2244 {
2245 CheckThreatLevel(ThreatLevel.VeryLow, "osReplaceString");
2246 m_host.AddScriptLPS(1);
2247  
2248 // Normalize indices (if negative).
2249 // After normlaization they may still be
2250 // negative, but that is now relative to
2251 // the start, rather than the end, of the
2252 // sequence.
2253 if (start < 0)
2254 {
2255 start = src.Length + start;
2256 }
2257  
2258 if (start < 0 || start >= src.Length)
2259 {
2260 return src;
2261 }
2262  
2263 // Find matches beginning at start position
2264 Regex matcher = new Regex(pattern);
2265 return matcher.Replace(src,replace,count,start);
2266 }
2267  
2268 public string osLoadedCreationDate()
2269 {
2270 CheckThreatLevel(ThreatLevel.Low, "osLoadedCreationDate");
2271 m_host.AddScriptLPS(1);
2272  
2273 return World.RegionInfo.RegionSettings.LoadedCreationDate;
2274 }
2275  
2276 public string osLoadedCreationTime()
2277 {
2278 CheckThreatLevel(ThreatLevel.Low, "osLoadedCreationTime");
2279 m_host.AddScriptLPS(1);
2280  
2281 return World.RegionInfo.RegionSettings.LoadedCreationTime;
2282 }
2283  
2284 public string osLoadedCreationID()
2285 {
2286 CheckThreatLevel(ThreatLevel.Low, "osLoadedCreationID");
2287 m_host.AddScriptLPS(1);
2288  
2289 return World.RegionInfo.RegionSettings.LoadedCreationID;
2290 }
2291  
2292 /// <summary>
2293 /// Get the primitive parameters of a linked prim.
2294 /// </summary>
2295 /// <remarks>
2296 /// Threat level is 'Low' because certain users could possibly be tricked into
2297 /// dropping an unverified script into one of their own objects, which could
2298 /// then gather the physical construction details of the object and transmit it
2299 /// to an unscrupulous third party, thus permitting unauthorized duplication of
2300 /// the object's form.
2301 /// </remarks>
2302 /// <param name="linknumber"></param>
2303 /// <param name="rules"></param>
2304 /// <returns></returns>
2305 public LSL_List osGetLinkPrimitiveParams(int linknumber, LSL_List rules)
2306 {
2307 CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams");
2308 m_host.AddScriptLPS(1);
2309 InitLSL();
2310 // One needs to cast m_LSL_Api because we're using functions not
2311 // on the ILSL_Api interface.
2312 LSL_Api LSL_Api = (LSL_Api)m_LSL_Api;
2313 LSL_List retVal = new LSL_List();
2314 LSL_List remaining = null;
2315 List<SceneObjectPart> parts = LSL_Api.GetLinkParts(linknumber);
2316 foreach (SceneObjectPart part in parts)
2317 {
2318 remaining = LSL_Api.GetPrimParams(part, rules, ref retVal);
2319 }
2320  
2321 while (remaining != null && remaining.Length > 2)
2322 {
2323 linknumber = remaining.GetLSLIntegerItem(0);
2324 rules = remaining.GetSublist(1, -1);
2325 parts = LSL_Api.GetLinkParts(linknumber);
2326  
2327 foreach (SceneObjectPart part in parts)
2328 remaining = LSL_Api.GetPrimParams(part, rules, ref retVal);
2329 }
2330 return retVal;
2331 }
2332  
2333 public void osForceCreateLink(string target, int parent)
2334 {
2335 CheckThreatLevel(ThreatLevel.VeryLow, "osForceCreateLink");
2336  
2337 m_host.AddScriptLPS(1);
2338  
2339 InitLSL();
2340 ((LSL_Api)m_LSL_Api).CreateLink(target, parent);
2341 }
2342  
2343 public void osForceBreakLink(int linknum)
2344 {
2345 CheckThreatLevel(ThreatLevel.VeryLow, "osForceBreakLink");
2346  
2347 m_host.AddScriptLPS(1);
2348  
2349 InitLSL();
2350 ((LSL_Api)m_LSL_Api).BreakLink(linknum);
2351 }
2352  
2353 public void osForceBreakAllLinks()
2354 {
2355 CheckThreatLevel(ThreatLevel.VeryLow, "osForceBreakAllLinks");
2356  
2357 m_host.AddScriptLPS(1);
2358  
2359 InitLSL();
2360 ((LSL_Api)m_LSL_Api).BreakAllLinks();
2361 }
2362  
2363 public LSL_Integer osIsNpc(LSL_Key npc)
2364 {
2365 CheckThreatLevel(ThreatLevel.None, "osIsNpc");
2366 m_host.AddScriptLPS(1);
2367  
2368 INPCModule module = World.RequestModuleInterface<INPCModule>();
2369 if (module != null)
2370 {
2371 UUID npcId;
2372 if (UUID.TryParse(npc.m_string, out npcId))
2373 if (module.IsNPC(npcId, World))
2374 return ScriptBaseClass.TRUE;
2375 }
2376  
2377 return ScriptBaseClass.FALSE;
2378 }
2379  
2380 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard)
2381 {
2382 CheckThreatLevel(ThreatLevel.High, "osNpcCreate");
2383 m_host.AddScriptLPS(1);
2384  
2385 return NpcCreate(firstname, lastname, position, notecard, false, false);
2386 }
2387  
2388 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options)
2389 {
2390 CheckThreatLevel(ThreatLevel.High, "osNpcCreate");
2391 m_host.AddScriptLPS(1);
2392  
2393 return NpcCreate(
2394 firstname, lastname, position, notecard,
2395 (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0,
2396 (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) != 0);
2397 }
2398  
2399 private LSL_Key NpcCreate(
2400 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent)
2401 {
2402 INPCModule module = World.RequestModuleInterface<INPCModule>();
2403 if (module != null)
2404 {
2405 AvatarAppearance appearance = null;
2406  
2407 UUID id;
2408 if (UUID.TryParse(notecard, out id))
2409 {
2410 ScenePresence clonePresence = World.GetScenePresence(id);
2411 if (clonePresence != null)
2412 appearance = clonePresence.Appearance;
2413 }
2414  
2415 if (appearance == null)
2416 {
2417 string appearanceSerialized = LoadNotecard(notecard);
2418  
2419 if (appearanceSerialized != null)
2420 {
2421 OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized);
2422 appearance = new AvatarAppearance();
2423 appearance.Unpack(appearanceOsd);
2424 }
2425 else
2426 {
2427 OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard));
2428 }
2429 }
2430  
2431 UUID ownerID = UUID.Zero;
2432 if (owned)
2433 ownerID = m_host.OwnerID;
2434 UUID x = module.CreateNPC(firstname,
2435 lastname,
2436 position,
2437 ownerID,
2438 senseAsAgent,
2439 World,
2440 appearance);
2441  
2442 return new LSL_Key(x.ToString());
2443 }
2444  
2445 return new LSL_Key(UUID.Zero.ToString());
2446 }
2447  
2448 /// <summary>
2449 /// Save the current appearance of the NPC permanently to the named notecard.
2450 /// </summary>
2451 /// <param name="avatar"></param>
2452 /// <param name="notecard">The name of the notecard to which to save the appearance.</param>
2453 /// <returns>The asset ID of the notecard saved.</returns>
2454 public LSL_Key osNpcSaveAppearance(LSL_Key npc, string notecard)
2455 {
2456 CheckThreatLevel(ThreatLevel.High, "osNpcSaveAppearance");
2457 m_host.AddScriptLPS(1);
2458  
2459 INPCModule npcModule = World.RequestModuleInterface<INPCModule>();
2460  
2461 if (npcModule != null)
2462 {
2463 UUID npcId;
2464 if (!UUID.TryParse(npc.m_string, out npcId))
2465 return new LSL_Key(UUID.Zero.ToString());
2466  
2467 if (!npcModule.CheckPermissions(npcId, m_host.OwnerID))
2468 return new LSL_Key(UUID.Zero.ToString());
2469  
2470 return SaveAppearanceToNotecard(npcId, notecard);
2471 }
2472  
2473 return new LSL_Key(UUID.Zero.ToString());
2474 }
2475  
2476 public void osNpcLoadAppearance(LSL_Key npc, string notecard)
2477 {
2478 CheckThreatLevel(ThreatLevel.High, "osNpcLoadAppearance");
2479 m_host.AddScriptLPS(1);
2480  
2481 INPCModule npcModule = World.RequestModuleInterface<INPCModule>();
2482  
2483 if (npcModule != null)
2484 {
2485 UUID npcId;
2486 if (!UUID.TryParse(npc.m_string, out npcId))
2487 return;
2488  
2489 if (!npcModule.CheckPermissions(npcId, m_host.OwnerID))
2490 return;
2491  
2492 string appearanceSerialized = LoadNotecard(notecard);
2493  
2494 if (appearanceSerialized == null)
2495 OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard));
2496  
2497 OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized);
2498 // OSD a = OSDParser.DeserializeLLSDXml(appearanceSerialized);
2499 // Console.WriteLine("appearanceSerialized {0}", appearanceSerialized);
2500 // Console.WriteLine("a.Type {0}, a.ToString() {1}", a.Type, a);
2501 AvatarAppearance appearance = new AvatarAppearance();
2502 appearance.Unpack(appearanceOsd);
2503  
2504 npcModule.SetNPCAppearance(npcId, appearance, m_host.ParentGroup.Scene);
2505 }
2506 }
2507  
2508 public LSL_Key osNpcGetOwner(LSL_Key npc)
2509 {
2510 CheckThreatLevel(ThreatLevel.None, "osNpcGetOwner");
2511 m_host.AddScriptLPS(1);
2512  
2513 INPCModule npcModule = World.RequestModuleInterface<INPCModule>();
2514 if (npcModule != null)
2515 {
2516 UUID npcId;
2517 if (UUID.TryParse(npc.m_string, out npcId))
2518 {
2519 UUID owner = npcModule.GetOwner(npcId);
2520 if (owner != UUID.Zero)
2521 return new LSL_Key(owner.ToString());
2522 else
2523 return npc;
2524 }
2525 }
2526  
2527 return new LSL_Key(UUID.Zero.ToString());
2528 }
2529  
2530 public LSL_Vector osNpcGetPos(LSL_Key npc)
2531 {
2532 CheckThreatLevel(ThreatLevel.High, "osNpcGetPos");
2533 m_host.AddScriptLPS(1);
2534  
2535 INPCModule npcModule = World.RequestModuleInterface<INPCModule>();
2536 if (npcModule != null)
2537 {
2538 UUID npcId;
2539 if (!UUID.TryParse(npc.m_string, out npcId))
2540 return new LSL_Vector(0, 0, 0);
2541  
2542 if (!npcModule.CheckPermissions(npcId, m_host.OwnerID))
2543 return new LSL_Vector(0, 0, 0);
2544  
2545 ScenePresence sp = World.GetScenePresence(npcId);
2546  
2547 if (sp != null)
2548 return new LSL_Vector(sp.AbsolutePosition);
2549 }
2550  
2551 return Vector3.Zero;
2552 }
2553  
2554 public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos)
2555 {
2556 CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo");
2557 m_host.AddScriptLPS(1);
2558  
2559 INPCModule module = World.RequestModuleInterface<INPCModule>();
2560 if (module != null)
2561 {
2562 UUID npcId;
2563 if (!UUID.TryParse(npc.m_string, out npcId))
2564 return;
2565  
2566 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2567 return;
2568  
2569 module.MoveToTarget(npcId, World, pos, false, true, false);
2570 }
2571 }
2572  
2573 public void osNpcMoveToTarget(LSL_Key npc, LSL_Vector target, int options)
2574 {
2575 CheckThreatLevel(ThreatLevel.High, "osNpcMoveToTarget");
2576 m_host.AddScriptLPS(1);
2577  
2578 INPCModule module = World.RequestModuleInterface<INPCModule>();
2579 if (module != null)
2580 {
2581 UUID npcId;
2582 if (!UUID.TryParse(npc.m_string, out npcId))
2583 return;
2584  
2585 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2586 return;
2587  
2588 module.MoveToTarget(
2589 new UUID(npc.m_string),
2590 World,
2591 target,
2592 (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0,
2593 (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0,
2594 (options & ScriptBaseClass.OS_NPC_RUNNING) != 0);
2595 }
2596 }
2597  
2598 public LSL_Rotation osNpcGetRot(LSL_Key npc)
2599 {
2600 CheckThreatLevel(ThreatLevel.High, "osNpcGetRot");
2601 m_host.AddScriptLPS(1);
2602  
2603 INPCModule npcModule = World.RequestModuleInterface<INPCModule>();
2604 if (npcModule != null)
2605 {
2606 UUID npcId;
2607 if (!UUID.TryParse(npc.m_string, out npcId))
2608 return new LSL_Rotation(Quaternion.Identity);
2609  
2610 if (!npcModule.CheckPermissions(npcId, m_host.OwnerID))
2611 return new LSL_Rotation(Quaternion.Identity);
2612  
2613 ScenePresence sp = World.GetScenePresence(npcId);
2614  
2615 if (sp != null)
2616 return new LSL_Rotation(sp.GetWorldRotation());
2617 }
2618  
2619 return Quaternion.Identity;
2620 }
2621  
2622 public void osNpcSetRot(LSL_Key npc, LSL_Rotation rotation)
2623 {
2624 CheckThreatLevel(ThreatLevel.High, "osNpcSetRot");
2625 m_host.AddScriptLPS(1);
2626  
2627 INPCModule npcModule = World.RequestModuleInterface<INPCModule>();
2628 if (npcModule != null)
2629 {
2630 UUID npcId;
2631 if (!UUID.TryParse(npc.m_string, out npcId))
2632 return;
2633  
2634 if (!npcModule.CheckPermissions(npcId, m_host.OwnerID))
2635 return;
2636  
2637 ScenePresence sp = World.GetScenePresence(npcId);
2638  
2639 if (sp != null)
2640 sp.Rotation = rotation;
2641 }
2642 }
2643  
2644 public void osNpcStopMoveToTarget(LSL_Key npc)
2645 {
2646 CheckThreatLevel(ThreatLevel.High, "osNpcStopMoveToTarget");
2647 m_host.AddScriptLPS(1);
2648  
2649 INPCModule module = World.RequestModuleInterface<INPCModule>();
2650 if (module != null)
2651 {
2652 UUID npcId = new UUID(npc.m_string);
2653  
2654 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2655 return;
2656  
2657 module.StopMoveToTarget(npcId, World);
2658 }
2659 }
2660  
2661 public void osNpcSay(LSL_Key npc, string message)
2662 {
2663 osNpcSay(npc, 0, message);
2664 }
2665  
2666 public void osNpcSay(LSL_Key npc, int channel, string message)
2667 {
2668 CheckThreatLevel(ThreatLevel.High, "osNpcSay");
2669 m_host.AddScriptLPS(1);
2670  
2671 INPCModule module = World.RequestModuleInterface<INPCModule>();
2672 if (module != null)
2673 {
2674 UUID npcId = new UUID(npc.m_string);
2675  
2676 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2677 return;
2678  
2679 module.Say(npcId, World, message, channel);
2680 }
2681 }
2682  
2683 public void osNpcShout(LSL_Key npc, int channel, string message)
2684 {
2685 CheckThreatLevel(ThreatLevel.High, "osNpcShout");
2686 m_host.AddScriptLPS(1);
2687  
2688 INPCModule module = World.RequestModuleInterface<INPCModule>();
2689 if (module != null)
2690 {
2691 UUID npcId = new UUID(npc.m_string);
2692  
2693 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2694 return;
2695  
2696 module.Shout(npcId, World, message, channel);
2697 }
2698 }
2699  
2700 public void osNpcSit(LSL_Key npc, LSL_Key target, int options)
2701 {
2702 CheckThreatLevel(ThreatLevel.High, "osNpcSit");
2703 m_host.AddScriptLPS(1);
2704  
2705 INPCModule module = World.RequestModuleInterface<INPCModule>();
2706 if (module != null)
2707 {
2708 UUID npcId = new UUID(npc.m_string);
2709  
2710 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2711 return;
2712  
2713 module.Sit(npcId, new UUID(target.m_string), World);
2714 }
2715 }
2716  
2717 public void osNpcStand(LSL_Key npc)
2718 {
2719 CheckThreatLevel(ThreatLevel.High, "osNpcStand");
2720 m_host.AddScriptLPS(1);
2721  
2722 INPCModule module = World.RequestModuleInterface<INPCModule>();
2723 if (module != null)
2724 {
2725 UUID npcId = new UUID(npc.m_string);
2726  
2727 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2728 return;
2729  
2730 module.Stand(npcId, World);
2731 }
2732 }
2733  
2734 public void osNpcRemove(LSL_Key npc)
2735 {
2736 CheckThreatLevel(ThreatLevel.High, "osNpcRemove");
2737 m_host.AddScriptLPS(1);
2738  
2739 INPCModule module = World.RequestModuleInterface<INPCModule>();
2740 if (module != null)
2741 {
2742 UUID npcId = new UUID(npc.m_string);
2743  
2744 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2745 return;
2746  
2747 module.DeleteNPC(npcId, World);
2748 }
2749 }
2750  
2751 public void osNpcPlayAnimation(LSL_Key npc, string animation)
2752 {
2753 CheckThreatLevel(ThreatLevel.High, "osNpcPlayAnimation");
2754 m_host.AddScriptLPS(1);
2755  
2756 INPCModule module = World.RequestModuleInterface<INPCModule>();
2757 if (module != null)
2758 {
2759 UUID npcID = new UUID(npc.m_string);
2760  
2761 if (module.CheckPermissions(npcID, m_host.OwnerID))
2762 AvatarPlayAnimation(npcID.ToString(), animation);
2763 }
2764 }
2765  
2766 public void osNpcStopAnimation(LSL_Key npc, string animation)
2767 {
2768 CheckThreatLevel(ThreatLevel.High, "osNpcStopAnimation");
2769 m_host.AddScriptLPS(1);
2770  
2771 INPCModule module = World.RequestModuleInterface<INPCModule>();
2772 if (module != null)
2773 {
2774 UUID npcID = new UUID(npc.m_string);
2775  
2776 if (module.CheckPermissions(npcID, m_host.OwnerID))
2777 AvatarStopAnimation(npcID.ToString(), animation);
2778 }
2779 }
2780  
2781 public void osNpcWhisper(LSL_Key npc, int channel, string message)
2782 {
2783 CheckThreatLevel(ThreatLevel.High, "osNpcWhisper");
2784 m_host.AddScriptLPS(1);
2785  
2786 INPCModule module = World.RequestModuleInterface<INPCModule>();
2787 if (module != null)
2788 {
2789 UUID npcId = new UUID(npc.m_string);
2790  
2791 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2792 return;
2793  
2794 module.Whisper(npcId, World, message, channel);
2795 }
2796 }
2797  
2798 public void osNpcTouch(LSL_Key npcLSL_Key, LSL_Key object_key, LSL_Integer link_num)
2799 {
2800 CheckThreatLevel(ThreatLevel.High, "osNpcTouch");
2801 m_host.AddScriptLPS(1);
2802  
2803 INPCModule module = World.RequestModuleInterface<INPCModule>();
2804 int linkNum = link_num.value;
2805 if (module != null || (linkNum < 0 && linkNum != ScriptBaseClass.LINK_THIS))
2806 {
2807 UUID npcId;
2808 if (!UUID.TryParse(npcLSL_Key, out npcId) || !module.CheckPermissions(npcId, m_host.OwnerID))
2809 return;
2810  
2811 SceneObjectPart part = null;
2812 UUID objectId;
2813 if (UUID.TryParse(LSL_String.ToString(object_key), out objectId))
2814 part = World.GetSceneObjectPart(objectId);
2815  
2816 if (part == null)
2817 return;
2818  
2819 if (linkNum != ScriptBaseClass.LINK_THIS)
2820 {
2821 if (linkNum == 0 || linkNum == ScriptBaseClass.LINK_ROOT)
2822 { // 0 and 1 are treated as root, find the root if the current part isnt it
2823 if (!part.IsRoot)
2824 part = part.ParentGroup.RootPart;
2825 }
2826 else
2827 { // Find the prim with the given link number if not found then fail silently
2828 part = part.ParentGroup.GetLinkNumPart(linkNum);
2829 if (part == null)
2830 return;
2831 }
2832 }
2833  
2834 module.Touch(npcId, part.UUID);
2835 }
2836 }
2837  
2838 /// <summary>
2839 /// Save the current appearance of the script owner permanently to the named notecard.
2840 /// </summary>
2841 /// <param name="notecard">The name of the notecard to which to save the appearance.</param>
2842 /// <returns>The asset ID of the notecard saved.</returns>
2843 public LSL_Key osOwnerSaveAppearance(string notecard)
2844 {
2845 CheckThreatLevel(ThreatLevel.High, "osOwnerSaveAppearance");
2846 m_host.AddScriptLPS(1);
2847  
2848 return SaveAppearanceToNotecard(m_host.OwnerID, notecard);
2849 }
2850  
2851 public LSL_Key osAgentSaveAppearance(LSL_Key avatarId, string notecard)
2852 {
2853 CheckThreatLevel(ThreatLevel.VeryHigh, "osAgentSaveAppearance");
2854 m_host.AddScriptLPS(1);
2855  
2856 return SaveAppearanceToNotecard(avatarId, notecard);
2857 }
2858  
2859 protected LSL_Key SaveAppearanceToNotecard(ScenePresence sp, string notecard)
2860 {
2861 IAvatarFactoryModule appearanceModule = World.RequestModuleInterface<IAvatarFactoryModule>();
2862  
2863 if (appearanceModule != null)
2864 {
2865 appearanceModule.SaveBakedTextures(sp.UUID);
2866 OSDMap appearancePacked = sp.Appearance.Pack();
2867  
2868 TaskInventoryItem item
2869 = SaveNotecard(notecard, "Avatar Appearance", Util.GetFormattedXml(appearancePacked as OSD), true);
2870  
2871 return new LSL_Key(item.AssetID.ToString());
2872 }
2873 else
2874 {
2875 return new LSL_Key(UUID.Zero.ToString());
2876 }
2877 }
2878  
2879 protected LSL_Key SaveAppearanceToNotecard(UUID avatarId, string notecard)
2880 {
2881 ScenePresence sp = World.GetScenePresence(avatarId);
2882  
2883 if (sp == null || sp.IsChildAgent)
2884 return new LSL_Key(UUID.Zero.ToString());
2885  
2886 return SaveAppearanceToNotecard(sp, notecard);
2887 }
2888  
2889 protected LSL_Key SaveAppearanceToNotecard(LSL_Key rawAvatarId, string notecard)
2890 {
2891 UUID avatarId;
2892 if (!UUID.TryParse(rawAvatarId, out avatarId))
2893 return new LSL_Key(UUID.Zero.ToString());
2894  
2895 return SaveAppearanceToNotecard(avatarId, notecard);
2896 }
2897  
2898 /// <summary>
2899 /// Get current region's map texture UUID
2900 /// </summary>
2901 /// <returns></returns>
2902 public LSL_Key osGetMapTexture()
2903 {
2904 CheckThreatLevel(ThreatLevel.None, "osGetMapTexture");
2905 m_host.AddScriptLPS(1);
2906  
2907 return m_ScriptEngine.World.RegionInfo.RegionSettings.TerrainImageID.ToString();
2908 }
2909  
2910 /// <summary>
2911 /// Get a region's map texture UUID by region UUID or name.
2912 /// </summary>
2913 /// <param name="regionName"></param>
2914 /// <returns></returns>
2915 public LSL_Key osGetRegionMapTexture(string regionName)
2916 {
2917 CheckThreatLevel(ThreatLevel.High, "osGetRegionMapTexture");
2918 m_host.AddScriptLPS(1);
2919  
2920 Scene scene = m_ScriptEngine.World;
2921 UUID key = UUID.Zero;
2922 GridRegion region;
2923  
2924 //If string is a key, use it. Otherwise, try to locate region by name.
2925 if (UUID.TryParse(regionName, out key))
2926 region = scene.GridService.GetRegionByUUID(UUID.Zero, key);
2927 else
2928 region = scene.GridService.GetRegionByName(UUID.Zero, regionName);
2929  
2930 // If region was found, return the regions map texture key.
2931 if (region != null)
2932 key = region.TerrainImage;
2933  
2934 ScriptSleep(1000);
2935  
2936 return key.ToString();
2937 }
2938  
2939 /// <summary>
2940 /// Return information regarding various simulator statistics (sim fps, physics fps, time
2941 /// dilation, total number of prims, total number of active scripts, script lps, various
2942 /// timing data, packets in/out, etc. Basically much the information that's shown in the
2943 /// client's Statistics Bar (Ctrl-Shift-1)
2944 /// </summary>
2945 /// <returns>List of floats</returns>
2946 public LSL_List osGetRegionStats()
2947 {
2948 CheckThreatLevel(ThreatLevel.Moderate, "osGetRegionStats");
2949 m_host.AddScriptLPS(1);
2950 LSL_List ret = new LSL_List();
2951 float[] stats = World.StatsReporter.LastReportedSimStats;
2952  
2953 for (int i = 0; i < 21; i++)
2954 {
2955 ret.Add(new LSL_Float(stats[i]));
2956 }
2957 return ret;
2958 }
2959  
2960 public LSL_Vector osGetRegionSize()
2961 {
2962 CheckThreatLevel(ThreatLevel.None, "osGetRegionSize");
2963 m_host.AddScriptLPS(1);
2964  
2965 bool isMegaregion;
2966 IRegionCombinerModule rcMod = World.RequestModuleInterface<IRegionCombinerModule>();
2967 if (rcMod != null)
2968 isMegaregion = rcMod.IsRootForMegaregion(World.RegionInfo.RegionID);
2969 else
2970 isMegaregion = false;
2971  
2972 if (isMegaregion)
2973 {
2974 Vector2 size = rcMod.GetSizeOfMegaregion(World.RegionInfo.RegionID);
2975 return new LSL_Vector(size.X, size.Y, Constants.RegionHeight);
2976 }
2977 else
2978 {
2979 Scene scene = m_ScriptEngine.World;
2980 GridRegion region = scene.GridService.GetRegionByUUID(UUID.Zero, World.RegionInfo.RegionID);
2981 return new LSL_Vector((float)region.RegionSizeX, (float)region.RegionSizeX, Constants.RegionHeight);
2982 }
2983 }
2984  
2985 public int osGetSimulatorMemory()
2986 {
2987 CheckThreatLevel(ThreatLevel.Moderate, "osGetSimulatorMemory");
2988 m_host.AddScriptLPS(1);
2989 long pws = System.Diagnostics.Process.GetCurrentProcess().WorkingSet64;
2990  
2991 if (pws > Int32.MaxValue)
2992 return Int32.MaxValue;
2993 if (pws < 0)
2994 return 0;
2995  
2996 return (int)pws;
2997 }
2998  
2999 public void osSetSpeed(string UUID, LSL_Float SpeedModifier)
3000 {
3001 CheckThreatLevel(ThreatLevel.Moderate, "osSetSpeed");
3002 m_host.AddScriptLPS(1);
3003 ScenePresence avatar = World.GetScenePresence(new UUID(UUID));
3004  
3005 if (avatar != null)
3006 avatar.SpeedModifier = (float)SpeedModifier;
3007 }
3008  
3009 public void osKickAvatar(string FirstName, string SurName, string alert)
3010 {
3011 CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar");
3012 m_host.AddScriptLPS(1);
3013  
3014 World.ForEachRootScenePresence(delegate(ScenePresence sp)
3015 {
3016 if (sp.Firstname == FirstName && sp.Lastname == SurName)
3017 {
3018 // kick client...
3019 if (alert != null)
3020 sp.ControllingClient.Kick(alert);
3021  
3022 // ...and close on our side
3023 sp.Scene.CloseAgent(sp.UUID, false);
3024 }
3025 });
3026 }
3027  
3028 public LSL_Float osGetHealth(string avatar)
3029 {
3030 CheckThreatLevel(ThreatLevel.None, "osGetHealth");
3031 m_host.AddScriptLPS(1);
3032  
3033 LSL_Float health = new LSL_Float(-1);
3034 ScenePresence presence = World.GetScenePresence(new UUID(avatar));
3035 if (presence != null) health = presence.Health;
3036 return health;
3037 }
3038  
3039 public void osCauseDamage(string avatar, double damage)
3040 {
3041 CheckThreatLevel(ThreatLevel.High, "osCauseDamage");
3042 m_host.AddScriptLPS(1);
3043  
3044 UUID avatarId = new UUID(avatar);
3045 Vector3 pos = m_host.GetWorldPosition();
3046  
3047 ScenePresence presence = World.GetScenePresence(avatarId);
3048 if (presence != null)
3049 {
3050 LandData land = World.GetLandData(pos);
3051 if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage)
3052 {
3053 float health = presence.Health;
3054 health -= (float)damage;
3055 presence.setHealthWithUpdate(health);
3056 if (health <= 0)
3057 {
3058 float healthliveagain = 100;
3059 presence.ControllingClient.SendAgentAlertMessage("You died!", true);
3060 presence.setHealthWithUpdate(healthliveagain);
3061 presence.Scene.TeleportClientHome(presence.UUID, presence.ControllingClient);
3062 }
3063 }
3064 }
3065 }
3066  
3067 public void osCauseHealing(string avatar, double healing)
3068 {
3069 CheckThreatLevel(ThreatLevel.High, "osCauseHealing");
3070 m_host.AddScriptLPS(1);
3071  
3072 UUID avatarId = new UUID(avatar);
3073 ScenePresence presence = World.GetScenePresence(avatarId);
3074  
3075 if (presence != null && World.ScriptDanger(m_host.LocalId, m_host.GetWorldPosition()))
3076 {
3077 float health = presence.Health;
3078 health += (float)healing;
3079  
3080 if (health >= 100)
3081 health = 100;
3082  
3083 presence.setHealthWithUpdate(health);
3084 }
3085 }
3086  
3087 public LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules)
3088 {
3089 CheckThreatLevel(ThreatLevel.High, "osGetPrimitiveParams");
3090 m_host.AddScriptLPS(1);
3091 InitLSL();
3092  
3093 return m_LSL_Api.GetPrimitiveParamsEx(prim, rules);
3094 }
3095  
3096 public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules)
3097 {
3098 CheckThreatLevel(ThreatLevel.High, "osSetPrimitiveParams");
3099 m_host.AddScriptLPS(1);
3100 InitLSL();
3101  
3102 m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams");
3103 }
3104  
3105 /// <summary>
3106 /// Set parameters for light projection in host prim
3107 /// </summary>
3108 public void osSetProjectionParams(bool projection, LSL_Key texture, double fov, double focus, double amb)
3109 {
3110 CheckThreatLevel(ThreatLevel.High, "osSetProjectionParams");
3111  
3112 osSetProjectionParams(UUID.Zero.ToString(), projection, texture, fov, focus, amb);
3113 }
3114  
3115 /// <summary>
3116 /// Set parameters for light projection with uuid of target prim
3117 /// </summary>
3118 public void osSetProjectionParams(LSL_Key prim, bool projection, LSL_Key texture, double fov, double focus, double amb)
3119 {
3120 CheckThreatLevel(ThreatLevel.High, "osSetProjectionParams");
3121 m_host.AddScriptLPS(1);
3122  
3123 SceneObjectPart obj = null;
3124 if (prim == UUID.Zero.ToString())
3125 {
3126 obj = m_host;
3127 }
3128 else
3129 {
3130 obj = World.GetSceneObjectPart(new UUID(prim));
3131 if (obj == null)
3132 return;
3133 }
3134  
3135 obj.Shape.ProjectionEntry = projection;
3136 obj.Shape.ProjectionTextureUUID = new UUID(texture);
3137 obj.Shape.ProjectionFOV = (float)fov;
3138 obj.Shape.ProjectionFocus = (float)focus;
3139 obj.Shape.ProjectionAmbiance = (float)amb;
3140  
3141 obj.ParentGroup.HasGroupChanged = true;
3142 obj.ScheduleFullUpdate();
3143 }
3144  
3145 /// <summary>
3146 /// Like osGetAgents but returns enough info for a radar
3147 /// </summary>
3148 /// <returns>Strided list of the UUID, position and name of each avatar in the region</returns>
3149 public LSL_List osGetAvatarList()
3150 {
3151 CheckThreatLevel(ThreatLevel.None, "osGetAvatarList");
3152 m_host.AddScriptLPS(1);
3153  
3154 LSL_List result = new LSL_List();
3155 World.ForEachRootScenePresence(delegate (ScenePresence avatar)
3156 {
3157 if (avatar != null && avatar.UUID != m_host.OwnerID)
3158 {
3159 result.Add(new LSL_String(avatar.UUID.ToString()));
3160 result.Add(new LSL_Vector(avatar.AbsolutePosition));
3161 result.Add(new LSL_String(avatar.Name));
3162 }
3163 });
3164  
3165 return result;
3166 }
3167  
3168 /// <summary>
3169 /// Convert a unix time to a llGetTimestamp() like string
3170 /// </summary>
3171 /// <param name="unixTime"></param>
3172 /// <returns></returns>
3173 public LSL_String osUnixTimeToTimestamp(long time)
3174 {
3175 CheckThreatLevel(ThreatLevel.VeryLow, "osUnixTimeToTimestamp");
3176 m_host.AddScriptLPS(1);
3177  
3178 long baseTicks = 621355968000000000;
3179 long tickResolution = 10000000;
3180 long epochTicks = (time * tickResolution) + baseTicks;
3181 DateTime date = new DateTime(epochTicks);
3182  
3183 return date.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ");
3184 }
3185  
3186 /// <summary>
3187 /// Get the description from an inventory item
3188 /// </summary>
3189 /// <param name="inventoryName"></param>
3190 /// <returns>Item description</returns>
3191 public LSL_String osGetInventoryDesc(string item)
3192 {
3193 m_host.AddScriptLPS(1);
3194  
3195 lock (m_host.TaskInventory)
3196 {
3197 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3198 {
3199 if (inv.Value.Name == item)
3200 {
3201 return inv.Value.Description.ToString();
3202 }
3203 }
3204 }
3205  
3206 return String.Empty;
3207 }
3208  
3209 /// <summary>
3210 /// Invite user to the group this object is set to
3211 /// </summary>
3212 /// <param name="agentId"></param>
3213 /// <returns></returns>
3214 public LSL_Integer osInviteToGroup(LSL_Key agentId)
3215 {
3216 CheckThreatLevel(ThreatLevel.VeryLow, "osInviteToGroup");
3217 m_host.AddScriptLPS(1);
3218  
3219 UUID agent = new UUID(agentId);
3220  
3221 // groups module is required
3222 IGroupsModule groupsModule = m_ScriptEngine.World.RequestModuleInterface<IGroupsModule>();
3223 if (groupsModule == null) return ScriptBaseClass.FALSE;
3224  
3225 // object has to be set to a group, but not group owned
3226 if (m_host.GroupID == UUID.Zero || m_host.GroupID == m_host.OwnerID) return ScriptBaseClass.FALSE;
3227  
3228 // object owner has to be in that group and required permissions
3229 GroupMembershipData member = groupsModule.GetMembershipData(m_host.GroupID, m_host.OwnerID);
3230 if (member == null || (member.GroupPowers & (ulong)GroupPowers.Invite) == 0) return ScriptBaseClass.FALSE;
3231  
3232 // check if agent is in that group already
3233 //member = groupsModule.GetMembershipData(agent, m_host.GroupID, agent);
3234 //if (member != null) return ScriptBaseClass.FALSE;
3235  
3236 // invited agent has to be present in this scene
3237 if (World.GetScenePresence(agent) == null) return ScriptBaseClass.FALSE;
3238  
3239 groupsModule.InviteGroup(null, m_host.OwnerID, m_host.GroupID, agent, UUID.Zero);
3240  
3241 return ScriptBaseClass.TRUE;
3242 }
3243  
3244 /// <summary>
3245 /// Eject user from the group this object is set to
3246 /// </summary>
3247 /// <param name="agentId"></param>
3248 /// <returns></returns>
3249 public LSL_Integer osEjectFromGroup(LSL_Key agentId)
3250 {
3251 CheckThreatLevel(ThreatLevel.VeryLow, "osEjectFromGroup");
3252 m_host.AddScriptLPS(1);
3253  
3254 UUID agent = new UUID(agentId);
3255  
3256 // groups module is required
3257 IGroupsModule groupsModule = m_ScriptEngine.World.RequestModuleInterface<IGroupsModule>();
3258 if (groupsModule == null) return ScriptBaseClass.FALSE;
3259  
3260 // object has to be set to a group, but not group owned
3261 if (m_host.GroupID == UUID.Zero || m_host.GroupID == m_host.OwnerID) return ScriptBaseClass.FALSE;
3262  
3263 // object owner has to be in that group and required permissions
3264 GroupMembershipData member = groupsModule.GetMembershipData(m_host.GroupID, m_host.OwnerID);
3265 if (member == null || (member.GroupPowers & (ulong)GroupPowers.Eject) == 0) return ScriptBaseClass.FALSE;
3266  
3267 // agent has to be in that group
3268 //member = groupsModule.GetMembershipData(agent, m_host.GroupID, agent);
3269 //if (member == null) return ScriptBaseClass.FALSE;
3270  
3271 // ejectee can be offline
3272  
3273 groupsModule.EjectGroupMember(null, m_host.OwnerID, m_host.GroupID, agent);
3274  
3275 return ScriptBaseClass.TRUE;
3276 }
3277  
3278 /// <summary>
3279 /// Sets terrain estate texture
3280 /// </summary>
3281 /// <param name="level"></param>
3282 /// <param name="texture"></param>
3283 /// <returns></returns>
3284 public void osSetTerrainTexture(int level, LSL_Key texture)
3285 {
3286 CheckThreatLevel(ThreatLevel.High, "osSetTerrainTexture");
3287  
3288 m_host.AddScriptLPS(1);
3289 //Check to make sure that the script's owner is the estate manager/master
3290 //World.Permissions.GenericEstatePermission(
3291 if (World.Permissions.IsGod(m_host.OwnerID))
3292 {
3293 if (level < 0 || level > 3)
3294 return;
3295  
3296 UUID textureID = new UUID();
3297 if (!UUID.TryParse(texture, out textureID))
3298 return;
3299  
3300 // estate module is required
3301 IEstateModule estate = World.RequestModuleInterface<IEstateModule>();
3302 if (estate != null)
3303 estate.setEstateTerrainBaseTexture(level, textureID);
3304 }
3305 }
3306  
3307 /// <summary>
3308 /// Sets terrain heights of estate
3309 /// </summary>
3310 /// <param name="corner"></param>
3311 /// <param name="low"></param>
3312 /// <param name="high"></param>
3313 /// <returns></returns>
3314 public void osSetTerrainTextureHeight(int corner, double low, double high)
3315 {
3316 CheckThreatLevel(ThreatLevel.High, "osSetTerrainTextureHeight");
3317  
3318 m_host.AddScriptLPS(1);
3319 //Check to make sure that the script's owner is the estate manager/master
3320 //World.Permissions.GenericEstatePermission(
3321 if (World.Permissions.IsGod(m_host.OwnerID))
3322 {
3323 if (corner < 0 || corner > 3)
3324 return;
3325  
3326 // estate module is required
3327 IEstateModule estate = World.RequestModuleInterface<IEstateModule>();
3328 if (estate != null)
3329 estate.setEstateTerrainTextureHeights(corner, (float)low, (float)high);
3330 }
3331 }
3332  
3333 #region Attachment commands
3334  
3335 public void osForceAttachToAvatar(int attachmentPoint)
3336 {
3337 CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar");
3338  
3339 m_host.AddScriptLPS(1);
3340  
3341 InitLSL();
3342 ((LSL_Api)m_LSL_Api).AttachToAvatar(attachmentPoint);
3343 }
3344  
3345 public void osForceAttachToAvatarFromInventory(string itemName, int attachmentPoint)
3346 {
3347 CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatarFromInventory");
3348  
3349 m_host.AddScriptLPS(1);
3350  
3351 ForceAttachToAvatarFromInventory(m_host.OwnerID, itemName, attachmentPoint);
3352 }
3353  
3354 public void osForceAttachToOtherAvatarFromInventory(string rawAvatarId, string itemName, int attachmentPoint)
3355 {
3356 CheckThreatLevel(ThreatLevel.Severe, "osForceAttachToOtherAvatarFromInventory");
3357  
3358 m_host.AddScriptLPS(1);
3359  
3360 UUID avatarId;
3361  
3362 if (!UUID.TryParse(rawAvatarId, out avatarId))
3363 return;
3364  
3365 ForceAttachToAvatarFromInventory(avatarId, itemName, attachmentPoint);
3366 }
3367  
3368 public void ForceAttachToAvatarFromInventory(UUID avatarId, string itemName, int attachmentPoint)
3369 {
3370 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3371  
3372 if (attachmentsModule == null)
3373 return;
3374  
3375 InitLSL();
3376  
3377 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName);
3378  
3379 if (item == null)
3380 {
3381 ((LSL_Api)m_LSL_Api).llSay(0, string.Format("Could not find object '{0}'", itemName));
3382 throw new Exception(String.Format("The inventory item '{0}' could not be found", itemName));
3383 }
3384  
3385 if (item.InvType != (int)InventoryType.Object)
3386 {
3387 // FIXME: Temporary null check for regression tests since they dont' have the infrastructure to set
3388 // up the api reference.
3389 if (m_LSL_Api != null)
3390 ((LSL_Api)m_LSL_Api).llSay(0, string.Format("Unable to attach, item '{0}' is not an object.", itemName));
3391  
3392 throw new Exception(String.Format("The inventory item '{0}' is not an object", itemName));
3393 }
3394  
3395 ScenePresence sp = World.GetScenePresence(avatarId);
3396  
3397 if (sp == null)
3398 return;
3399  
3400 string message;
3401 InventoryItemBase newItem = World.MoveTaskInventoryItem(sp.UUID, UUID.Zero, m_host, item.ItemID, out message);
3402  
3403 if (newItem == null)
3404 {
3405 m_log.ErrorFormat(
3406 "[OSSL API]: Could not create user inventory item {0} for {1}, attach point {2} in {3}: {4}",
3407 itemName, m_host.Name, attachmentPoint, World.Name, message);
3408 ((LSL_Api)m_LSL_Api).llSay(0, message);
3409 return;
3410 }
3411  
3412 attachmentsModule.RezSingleAttachmentFromInventory(sp, newItem.ID, (uint)attachmentPoint);
3413 }
3414  
3415 public void osForceDetachFromAvatar()
3416 {
3417 CheckThreatLevel(ThreatLevel.High, "osForceDetachFromAvatar");
3418  
3419 m_host.AddScriptLPS(1);
3420  
3421 InitLSL();
3422 ((LSL_Api)m_LSL_Api).DetachFromAvatar();
3423 }
3424  
3425 public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
3426 {
3427 CheckThreatLevel(ThreatLevel.Moderate, "osGetNumberOfAttachments");
3428  
3429 m_host.AddScriptLPS(1);
3430  
3431 UUID targetUUID;
3432 ScenePresence target;
3433 LSL_List resp = new LSL_List();
3434  
3435 if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
3436 {
3437 foreach (object point in attachmentPoints.Data)
3438 {
3439 LSL_Integer ipoint = new LSL_Integer(
3440 (point is LSL_Integer || point is int || point is uint) ?
3441 (int)point :
3442  
3443 );
3444 resp.Add(ipoint);
3445 if (ipoint == 0)
3446 {
3447 // indicates zero attachments
3448 resp.Add(new LSL_Integer(0));
3449 }
3450 else
3451 {
3452 // gets the number of attachments on the attachment point
3453 resp.Add(new LSL_Integer(target.GetAttachments((uint)ipoint).Count));
3454 }
3455 }
3456 }
3457  
3458 return resp;
3459 }
3460  
3461 public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int options)
3462 {
3463 CheckThreatLevel(ThreatLevel.Moderate, "osMessageAttachments");
3464 m_host.AddScriptLPS(1);
3465  
3466 UUID targetUUID;
3467 ScenePresence target;
3468  
3469 if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
3470 {
3471 List<int> aps = new List<int>();
3472 foreach (object point in attachmentPoints.Data)
3473 {
3474 int ipoint;
3475 if (int.TryParse(point.ToString(), out ipoint))
3476 {
3477 aps.Add(ipoint);
3478 }
3479 }
3480  
3481 List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
3482  
3483 bool msgAll = aps.Contains(ScriptBaseClass.OS_ATTACH_MSG_ALL);
3484 bool invertPoints = (options & ScriptBaseClass.OS_ATTACH_MSG_INVERT_POINTS) != 0;
3485  
3486 if (msgAll && invertPoints)
3487 {
3488 return;
3489 }
3490 else if (msgAll || invertPoints)
3491 {
3492 attachments = target.GetAttachments();
3493 }
3494 else
3495 {
3496 foreach (int point in aps)
3497 {
3498 if (point > 0)
3499 {
3500 attachments.AddRange(target.GetAttachments((uint)point));
3501 }
3502 }
3503 }
3504  
3505 // if we have no attachments at this point, exit now
3506 if (attachments.Count == 0)
3507 {
3508 return;
3509 }
3510  
3511 List<SceneObjectGroup> ignoreThese = new List<SceneObjectGroup>();
3512  
3513 if (invertPoints)
3514 {
3515 foreach (SceneObjectGroup attachment in attachments)
3516 {
3517 if (aps.Contains((int)attachment.AttachmentPoint))
3518 {
3519 ignoreThese.Add(attachment);
3520 }
3521 }
3522 }
3523  
3524 foreach (SceneObjectGroup attachment in ignoreThese)
3525 {
3526 attachments.Remove(attachment);
3527 }
3528 ignoreThese.Clear();
3529  
3530 // if inverting removed all attachments to check, exit now
3531 if (attachments.Count < 1)
3532 {
3533 return;
3534 }
3535  
3536 if ((options & ScriptBaseClass.OS_ATTACH_MSG_OBJECT_CREATOR) != 0)
3537 {
3538 foreach (SceneObjectGroup attachment in attachments)
3539 {
3540 if (attachment.RootPart.CreatorID != m_host.CreatorID)
3541 {
3542 ignoreThese.Add(attachment);
3543 }
3544 }
3545  
3546 foreach (SceneObjectGroup attachment in ignoreThese)
3547 {
3548 attachments.Remove(attachment);
3549 }
3550 ignoreThese.Clear();
3551  
3552 // if filtering by same object creator removed all
3553 // attachments to check, exit now
3554 if (attachments.Count == 0)
3555 {
3556 return;
3557 }
3558 }
3559  
3560 if ((options & ScriptBaseClass.OS_ATTACH_MSG_SCRIPT_CREATOR) != 0)
3561 {
3562 foreach (SceneObjectGroup attachment in attachments)
3563 {
3564 if (attachment.RootPart.CreatorID != m_item.CreatorID)
3565 {
3566 ignoreThese.Add(attachment);
3567 }
3568 }
3569  
3570 foreach (SceneObjectGroup attachment in ignoreThese)
3571 {
3572 attachments.Remove(attachment);
3573 }
3574 ignoreThese.Clear();
3575  
3576 // if filtering by object creator must match originating
3577 // script creator removed all attachments to check,
3578 // exit now
3579 if (attachments.Count == 0)
3580 {
3581 return;
3582 }
3583 }
3584  
3585 foreach (SceneObjectGroup attachment in attachments)
3586 {
3587 MessageObject(attachment.RootPart.UUID, message);
3588 }
3589 }
3590 }
3591  
3592 #endregion
3593  
3594 /// <summary>
3595 /// Checks if thing is a UUID.
3596 /// </summary>
3597 /// <param name="thing"></param>
3598 /// <returns>1 if thing is a valid UUID, 0 otherwise</returns>
3599 public LSL_Integer osIsUUID(string thing)
3600 {
3601 CheckThreatLevel(ThreatLevel.None, "osIsUUID");
3602 m_host.AddScriptLPS(1);
3603  
3604 UUID test;
3605 return UUID.TryParse(thing, out test) ? 1 : 0;
3606 }
3607  
3608 /// <summary>
3609 /// Wraps to Math.Min()
3610 /// </summary>
3611 /// <param name="a"></param>
3612 /// <param name="b"></param>
3613 /// <returns></returns>
3614 public LSL_Float osMin(double a, double b)
3615 {
3616 CheckThreatLevel(ThreatLevel.None, "osMin");
3617 m_host.AddScriptLPS(1);
3618  
3619 return Math.Min(a, b);
3620 }
3621  
3622 /// <summary>
3623 /// Wraps to Math.max()
3624 /// </summary>
3625 /// <param name="a"></param>
3626 /// <param name="b"></param>
3627 /// <returns></returns>
3628 public LSL_Float osMax(double a, double b)
3629 {
3630 CheckThreatLevel(ThreatLevel.None, "osMax");
3631 m_host.AddScriptLPS(1);
3632  
3633 return Math.Max(a, b);
3634 }
3635  
3636 public LSL_Key osGetRezzingObject()
3637 {
3638 CheckThreatLevel(ThreatLevel.None, "osGetRezzingObject");
3639 m_host.AddScriptLPS(1);
3640  
3641 return new LSL_Key(m_host.ParentGroup.FromPartID.ToString());
3642 }
3643  
3644 /// <summary>
3645 /// Sets the response type for an HTTP request/response
3646 /// </summary>
3647 /// <returns></returns>
3648 public void osSetContentType(LSL_Key id, string type)
3649 {
3650 CheckThreatLevel(ThreatLevel.High, "osSetContentType");
3651  
3652 if (m_UrlModule != null)
3653 m_UrlModule.HttpContentType(new UUID(id),type);
3654 }
3655  
3656 /// Shout an error if the object owner did not grant the script the specified permissions.
3657 /// </summary>
3658 /// <param name="perms"></param>
3659 /// <returns>boolean indicating whether an error was shouted.</returns>
3660 protected bool ShoutErrorOnLackingOwnerPerms(int perms, string errorPrefix)
3661 {
3662 m_host.AddScriptLPS(1);
3663 bool fail = false;
3664 if (m_item.PermsGranter != m_host.OwnerID)
3665 {
3666 fail = true;
3667 OSSLShoutError(string.Format("{0}. Permissions not granted to owner.", errorPrefix));
3668 }
3669 else if ((m_item.PermsMask & perms) == 0)
3670 {
3671 fail = true;
3672 OSSLShoutError(string.Format("{0}. Permissions not granted.", errorPrefix));
3673 }
3674  
3675 return fail;
3676 }
3677  
3678 protected void DropAttachment(bool checkPerms)
3679 {
3680 if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment"))
3681 {
3682 return;
3683 }
3684  
3685 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3686 ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID);
3687  
3688 if (attachmentsModule != null && sp != null)
3689 {
3690 attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId);
3691 }
3692 }
3693  
3694 protected void DropAttachmentAt(bool checkPerms, LSL_Vector pos, LSL_Rotation rot)
3695 {
3696 if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment"))
3697 {
3698 return;
3699 }
3700  
3701 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3702 ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID);
3703  
3704 if (attachmentsModule != null && sp != null)
3705 {
3706 attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId, pos, rot);
3707 }
3708 }
3709  
3710 public void osDropAttachment()
3711 {
3712 CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment");
3713 m_host.AddScriptLPS(1);
3714  
3715 DropAttachment(true);
3716 }
3717  
3718 public void osForceDropAttachment()
3719 {
3720 CheckThreatLevel(ThreatLevel.High, "osForceDropAttachment");
3721 m_host.AddScriptLPS(1);
3722  
3723 DropAttachment(false);
3724 }
3725  
3726 public void osDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot)
3727 {
3728 CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachmentAt");
3729 m_host.AddScriptLPS(1);
3730  
3731 DropAttachmentAt(true, pos, rot);
3732 }
3733  
3734 public void osForceDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot)
3735 {
3736 CheckThreatLevel(ThreatLevel.High, "osForceDropAttachmentAt");
3737 m_host.AddScriptLPS(1);
3738  
3739 DropAttachmentAt(false, pos, rot);
3740 }
3741  
3742 public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield)
3743 {
3744 CheckThreatLevel(ThreatLevel.Low, "osListenRegex");
3745 m_host.AddScriptLPS(1);
3746 UUID keyID;
3747 UUID.TryParse(ID, out keyID);
3748  
3749 // if we want the name to be used as a regular expression, ensure it is valid first.
3750 if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_NAME) == ScriptBaseClass.OS_LISTEN_REGEX_NAME)
3751 {
3752 try
3753 {
3754 Regex.IsMatch("", name);
3755 }
3756 catch (Exception)
3757 {
3758 OSSLShoutError("Name regex is invalid.");
3759 return -1;
3760 }
3761 }
3762  
3763 // if we want the msg to be used as a regular expression, ensure it is valid first.
3764 if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE) == ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE)
3765 {
3766 try
3767 {
3768 Regex.IsMatch("", msg);
3769 }
3770 catch (Exception)
3771 {
3772 OSSLShoutError("Message regex is invalid.");
3773 return -1;
3774 }
3775 }
3776  
3777 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
3778 return (wComm == null) ? -1 : wComm.Listen(
3779 m_host.LocalId,
3780 m_item.ItemID,
3781 m_host.UUID,
3782 channelID,
3783 name,
3784 keyID,
3785 msg,
3786 regexBitfield
3787 );
3788 }
3789  
3790 public LSL_Integer osRegexIsMatch(string input, string pattern)
3791 {
3792 CheckThreatLevel(ThreatLevel.Low, "osRegexIsMatch");
3793 m_host.AddScriptLPS(1);
3794 try
3795 {
3796 return Regex.IsMatch(input, pattern) ? 1 : 0;
3797 }
3798 catch (Exception)
3799 {
3800 OSSLShoutError("Possible invalid regular expression detected.");
3801 return 0;
3802 }
3803 }
3804 }
3805 }