OSSL_Api.cs 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191
  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 OpenSim 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. using System;
  28. using System.Collections;
  29. using System.Collections.Generic;
  30. using System.Runtime.Remoting.Lifetime;
  31. using System.Text;
  32. using System.Net;
  33. using OpenMetaverse;
  34. using Nini.Config;
  35. using OpenSim;
  36. using OpenSim.Framework;
  37. using OpenSim.Framework.Console;
  38. using OpenSim.Region.Framework.Interfaces;
  39. using OpenSim.Region.Framework.Scenes;
  40. using OpenSim.Region.ScriptEngine.Shared;
  41. using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
  42. using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
  43. using OpenSim.Region.ScriptEngine.Interfaces;
  44. using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
  45. using TPFlags = OpenSim.Framework.Constants.TeleportFlags;
  46. using System.Text.RegularExpressions;
  47. using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
  48. using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
  49. using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
  50. using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
  51. using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
  52. using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
  53. using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
  54. namespace OpenSim.Region.ScriptEngine.Shared.Api
  55. {
  56. //////////////////////////////////////////////////////////////
  57. //
  58. // Level description
  59. //
  60. // None - Function is no threat at all. It doesn't constitute
  61. // an threat to either users or the system and has no
  62. // known side effects
  63. //
  64. // Nuisance - Abuse of this command can cause a nuisance to the
  65. // region operator, such as log message spew
  66. //
  67. // VeryLow - Extreme levels ob abuse of this function can cause
  68. // impaired functioning of the region, or very gullible
  69. // users can be tricked into experiencing harmless effects
  70. //
  71. // Low - Intentional abuse can cause crashes or malfunction
  72. // under certain circumstances, which can easily be rectified,
  73. // or certain users can be tricked into certain situations
  74. // in an avoidable manner.
  75. //
  76. // Moderate - Intentional abuse can cause denial of service and crashes
  77. // with potential of data or state loss, or trusting users
  78. // can be tricked into embarrassing or uncomfortable
  79. // situationsa.
  80. //
  81. // High - Casual abuse can cause impaired functionality or temporary
  82. // denial of service conditions. Intentional abuse can easily
  83. // cause crashes with potential data loss, or can be used to
  84. // trick experienced and cautious users into unwanted situations,
  85. // or changes global data permanently and without undo ability
  86. //
  87. // VeryHigh - Even normal use may, depending on the number of instances,
  88. // or frequency of use, result in severe service impairment
  89. // or crash with loss of data, or can be used to cause
  90. // unwanted or harmful effects on users without giving the
  91. // user a means to avoid it.
  92. //
  93. // Severe - Even casual use is a danger to region stability, or function
  94. // allows console or OS command execution, or function allows
  95. // taking money without consent, or allows deletion or
  96. // modification of user data, or allows the compromise of
  97. // sensitive data by design.
  98. [Serializable]
  99. public class OSSL_Api : MarshalByRefObject, IOSSL_Api, IScriptApi
  100. {
  101. internal IScriptEngine m_ScriptEngine;
  102. internal ILSL_Api m_LSL_Api; // get a reference to the LSL API so we can call methods housed there
  103. internal SceneObjectPart m_host;
  104. internal uint m_localID;
  105. internal UUID m_itemID;
  106. internal bool m_OSFunctionsEnabled = false;
  107. internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow;
  108. internal float m_ScriptDelayFactor = 1.0f;
  109. internal float m_ScriptDistanceFactor = 1.0f;
  110. internal Dictionary<string, List<UUID> > m_FunctionPerms = new Dictionary<string, List<UUID> >();
  111. public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
  112. {
  113. m_ScriptEngine = ScriptEngine;
  114. m_host = host;
  115. m_localID = localID;
  116. m_itemID = itemID;
  117. if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false))
  118. m_OSFunctionsEnabled = true;
  119. m_ScriptDelayFactor =
  120. m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
  121. m_ScriptDistanceFactor =
  122. m_ScriptEngine.Config.GetFloat("ScriptDistanceLimitFactor", 1.0f);
  123. string risk = m_ScriptEngine.Config.GetString("OSFunctionThreatLevel", "VeryLow");
  124. switch (risk)
  125. {
  126. case "None":
  127. m_MaxThreatLevel = ThreatLevel.None;
  128. break;
  129. case "VeryLow":
  130. m_MaxThreatLevel = ThreatLevel.VeryLow;
  131. break;
  132. case "Low":
  133. m_MaxThreatLevel = ThreatLevel.Low;
  134. break;
  135. case "Moderate":
  136. m_MaxThreatLevel = ThreatLevel.Moderate;
  137. break;
  138. case "High":
  139. m_MaxThreatLevel = ThreatLevel.High;
  140. break;
  141. case "VeryHigh":
  142. m_MaxThreatLevel = ThreatLevel.VeryHigh;
  143. break;
  144. case "Severe":
  145. m_MaxThreatLevel = ThreatLevel.Severe;
  146. break;
  147. default:
  148. break;
  149. }
  150. }
  151. //
  152. // Never expire this object
  153. //
  154. public override Object InitializeLifetimeService()
  155. {
  156. ILease lease = (ILease)base.InitializeLifetimeService();
  157. if (lease.CurrentState == LeaseState.Initial)
  158. {
  159. lease.InitialLeaseTime = TimeSpan.Zero;
  160. }
  161. return lease;
  162. }
  163. public Scene World
  164. {
  165. get { return m_ScriptEngine.World; }
  166. }
  167. internal void OSSLError(string msg)
  168. {
  169. throw new Exception("OSSL Runtime Error: " + msg);
  170. }
  171. public void CheckThreatLevel(ThreatLevel level, string function)
  172. {
  173. if (!m_OSFunctionsEnabled)
  174. OSSLError(String.Format("{0} permission denied. All OS functions are disabled.", function)); // throws
  175. if (!m_FunctionPerms.ContainsKey(function))
  176. {
  177. string perm = m_ScriptEngine.Config.GetString("Allow_" + function, "");
  178. if (perm == "")
  179. {
  180. m_FunctionPerms[function] = null; // a null value is default
  181. }
  182. else
  183. {
  184. bool allowed;
  185. if (bool.TryParse(perm, out allowed))
  186. {
  187. // Boolean given
  188. if (allowed)
  189. {
  190. m_FunctionPerms[function] = new List<UUID>();
  191. m_FunctionPerms[function].Add(UUID.Zero);
  192. }
  193. else
  194. m_FunctionPerms[function] = new List<UUID>(); // Empty list = none
  195. }
  196. else
  197. {
  198. m_FunctionPerms[function] = new List<UUID>();
  199. string[] ids = perm.Split(new char[] {','});
  200. foreach (string id in ids)
  201. {
  202. string current = id.Trim();
  203. UUID uuid;
  204. if (UUID.TryParse(current, out uuid))
  205. {
  206. if (uuid != UUID.Zero)
  207. m_FunctionPerms[function].Add(uuid);
  208. }
  209. }
  210. }
  211. }
  212. }
  213. // If the list is null, then the value was true / undefined
  214. // Threat level governs permissions in this case
  215. //
  216. // If the list is non-null, then it is a list of UUIDs allowed
  217. // to use that particular function. False causes an empty
  218. // list and therefore means "no one"
  219. //
  220. // To allow use by anyone, the list contains UUID.Zero
  221. //
  222. if (m_FunctionPerms[function] == null) // No list = true
  223. {
  224. if (level > m_MaxThreatLevel)
  225. OSSLError(
  226. String.Format(
  227. "{0} permission denied. Allowed threat level is {1} but function threat level is {2}.",
  228. function, m_MaxThreatLevel, level));
  229. }
  230. else
  231. {
  232. if (!m_FunctionPerms[function].Contains(UUID.Zero))
  233. {
  234. if (!m_FunctionPerms[function].Contains(m_host.OwnerID))
  235. OSSLError(
  236. String.Format("{0} permission denied. Prim owner is not in the list of users allowed to execute this function.",
  237. function));
  238. }
  239. }
  240. }
  241. protected void ScriptSleep(int delay)
  242. {
  243. delay = (int)((float)delay * m_ScriptDelayFactor);
  244. if (delay == 0)
  245. return;
  246. System.Threading.Thread.Sleep(delay);
  247. }
  248. //
  249. // OpenSim functions
  250. //
  251. public int osTerrainSetHeight(int x, int y, double val)
  252. {
  253. CheckThreatLevel(ThreatLevel.High, "osTerrainSetHeight");
  254. m_host.AddScriptLPS(1);
  255. if (x > 255 || x < 0 || y > 255 || y < 0)
  256. OSSLError("osTerrainSetHeight: Coordinate out of bounds");
  257. if (World.Permissions.CanTerraformLand(m_host.OwnerID, new Vector3(x, y, 0)))
  258. {
  259. World.Heightmap[x, y] = val;
  260. return 1;
  261. }
  262. else
  263. {
  264. return 0;
  265. }
  266. }
  267. public double osTerrainGetHeight(int x, int y)
  268. {
  269. CheckThreatLevel(ThreatLevel.None, "osTerrainGetHeight");
  270. m_host.AddScriptLPS(1);
  271. if (x > 255 || x < 0 || y > 255 || y < 0)
  272. OSSLError("osTerrainGetHeight: Coordinate out of bounds");
  273. return World.Heightmap[x, y];
  274. }
  275. public int osRegionRestart(double seconds)
  276. {
  277. // This is High here because region restart is not reliable
  278. // it may result in the region staying down or becoming
  279. // unstable. This should be changed to Low or VeryLow once
  280. // The underlying functionality is fixed, since the security
  281. // as such is sound
  282. //
  283. CheckThreatLevel(ThreatLevel.High, "osRegionRestart");
  284. m_host.AddScriptLPS(1);
  285. if (World.Permissions.CanIssueEstateCommand(m_host.OwnerID, false))
  286. {
  287. World.Restart((float)seconds);
  288. return 1;
  289. }
  290. else
  291. {
  292. return 0;
  293. }
  294. }
  295. public void osRegionNotice(string msg)
  296. {
  297. // This implementation provides absolutely no security
  298. // It's high griefing potential makes this classification
  299. // necessary
  300. //
  301. CheckThreatLevel(ThreatLevel.VeryHigh, "osRegionNotice");
  302. m_host.AddScriptLPS(1);
  303. IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
  304. if (dm != null)
  305. dm.SendGeneralAlert(msg);
  306. }
  307. public void osSetRot(UUID target, Quaternion rotation)
  308. {
  309. // This function has no security. It can be used to destroy
  310. // arbitrary builds the user would normally have no rights to
  311. //
  312. CheckThreatLevel(ThreatLevel.VeryHigh, "osSetRot");
  313. m_host.AddScriptLPS(1);
  314. if (World.Entities.ContainsKey(target))
  315. {
  316. World.Entities[target].Rotation = rotation;
  317. }
  318. else
  319. {
  320. OSSLError("osSetRot: Invalid target");
  321. }
  322. }
  323. public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams,
  324. int timer)
  325. {
  326. // This may be upgraded depending on the griefing or DOS
  327. // potential, or guarded with a delay
  328. //
  329. CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureURL");
  330. m_host.AddScriptLPS(1);
  331. if (dynamicID == String.Empty)
  332. {
  333. IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
  334. UUID createdTexture =
  335. textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url,
  336. extraParams, timer);
  337. return createdTexture.ToString();
  338. }
  339. else
  340. {
  341. //TODO update existing dynamic textures
  342. }
  343. return UUID.Zero.ToString();
  344. }
  345. public string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams,
  346. int timer, int alpha)
  347. {
  348. CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureURLBlend");
  349. m_host.AddScriptLPS(1);
  350. if (dynamicID == String.Empty)
  351. {
  352. IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
  353. UUID createdTexture =
  354. textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url,
  355. extraParams, timer, true, (byte) alpha);
  356. return createdTexture.ToString();
  357. }
  358. else
  359. {
  360. //TODO update existing dynamic textures
  361. }
  362. return UUID.Zero.ToString();
  363. }
  364. public string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams,
  365. int timer)
  366. {
  367. CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureData");
  368. m_host.AddScriptLPS(1);
  369. if (dynamicID == String.Empty)
  370. {
  371. IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
  372. if (textureManager != null)
  373. {
  374. if (extraParams == String.Empty)
  375. {
  376. extraParams = "256";
  377. }
  378. UUID createdTexture =
  379. textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data,
  380. extraParams, timer);
  381. return createdTexture.ToString();
  382. }
  383. }
  384. else
  385. {
  386. //TODO update existing dynamic textures
  387. }
  388. return UUID.Zero.ToString();
  389. }
  390. public string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams,
  391. int timer, int alpha)
  392. {
  393. CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureDataBlend");
  394. m_host.AddScriptLPS(1);
  395. if (dynamicID == String.Empty)
  396. {
  397. IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
  398. if (textureManager != null)
  399. {
  400. if (extraParams == String.Empty)
  401. {
  402. extraParams = "256";
  403. }
  404. UUID createdTexture =
  405. textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data,
  406. extraParams, timer, true, (byte) alpha);
  407. return createdTexture.ToString();
  408. }
  409. }
  410. else
  411. {
  412. //TODO update existing dynamic textures
  413. }
  414. return UUID.Zero.ToString();
  415. }
  416. public bool osConsoleCommand(string command)
  417. {
  418. CheckThreatLevel(ThreatLevel.Severe, "osConsoleCommand");
  419. m_host.AddScriptLPS(1);
  420. if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID))
  421. {
  422. MainConsole.Instance.RunCommand(command);
  423. return true;
  424. }
  425. return false;
  426. }
  427. public void osSetPrimFloatOnWater(int floatYN)
  428. {
  429. CheckThreatLevel(ThreatLevel.VeryLow, "osSetPrimFloatOnWater");
  430. m_host.AddScriptLPS(1);
  431. if (m_host.ParentGroup != null)
  432. {
  433. if (m_host.ParentGroup.RootPart != null)
  434. {
  435. m_host.ParentGroup.RootPart.SetFloatOnWater(floatYN);
  436. }
  437. }
  438. }
  439. // Teleport functions
  440. public void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat)
  441. {
  442. // High because there is no security check. High griefer potential
  443. //
  444. CheckThreatLevel(ThreatLevel.High, "osTeleportAgent");
  445. m_host.AddScriptLPS(1);
  446. UUID agentId = new UUID();
  447. if (UUID.TryParse(agent, out agentId))
  448. {
  449. ScenePresence presence = World.GetScenePresence(agentId);
  450. if (presence != null)
  451. {
  452. // agent must be over owners land to avoid abuse
  453. if (m_host.OwnerID
  454. == World.LandChannel.GetLandObject(
  455. presence.AbsolutePosition.X, presence.AbsolutePosition.Y).landData.OwnerID)
  456. {
  457. presence.ControllingClient.SendTeleportLocationStart();
  458. World.RequestTeleportLocation(presence.ControllingClient, regionName,
  459. new Vector3((float)position.x, (float)position.y, (float)position.z),
  460. new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation);
  461. ScriptSleep(5000);
  462. }
  463. }
  464. }
  465. }
  466. // Teleport functions
  467. public void osTeleportAgent(string agent, uint regionX, uint regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat)
  468. {
  469. // High because there is no security check. High griefer potential
  470. //
  471. CheckThreatLevel(ThreatLevel.High, "osTeleportAgent");
  472. ulong regionHandle = Util.UIntsToLong((regionX * (uint)Constants.RegionSize), (regionY * (uint)Constants.RegionSize));
  473. m_host.AddScriptLPS(1);
  474. UUID agentId = new UUID();
  475. if (UUID.TryParse(agent, out agentId))
  476. {
  477. ScenePresence presence = World.GetScenePresence(agentId);
  478. if (presence != null)
  479. {
  480. // agent must be over owners land to avoid abuse
  481. if (m_host.OwnerID
  482. == World.LandChannel.GetLandObject(
  483. presence.AbsolutePosition.X, presence.AbsolutePosition.Y).landData.OwnerID)
  484. {
  485. presence.ControllingClient.SendTeleportLocationStart();
  486. World.RequestTeleportLocation(presence.ControllingClient, regionHandle,
  487. new Vector3((float)position.x, (float)position.y, (float)position.z),
  488. new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation);
  489. ScriptSleep(5000);
  490. }
  491. }
  492. }
  493. }
  494. public void osTeleportAgent(string agent, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat)
  495. {
  496. osTeleportAgent(agent, World.RegionInfo.RegionName, position, lookat);
  497. }
  498. // Functions that get information from the agent itself.
  499. //
  500. // osGetAgentIP - this is used to determine the IP address of
  501. //the client. This is needed to help configure other in world
  502. //resources based on the IP address of the clients connected.
  503. //I think High is a good risk level for this, as it is an
  504. //information leak.
  505. public string osGetAgentIP(string agent)
  506. {
  507. CheckThreatLevel(ThreatLevel.High, "osGetAgentIP");
  508. UUID avatarID = (UUID)agent;
  509. m_host.AddScriptLPS(1);
  510. if (World.Entities.ContainsKey((UUID)agent) && World.Entities[avatarID] is ScenePresence)
  511. {
  512. ScenePresence target = (ScenePresence)World.Entities[avatarID];
  513. EndPoint ep = target.ControllingClient.GetClientInfo().userEP;
  514. if (ep is IPEndPoint)
  515. {
  516. IPEndPoint ip = (IPEndPoint)ep;
  517. return ip.Address.ToString();
  518. }
  519. }
  520. // fall through case, just return nothing
  521. return "";
  522. }
  523. // Adam's super super custom animation functions
  524. public void osAvatarPlayAnimation(string avatar, string animation)
  525. {
  526. CheckThreatLevel(ThreatLevel.VeryHigh, "osAvatarPlayAnimation");
  527. UUID avatarID = (UUID)avatar;
  528. m_host.AddScriptLPS(1);
  529. if (World.Entities.ContainsKey((UUID)avatar) && World.Entities[avatarID] is ScenePresence)
  530. {
  531. ScenePresence target = (ScenePresence)World.Entities[avatarID];
  532. target.AddAnimation(animation, m_host.UUID);
  533. }
  534. }
  535. public void osAvatarStopAnimation(string avatar, string animation)
  536. {
  537. CheckThreatLevel(ThreatLevel.VeryHigh, "osAvatarStopAnimation");
  538. UUID avatarID = (UUID)avatar;
  539. m_host.AddScriptLPS(1);
  540. if (World.Entities.ContainsKey(avatarID) && World.Entities[avatarID] is ScenePresence)
  541. {
  542. ScenePresence target = (ScenePresence)World.Entities[avatarID];
  543. target.RemoveAnimation(animation);
  544. }
  545. }
  546. //Texture draw functions
  547. public string osMovePen(string drawList, int x, int y)
  548. {
  549. CheckThreatLevel(ThreatLevel.None, "osMovePen");
  550. m_host.AddScriptLPS(1);
  551. drawList += "MoveTo " + x + "," + y + ";";
  552. return drawList;
  553. }
  554. public string osDrawLine(string drawList, int startX, int startY, int endX, int endY)
  555. {
  556. CheckThreatLevel(ThreatLevel.None, "osDrawLine");
  557. m_host.AddScriptLPS(1);
  558. drawList += "MoveTo "+ startX+","+ startY +"; LineTo "+endX +","+endY +"; ";
  559. return drawList;
  560. }
  561. public string osDrawLine(string drawList, int endX, int endY)
  562. {
  563. CheckThreatLevel(ThreatLevel.None, "osDrawLine");
  564. m_host.AddScriptLPS(1);
  565. drawList += "LineTo " + endX + "," + endY + "; ";
  566. return drawList;
  567. }
  568. public string osDrawText(string drawList, string text)
  569. {
  570. CheckThreatLevel(ThreatLevel.None, "osDrawText");
  571. m_host.AddScriptLPS(1);
  572. drawList += "Text " + text + "; ";
  573. return drawList;
  574. }
  575. public string osDrawEllipse(string drawList, int width, int height)
  576. {
  577. CheckThreatLevel(ThreatLevel.None, "osDrawEllipse");
  578. m_host.AddScriptLPS(1);
  579. drawList += "Ellipse " + width + "," + height + "; ";
  580. return drawList;
  581. }
  582. public string osDrawRectangle(string drawList, int width, int height)
  583. {
  584. CheckThreatLevel(ThreatLevel.None, "osDrawRectangle");
  585. m_host.AddScriptLPS(1);
  586. drawList += "Rectangle " + width + "," + height + "; ";
  587. return drawList;
  588. }
  589. public string osDrawFilledRectangle(string drawList, int width, int height)
  590. {
  591. CheckThreatLevel(ThreatLevel.None, "osDrawFilledRectangle");
  592. m_host.AddScriptLPS(1);
  593. drawList += "FillRectangle " + width + "," + height + "; ";
  594. return drawList;
  595. }
  596. public string osSetFontSize(string drawList, int fontSize)
  597. {
  598. CheckThreatLevel(ThreatLevel.None, "osSetFontSize");
  599. m_host.AddScriptLPS(1);
  600. drawList += "FontSize "+ fontSize +"; ";
  601. return drawList;
  602. }
  603. public string osSetPenSize(string drawList, int penSize)
  604. {
  605. CheckThreatLevel(ThreatLevel.None, "osSetPenSize");
  606. m_host.AddScriptLPS(1);
  607. drawList += "PenSize " + penSize + "; ";
  608. return drawList;
  609. }
  610. public string osSetPenColour(string drawList, string colour)
  611. {
  612. CheckThreatLevel(ThreatLevel.None, "osSetPenColour");
  613. m_host.AddScriptLPS(1);
  614. drawList += "PenColour " + colour + "; ";
  615. return drawList;
  616. }
  617. public string osDrawImage(string drawList, int width, int height, string imageUrl)
  618. {
  619. CheckThreatLevel(ThreatLevel.None, "osDrawImage");
  620. m_host.AddScriptLPS(1);
  621. drawList +="Image " +width + "," + height+ ","+ imageUrl +"; " ;
  622. return drawList;
  623. }
  624. public LSL_Vector osGetDrawStringSize(string contentType, string text, string fontName, int fontSize)
  625. {
  626. CheckThreatLevel(ThreatLevel.VeryLow, "osGetDrawStringSize");
  627. m_host.AddScriptLPS(1);
  628. LSL_Vector vec = new LSL_Vector(0,0,0);
  629. IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
  630. if (textureManager != null)
  631. {
  632. double xSize, ySize;
  633. textureManager.GetDrawStringSize(contentType, text, fontName, fontSize,
  634. out xSize, out ySize);
  635. vec.x = xSize;
  636. vec.y = ySize;
  637. }
  638. return vec;
  639. }
  640. public void osSetStateEvents(int events)
  641. {
  642. // This function is a hack. There is no reason for it's existence
  643. // anymore, since state events now work properly.
  644. // It was probably added as a crutch or debugging aid, and
  645. // should be removed
  646. //
  647. CheckThreatLevel(ThreatLevel.High, "osSetStateEvents");
  648. m_host.SetScriptEvents(m_itemID, events);
  649. }
  650. public void osSetRegionWaterHeight(double height)
  651. {
  652. CheckThreatLevel(ThreatLevel.High, "osSetRegionWaterHeight");
  653. m_host.AddScriptLPS(1);
  654. //Check to make sure that the script's owner is the estate manager/master
  655. //World.Permissions.GenericEstatePermission(
  656. if (World.Permissions.IsGod(m_host.OwnerID))
  657. {
  658. World.EventManager.TriggerRequestChangeWaterHeight((float)height);
  659. }
  660. }
  661. public double osList2Double(LSL_Types.list src, int index)
  662. {
  663. // There is really no double type in OSSL. C# and other
  664. // have one, but the current implementation of LSL_Types.list
  665. // is not allowed to contain any.
  666. // This really should be removed.
  667. //
  668. CheckThreatLevel(ThreatLevel.None, "osList2Double");
  669. m_host.AddScriptLPS(1);
  670. if (index < 0)
  671. {
  672. index = src.Length + index;
  673. }
  674. if (index >= src.Length)
  675. {
  676. return 0.0;
  677. }
  678. return Convert.ToDouble(src.Data[index]);
  679. }
  680. public void osSetParcelMediaURL(string url)
  681. {
  682. // What actually is the difference to the LL function?
  683. //
  684. CheckThreatLevel(ThreatLevel.VeryLow, "osSetParcelMediaURL");
  685. m_host.AddScriptLPS(1);
  686. ILandObject land
  687. = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
  688. if (land.landData.OwnerID != m_host.ObjectOwner)
  689. return;
  690. land.SetMediaUrl(url);
  691. }
  692. public string osGetScriptEngineName()
  693. {
  694. // This gets a "high" because knowing the engine may be used
  695. // to exploit engine-specific bugs or induce usage patterns
  696. // that trigger engine-specific failures.
  697. // Besides, public grid users aren't supposed to know.
  698. //
  699. CheckThreatLevel(ThreatLevel.High, "osGetScriptEngineName");
  700. m_host.AddScriptLPS(1);
  701. int scriptEngineNameIndex = 0;
  702. if (!String.IsNullOrEmpty(m_ScriptEngine.ScriptEngineName))
  703. {
  704. // parse off the "ScriptEngine."
  705. scriptEngineNameIndex = m_ScriptEngine.ScriptEngineName.IndexOf(".", scriptEngineNameIndex);
  706. scriptEngineNameIndex++; // get past delimiter
  707. int scriptEngineNameLength = m_ScriptEngine.ScriptEngineName.Length - scriptEngineNameIndex;
  708. // create char array then a string that is only the script engine name
  709. Char[] scriptEngineNameCharArray = m_ScriptEngine.ScriptEngineName.ToCharArray(scriptEngineNameIndex, scriptEngineNameLength);
  710. String scriptEngineName = new String(scriptEngineNameCharArray);
  711. return scriptEngineName;
  712. }
  713. else
  714. {
  715. return String.Empty;
  716. }
  717. }
  718. public string osGetSimulatorVersion()
  719. {
  720. // High because it can be used to target attacks to known weaknesses
  721. // This would allow a new class of griefer scripts that don't even
  722. // require their user to know what they are doing (see script
  723. // kiddie)
  724. //
  725. CheckThreatLevel(ThreatLevel.High,"osGetSimulatorVersion");
  726. m_host.AddScriptLPS(1);
  727. return m_ScriptEngine.World.GetSimulatorVersion();
  728. }
  729. public Hashtable osParseJSON(string JSON)
  730. {
  731. CheckThreatLevel(ThreatLevel.None, "osParseJSON");
  732. m_host.AddScriptLPS(1);
  733. // see http://www.json.org/ for more details on JSON
  734. string currentKey=null;
  735. Stack objectStack = new Stack(); // objects in JSON can be nested so we need to keep a track of this
  736. Hashtable jsondata = new Hashtable(); // the hashtable to be returned
  737. int i=0;
  738. try
  739. {
  740. // iterate through the serialised stream of tokens and store at the right depth in the hashtable
  741. // the top level hashtable may contain more nested hashtables within it each containing an objects representation
  742. for (i=0;i<JSON.Length; i++)
  743. {
  744. // m_log.Debug(""+JSON[i]);
  745. switch (JSON[i])
  746. {
  747. case '{':
  748. // create hashtable and add it to the stack or array if we are populating one, we can have a lot of nested objects in JSON
  749. Hashtable currentObject = new Hashtable();
  750. if (objectStack.Count==0) // the stack should only be empty for the first outer object
  751. {
  752. objectStack.Push(jsondata);
  753. }
  754. else if (objectStack.Peek().ToString()=="System.Collections.ArrayList")
  755. {
  756. // add it to the parent array
  757. ((ArrayList)objectStack.Peek()).Add(currentObject);
  758. objectStack.Push(currentObject);
  759. }
  760. else
  761. {
  762. // add it to the parent hashtable
  763. ((Hashtable)objectStack.Peek()).Add(currentKey,currentObject);
  764. objectStack.Push(currentObject);
  765. }
  766. // clear the key
  767. currentKey=null;
  768. break;
  769. case '}':
  770. // pop the hashtable off the stack
  771. objectStack.Pop();
  772. break;
  773. case '"':// string boundary
  774. string tokenValue="";
  775. i++; // move to next char
  776. // just loop through until the next quote mark storing the string, ignore quotes with pre-ceding \
  777. while (JSON[i]!='"')
  778. {
  779. tokenValue+=JSON[i];
  780. // handle escaped double quotes \"
  781. if (JSON[i]=='\\' && JSON[i+1]=='"')
  782. {
  783. tokenValue+=JSON[i+1];
  784. i++;
  785. }
  786. i++;
  787. }
  788. // ok we've got a string, if we've got an array on the top of the stack then we store it
  789. if (objectStack.Peek().ToString()=="System.Collections.ArrayList")
  790. {
  791. ((ArrayList)objectStack.Peek()).Add(tokenValue);
  792. }
  793. else if (currentKey==null) // no key stored and its not an array this must be a key so store it
  794. {
  795. currentKey = tokenValue;
  796. }
  797. else
  798. {
  799. // we have a key so lets store this value
  800. ((Hashtable)objectStack.Peek()).Add(currentKey,tokenValue);
  801. // now lets clear the key, we're done with it and moving on
  802. currentKey=null;
  803. }
  804. break;
  805. case ':':// key : value separator
  806. // just ignore
  807. break;
  808. case ' ':// spaces
  809. // just ignore
  810. break;
  811. case '[': // array start
  812. ArrayList currentArray = new ArrayList();
  813. if (objectStack.Peek().ToString()=="System.Collections.ArrayList")
  814. {
  815. ((ArrayList)objectStack.Peek()).Add(currentArray);
  816. }
  817. else
  818. {
  819. ((Hashtable)objectStack.Peek()).Add(currentKey,currentArray);
  820. // clear the key
  821. currentKey=null;
  822. }
  823. objectStack.Push(currentArray);
  824. break;
  825. case ',':// seperator
  826. // just ignore
  827. break;
  828. case ']'://Array end
  829. // pop the array off the stack
  830. objectStack.Pop();
  831. break;
  832. case 't': // we've found a character start not in quotes, it must be a boolean true
  833. if (objectStack.Peek().ToString()=="System.Collections.ArrayList")
  834. {
  835. ((ArrayList)objectStack.Peek()).Add(true);
  836. }
  837. else
  838. {
  839. ((Hashtable)objectStack.Peek()).Add(currentKey,true);
  840. currentKey=null;
  841. }
  842. //advance the counter to the letter 'e'
  843. i = i+3;
  844. break;
  845. case 'f': // we've found a character start not in quotes, it must be a boolean false
  846. if (objectStack.Peek().ToString()=="System.Collections.ArrayList")
  847. {
  848. ((ArrayList)objectStack.Peek()).Add(false);
  849. }
  850. else
  851. {
  852. ((Hashtable)objectStack.Peek()).Add(currentKey,false);
  853. currentKey=null;
  854. }
  855. //advance the counter to the letter 'e'
  856. i = i+4;
  857. break;
  858. case '\n':// carriage return
  859. // just ignore
  860. break;
  861. case '\r':// carriage return
  862. // just ignore
  863. break;
  864. default:
  865. // ok here we're catching all numeric types int,double,long we might want to spit these up mr accurately
  866. // but for now we'll just do them as strings
  867. string numberValue="";
  868. // just loop through until the next known marker quote mark storing the string
  869. while (JSON[i] != '"' && JSON[i] != ',' && JSON[i] != ']' && JSON[i] != '}' && JSON[i] != ' ')
  870. {
  871. numberValue+=""+JSON[i++];
  872. }
  873. i--; // we want to process this caracter that marked the end of this string in the main loop
  874. // ok we've got a string, if we've got an array on the top of the stack then we store it
  875. if (objectStack.Peek().ToString()=="System.Collections.ArrayList")
  876. {
  877. ((ArrayList)objectStack.Peek()).Add(numberValue);
  878. }
  879. else
  880. {
  881. // we have a key so lets store this value
  882. ((Hashtable)objectStack.Peek()).Add(currentKey,numberValue);
  883. // now lets clear the key, we're done with it and moving on
  884. currentKey=null;
  885. }
  886. break;
  887. }
  888. }
  889. }
  890. catch(Exception)
  891. {
  892. OSSLError("osParseJSON: The JSON string is not valid " + JSON) ;
  893. }
  894. return jsondata;
  895. }
  896. // send a message to to object identified by the given UUID, a script in the object must implement the dataserver function
  897. // the dataserver function is passed the ID of the calling function and a string message
  898. public void osMessageObject(LSL_Key objectUUID, string message)
  899. {
  900. CheckThreatLevel(ThreatLevel.Low, "osMessageObject");
  901. m_host.AddScriptLPS(1);
  902. object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) };
  903. SceneObjectPart sceneOP = World.GetSceneObjectPart(new UUID(objectUUID));
  904. m_ScriptEngine.PostObjectEvent(
  905. sceneOP.LocalId, new EventParams(
  906. "dataserver", resobj, new DetectParams[0]));
  907. }
  908. // This needs ThreatLevel high. It is an excellent griefer tool,
  909. // In a loop, it can cause asset bloat and DOS levels of asset
  910. // writes.
  911. //
  912. public void osMakeNotecard(string notecardName, LSL_Types.list contents)
  913. {
  914. CheckThreatLevel(ThreatLevel.High, "osMakeNotecard");
  915. m_host.AddScriptLPS(1);
  916. // Create new asset
  917. AssetBase asset = new AssetBase();
  918. asset.Name = notecardName;
  919. asset.Description = "Script Generated Notecard";
  920. asset.Type = 7;
  921. asset.FullID = UUID.Random();
  922. string notecardData = "";
  923. for (int i = 0; i < contents.Length; i++) {
  924. notecardData += contents.GetLSLStringItem(i) + "\n";
  925. }
  926. int textLength = notecardData.Length;
  927. notecardData = "Linden text version 2\n{\nLLEmbeddedItems version 1\n{\ncount 0\n}\nText length "
  928. + textLength.ToString() + "\n" + notecardData + "}\n";
  929. asset.Data = Encoding.ASCII.GetBytes(notecardData);
  930. World.CommsManager.AssetCache.AddAsset(asset);
  931. // Create Task Entry
  932. TaskInventoryItem taskItem=new TaskInventoryItem();
  933. taskItem.ResetIDs(m_host.UUID);
  934. taskItem.ParentID = m_host.UUID;
  935. taskItem.CreationDate = (uint)Util.UnixTimeSinceEpoch();
  936. taskItem.Name = asset.Name;
  937. taskItem.Description = asset.Description;
  938. taskItem.Type = 7;
  939. taskItem.InvType = 7;
  940. taskItem.OwnerID = m_host.OwnerID;
  941. taskItem.CreatorID = m_host.OwnerID;
  942. taskItem.BasePermissions = (uint)PermissionMask.All;
  943. taskItem.CurrentPermissions = (uint)PermissionMask.All;
  944. taskItem.EveryonePermissions = 0;
  945. taskItem.NextPermissions = (uint)PermissionMask.All;
  946. taskItem.GroupID = m_host.GroupID;
  947. taskItem.GroupPermissions = 0;
  948. taskItem.Flags = 0;
  949. taskItem.PermsGranter = UUID.Zero;
  950. taskItem.PermsMask = 0;
  951. taskItem.AssetID = asset.FullID;
  952. m_host.Inventory.AddInventoryItem(taskItem, false);
  953. }
  954. /// Threat level is Moderate because intentional abuse, for instance
  955. /// scripts that are written to be malicious only on one grid,
  956. /// for instance in a HG scenario, are a distinct possibility.
  957. ///
  958. /// Use value from the config file and return it.
  959. ///
  960. public string osGetGridNick()
  961. {
  962. CheckThreatLevel(ThreatLevel.Moderate, "osGetGridNick");
  963. m_host.AddScriptLPS(1);
  964. string nick = "hippogrid";
  965. IConfigSource config = new IniConfigSource(Application.iniFilePath);
  966. if (config.Configs["GridInfo"] != null)
  967. nick = config.Configs["GridInfo"].GetString("gridnick", nick);
  968. return nick;
  969. }
  970. public string osGetGridName()
  971. {
  972. CheckThreatLevel(ThreatLevel.Moderate, "osGetGridName");
  973. m_host.AddScriptLPS(1);
  974. string name = "the lost continent of hippo";
  975. IConfigSource config = new IniConfigSource(Application.iniFilePath);
  976. if (config.Configs["GridInfo"] != null)
  977. name = config.Configs["GridInfo"].GetString("gridname", name);
  978. return name;
  979. }
  980. public string osGetGridLoginURI()
  981. {
  982. CheckThreatLevel(ThreatLevel.Moderate, "osGetGridLoginURI");
  983. m_host.AddScriptLPS(1);
  984. string loginURI = "http://127.0.0.1:9000/";
  985. IConfigSource config = new IniConfigSource(Application.iniFilePath);
  986. if (config.Configs["GridInfo"] != null)
  987. loginURI = config.Configs["GridInfo"].GetString("login", loginURI);
  988. return loginURI;
  989. }
  990. public LSL_String osFormatString(string str, LSL_List strings)
  991. {
  992. CheckThreatLevel(ThreatLevel.Low, "osFormatString");
  993. m_host.AddScriptLPS(1);
  994. return String.Format(str, strings.Data);
  995. }
  996. public LSL_List osMatchString(string src, string pattern, int start)
  997. {
  998. CheckThreatLevel(ThreatLevel.High, "osMatchString");
  999. m_host.AddScriptLPS(1);
  1000. LSL_List result = new LSL_List();
  1001. // Normalize indices (if negative).
  1002. // After normlaization they may still be
  1003. // negative, but that is now relative to
  1004. // the start, rather than the end, of the
  1005. // sequence.
  1006. if (start < 0)
  1007. {
  1008. start = src.Length + start;
  1009. }
  1010. if (start < 0 || start >= src.Length)
  1011. {
  1012. return result; // empty list
  1013. }
  1014. // Find matches beginning at start position
  1015. Regex matcher = new Regex(pattern);
  1016. Match match = matcher.Match(src, start);
  1017. if (match.Success)
  1018. {
  1019. foreach (System.Text.RegularExpressions.Group g in match.Groups)
  1020. {
  1021. if (g.Success)
  1022. {
  1023. result.Add(g.Value);
  1024. result.Add(g.Index);
  1025. }
  1026. }
  1027. }
  1028. return result;
  1029. }
  1030. }
  1031. }