PageRenderTime 56ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/Aurora/Framework/Utilities/Util.cs

https://bitbucket.org/VirtualReality/async-sim-testing
C# | 3042 lines | 2328 code | 354 blank | 360 comment | 395 complexity | d4de62d4428e5e099577b3a9324ffbd4 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (c) Contributors, http://aurora-sim.org/, 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 Aurora-Sim 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 Amib.Threading;
  28. using Aurora.Framework.ConsoleFramework;
  29. using Aurora.Framework.Modules;
  30. using Nini.Config;
  31. using OpenMetaverse;
  32. using OpenMetaverse.StructuredData;
  33. using ProtoBuf;
  34. using ProtoBuf.Meta;
  35. using System;
  36. using System.Collections;
  37. using System.Collections.Generic;
  38. using System.Data;
  39. using System.Diagnostics;
  40. using System.Globalization;
  41. using System.IO;
  42. using System.IO.Compression;
  43. using System.Linq;
  44. using System.Net;
  45. using System.Net.NetworkInformation;
  46. using System.Net.Sockets;
  47. using System.Reflection;
  48. using System.Reflection.Emit;
  49. using System.Runtime.Serialization;
  50. using System.Runtime.Serialization.Formatters.Binary;
  51. using System.Security.Cryptography;
  52. using System.Text;
  53. using System.Text.RegularExpressions;
  54. using System.Threading;
  55. using System.Windows.Forms;
  56. using System.Xml;
  57. using ReaderWriterLockSlim = System.Threading.ReaderWriterLockSlim;
  58. namespace Aurora.Framework.Utilities
  59. {
  60. /// <summary>
  61. /// The method used by Util.FireAndForget for asynchronously firing events
  62. /// </summary>
  63. public enum FireAndForgetMethod
  64. {
  65. UnsafeQueueUserWorkItem,
  66. QueueUserWorkItem,
  67. BeginInvoke,
  68. SmartThreadPool,
  69. Thread
  70. }
  71. public enum RuntimeEnvironment
  72. {
  73. NET,
  74. WinMono,
  75. Mono
  76. }
  77. /// <summary>
  78. /// Miscellaneous utility functions
  79. /// </summary>
  80. public class Util
  81. {
  82. private static uint nextXferID = 5000;
  83. private static readonly Random randomClass = new Random();
  84. // Get a list of invalid file characters (OS dependent)
  85. private static readonly string regexInvalidFileChars = "[" + new String(Path.GetInvalidFileNameChars()) + "]";
  86. private static readonly string regexInvalidPathChars = "[" + new String(Path.GetInvalidPathChars()) + "]";
  87. private static readonly object XferLock = new object();
  88. /// <summary>
  89. /// Thread pool used for Util.FireAndForget if
  90. /// FireAndForgetMethod.SmartThreadPool is used
  91. /// </summary>
  92. private static SmartThreadPool m_ThreadPool;
  93. private static volatile bool m_threadPoolRunning;
  94. // Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC.
  95. public static readonly DateTime UnixEpoch =
  96. DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).
  97. ToUniversalTime();
  98. public static readonly Regex UUIDPattern
  99. = new Regex("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$");
  100. public static FireAndForgetMethod FireAndForgetMethod = FireAndForgetMethod.SmartThreadPool;
  101. static Util()
  102. {
  103. RuntimeTypeModel.Default.Add(typeof (UUID), false)
  104. .SetSurrogate(typeof (UUIDSurrogate));
  105. RuntimeTypeModel.Default.Add(typeof (IPEndPoint), false)
  106. .SetSurrogate(typeof (IPEndPointSurrogate));
  107. RuntimeTypeModel.Default.Add(typeof (OSD), false)
  108. .SetSurrogate(typeof (OSDSurrogate));
  109. RuntimeTypeModel.Default.Add(typeof (OSDMap), false)
  110. .SetSurrogate(typeof (OSDMapSurrogate));
  111. RuntimeTypeModel.Default.Add(typeof (Vector3), false)
  112. .SetSurrogate(typeof (Vector3Surrogate));
  113. RuntimeTypeModel.Default.Add(typeof (Quaternion), false)
  114. .SetSurrogate(typeof (QuaternionSurrogate));
  115. RuntimeTypeModel.Default.Add(typeof (ParcelManager.ParcelAccessEntry), false)
  116. .SetSurrogate(typeof (ParcelAccessEntrySurrogate));
  117. RuntimeTypeModel.Default.Add(typeof (MediaEntry), false)
  118. .SetSurrogate(typeof (MediaEntrySurrogate));
  119. RuntimeTypeModel.Default.Add(typeof (System.Drawing.Color), false)
  120. .SetSurrogate(typeof (ColorSurrogate));
  121. }
  122. #region Protobuf helpers
  123. [ProtoContract]
  124. private class UUIDSurrogate
  125. {
  126. [ProtoMember(1)] public string ID;
  127. // protobuf-net wants an implicit or explicit operator between the types
  128. public static implicit operator UUID(UUIDSurrogate value)
  129. {
  130. return UUID.Parse(value.ID);
  131. }
  132. public static implicit operator UUIDSurrogate(UUID value)
  133. {
  134. return new UUIDSurrogate
  135. {
  136. ID = value.ToString()
  137. };
  138. }
  139. }
  140. [ProtoContract]
  141. private class Vector3Surrogate
  142. {
  143. [ProtoMember(1)] public float X;
  144. [ProtoMember(2)] public float Y;
  145. [ProtoMember(3)] public float Z;
  146. // protobuf-net wants an implicit or explicit operator between the types
  147. public static implicit operator Vector3(Vector3Surrogate value)
  148. {
  149. return new Vector3(value.X, value.Y, value.Z);
  150. }
  151. public static implicit operator Vector3Surrogate(Vector3 value)
  152. {
  153. return new Vector3Surrogate()
  154. {
  155. X = value.X,
  156. Y = value.Y,
  157. Z = value.Z
  158. };
  159. }
  160. }
  161. [ProtoContract]
  162. private class QuaternionSurrogate
  163. {
  164. [ProtoMember(1)] public float X;
  165. [ProtoMember(2)] public float Y;
  166. [ProtoMember(3)] public float Z;
  167. [ProtoMember(4)] public float W;
  168. // protobuf-net wants an implicit or explicit operator between the types
  169. public static implicit operator Quaternion(QuaternionSurrogate value)
  170. {
  171. return new Quaternion(value.X, value.Y, value.Z, value.W);
  172. }
  173. public static implicit operator QuaternionSurrogate(Quaternion value)
  174. {
  175. return new QuaternionSurrogate()
  176. {
  177. X = value.X,
  178. Y = value.Y,
  179. Z = value.Z,
  180. W = value.W
  181. };
  182. }
  183. }
  184. [ProtoContract]
  185. private class IPEndPointSurrogate
  186. {
  187. [ProtoMember(1)] public string IPAddr;
  188. [ProtoMember(2)] public int Port;
  189. // protobuf-net wants an implicit or explicit operator between the types
  190. public static implicit operator IPEndPoint(IPEndPointSurrogate value)
  191. {
  192. return value == null ? null : new IPEndPoint(IPAddress.Parse(value.IPAddr), value.Port);
  193. }
  194. public static implicit operator IPEndPointSurrogate(IPEndPoint value)
  195. {
  196. return value == null
  197. ? null
  198. : new IPEndPointSurrogate
  199. {
  200. IPAddr = value.Address.ToString(),
  201. Port = value.Port
  202. };
  203. }
  204. }
  205. [ProtoContract]
  206. private class OSDSurrogate
  207. {
  208. [ProtoMember(1)] public string str;
  209. // protobuf-net wants an implicit or explicit operator between the types
  210. public static implicit operator OSD(OSDSurrogate value)
  211. {
  212. return value.str == "" ? null : OSDParser.DeserializeJson(value.str);
  213. }
  214. public static implicit operator OSDSurrogate(OSD value)
  215. {
  216. return new OSDSurrogate
  217. {
  218. str = value == null ? "" : OSDParser.SerializeJsonString(value)
  219. };
  220. }
  221. }
  222. [ProtoContract]
  223. private class OSDMapSurrogate
  224. {
  225. [ProtoMember(1)] public string str;
  226. // protobuf-net wants an implicit or explicit operator between the types
  227. public static implicit operator OSDMap(OSDMapSurrogate value)
  228. {
  229. return value.str == "" ? null : (OSDMap) OSDParser.DeserializeJson(value.str);
  230. }
  231. public static implicit operator OSDMapSurrogate(OSDMap value)
  232. {
  233. return new OSDMapSurrogate
  234. {
  235. str = value == null ? "" : OSDParser.SerializeJsonString(value)
  236. };
  237. }
  238. }
  239. [ProtoContract]
  240. private class ParcelAccessEntrySurrogate
  241. {
  242. [ProtoMember(1)] public UUID AgentID;
  243. [ProtoMember(2)] public AccessList Flags;
  244. [ProtoMember(3)] public DateTime Time;
  245. // protobuf-net wants an implicit or explicit operator between the types
  246. public static implicit operator ParcelManager.ParcelAccessEntry(ParcelAccessEntrySurrogate value)
  247. {
  248. return new ParcelManager.ParcelAccessEntry()
  249. {
  250. AgentID = value.AgentID,
  251. Flags = value.Flags,
  252. Time = value.Time
  253. };
  254. }
  255. public static implicit operator ParcelAccessEntrySurrogate(ParcelManager.ParcelAccessEntry value)
  256. {
  257. return new ParcelAccessEntrySurrogate
  258. {
  259. AgentID = value.AgentID,
  260. Flags = value.Flags,
  261. Time = value.Time
  262. };
  263. }
  264. }
  265. [ProtoContract]
  266. private class MediaEntrySurrogate
  267. {
  268. [ProtoMember(1)] public OSD info;
  269. // protobuf-net wants an implicit or explicit operator between the types
  270. public static implicit operator MediaEntry(MediaEntrySurrogate value)
  271. {
  272. return value.info == null ? null : MediaEntry.FromOSD(value.info);
  273. }
  274. public static implicit operator MediaEntrySurrogate(MediaEntry value)
  275. {
  276. return new MediaEntrySurrogate
  277. {
  278. info = value == null ? null : value.GetOSD()
  279. };
  280. }
  281. }
  282. [ProtoContract]
  283. private class ColorSurrogate
  284. {
  285. [ProtoMember(1)] public int A;
  286. [ProtoMember(2)] public int R;
  287. [ProtoMember(3)] public int G;
  288. [ProtoMember(4)] public int B;
  289. // protobuf-net wants an implicit or explicit operator between the types
  290. public static implicit operator System.Drawing.Color(ColorSurrogate value)
  291. {
  292. return System.Drawing.Color.FromArgb(value.A, value.R, value.G, value.B);
  293. }
  294. public static implicit operator ColorSurrogate(System.Drawing.Color value)
  295. {
  296. return new ColorSurrogate
  297. {
  298. A = value.A,
  299. R = value.R,
  300. G = value.G,
  301. B = value.B
  302. };
  303. }
  304. }
  305. #endregion
  306. public static string ConvertToString(List<string> list)
  307. {
  308. StringBuilder builder = new StringBuilder();
  309. foreach (string val in list)
  310. {
  311. builder.Append(val + ",");
  312. }
  313. return builder.ToString();
  314. }
  315. public static string ConvertToString(Dictionary<string, object> list)
  316. {
  317. StringBuilder builder = new StringBuilder();
  318. foreach (var val in list)
  319. {
  320. builder.Append(val.Key + "=" + val.Value.ToString() + ",");
  321. }
  322. return builder.ToString();
  323. }
  324. //wab - Added for debugging ease
  325. public static string ConvertToString(OSDMap values, string lineStart)
  326. {
  327. if (string.IsNullOrEmpty(lineStart)) lineStart = "\t";
  328. StringBuilder builder = new StringBuilder();
  329. String[] keys = new String[values.Count];
  330. values.Keys.CopyTo(keys, 0);
  331. foreach (String key in keys)
  332. {
  333. Object val = values[key];
  334. if (val == null)
  335. builder.AppendFormat("{0}{1}=null\n", lineStart, key);
  336. else if (val is OSDMap)
  337. builder.AppendFormat("{0}{1}=...\n{2}", lineStart, key, ConvertToString((OSDMap) val, "\t\t"));
  338. else
  339. builder.AppendFormat("{0}{1}={2}\n", lineStart, key, val.ToString());
  340. }
  341. return builder.ToString();
  342. }
  343. public static List<string> ConvertToList(string listAsString)
  344. {
  345. //Do both , and " " so that it removes any annoying spaces in the string added by users
  346. List<string> value =
  347. new List<string>(listAsString.Split(new[] {","}, StringSplitOptions.RemoveEmptyEntries));
  348. return value;
  349. }
  350. public static Dictionary<string, string> ConvertToDictionary(string listAsString)
  351. {
  352. //Do both , and " " so that it removes any annoying spaces in the string added by users
  353. List<string> value =
  354. new List<string>(listAsString.Split(new[] {","}, StringSplitOptions.RemoveEmptyEntries));
  355. Dictionary<string, string> dict = new Dictionary<string, string>();
  356. foreach (var v in value)
  357. {
  358. var split = v.Split('=');
  359. dict.Add(split[0], split[1]);
  360. }
  361. return dict;
  362. }
  363. public static string BuildYMDDateString(DateTime time)
  364. {
  365. return time.Year + "-" + time.Month + "-" + time.Day;
  366. }
  367. /// <summary>
  368. /// Gets the name of the directory where the current running executable
  369. /// is located
  370. /// </summary>
  371. /// <returns>
  372. /// Filesystem path to the directory containing the current
  373. /// executable
  374. /// </returns>
  375. public static string ExecutingDirectory()
  376. {
  377. return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
  378. }
  379. /// <summary>
  380. /// Copy data from one stream to another, leaving the read position of both streams at the beginning.
  381. /// </summary>
  382. /// <param name='inputStream'>
  383. /// Input stream. Must be seekable.
  384. /// </param>
  385. /// <exception cref='ArgumentException'>
  386. /// Thrown if the input stream is not seekable.
  387. /// </exception>
  388. public static Stream Copy(Stream inputStream)
  389. {
  390. if (!inputStream.CanSeek)
  391. throw new ArgumentException("Util.Copy(Stream inputStream) must receive an inputStream that can seek");
  392. const int readSize = 256;
  393. byte[] buffer = new byte[readSize];
  394. MemoryStream ms = new MemoryStream();
  395. int count = inputStream.Read(buffer, 0, readSize);
  396. while (count > 0)
  397. {
  398. ms.Write(buffer, 0, count);
  399. count = inputStream.Read(buffer, 0, readSize);
  400. }
  401. ms.Position = 0;
  402. inputStream.Position = 0;
  403. return ms;
  404. }
  405. /// <summary>
  406. /// Linear interpolates B&lt;-&gt;C using percent A
  407. /// </summary>
  408. /// <param name="a"></param>
  409. /// <param name="b"></param>
  410. /// <param name="c"></param>
  411. /// <returns></returns>
  412. public static double lerp(double a, double b, double c)
  413. {
  414. return (b*a) + (c*(1 - a));
  415. }
  416. /// <summary>
  417. /// Bilinear Interpolate, see Lerp but for 2D using 'percents' X & Y.
  418. /// Layout:
  419. /// A B
  420. /// C D
  421. /// A&lt;-&gt;C = Y
  422. /// C&lt;-&gt;D = X
  423. /// </summary>
  424. /// <param name="x"></param>
  425. /// <param name="y"></param>
  426. /// <param name="a"></param>
  427. /// <param name="b"></param>
  428. /// <param name="c"></param>
  429. /// <param name="d"></param>
  430. /// <returns></returns>
  431. public static double lerp2D(double x, double y, double a, double b, double c, double d)
  432. {
  433. return lerp(y, lerp(x, a, b), lerp(x, c, d));
  434. }
  435. public static Encoding UTF8 = Encoding.UTF8;
  436. /// <value>
  437. /// Well known UUID for the blank texture used in the Linden SL viewer version 1.20 (and hopefully onwards)
  438. /// </value>
  439. public static UUID BLANK_TEXTURE_UUID = new UUID("5748decc-f629-461c-9a36-a35a221fe21f");
  440. #region Vector Equations
  441. /// <summary>
  442. /// Get the distance between two 3d vectors
  443. /// </summary>
  444. /// <param name="a">A 3d vector</param>
  445. /// <param name="b">A 3d vector</param>
  446. /// <returns>The distance between the two vectors</returns>
  447. public static double GetDistanceTo(Vector3 a, Vector3 b)
  448. {
  449. float dx = a.X - b.X;
  450. float dy = a.Y - b.Y;
  451. float dz = a.Z - b.Z;
  452. return Math.Sqrt(dx*dx + dy*dy + dz*dz);
  453. }
  454. /// <summary>
  455. /// Get the distance between two 3d vectors (excluding Z)
  456. /// </summary>
  457. /// <param name="a">A 3d vector</param>
  458. /// <param name="b">A 3d vector</param>
  459. /// <returns>The distance between the two vectors</returns>
  460. public static double GetFlatDistanceTo(Vector3 a, Vector3 b)
  461. {
  462. float dx = a.X - b.X;
  463. float dy = a.Y - b.Y;
  464. return Math.Sqrt(dx*dx + dy*dy);
  465. }
  466. /// <summary>
  467. /// Returns true if the distance beween A and B is less than amount. Significantly faster than GetDistanceTo since it eliminates the Sqrt.
  468. /// </summary>
  469. /// <param name="a"></param>
  470. /// <param name="b"></param>
  471. /// <param name="amount"></param>
  472. /// <returns></returns>
  473. public static bool DistanceLessThan(Vector3 a, Vector3 b, double amount)
  474. {
  475. float dx = a.X - b.X;
  476. float dy = a.Y - b.Y;
  477. float dz = a.Z - b.Z;
  478. return (dx*dx + dy*dy + dz*dz) < (amount*amount);
  479. }
  480. /// <summary>
  481. /// Get the magnitude of a 3d vector
  482. /// </summary>
  483. /// <param name="a">A 3d vector</param>
  484. /// <returns>The magnitude of the vector</returns>
  485. public static double GetMagnitude(Vector3 a)
  486. {
  487. return Math.Sqrt((a.X*a.X) + (a.Y*a.Y) + (a.Z*a.Z));
  488. }
  489. /// <summary>
  490. /// Get a normalized form of a 3d vector
  491. /// The vector paramater cannot be &lt;0,0,0&gt;
  492. /// </summary>
  493. /// <param name="a">A 3d vector</param>
  494. /// <returns>A new vector which is normalized form of the vector</returns>
  495. public static Vector3 GetNormalizedVector(Vector3 a)
  496. {
  497. if (IsZeroVector(a))
  498. throw new ArgumentException("Vector paramater cannot be a zero vector.");
  499. float Mag = (float) GetMagnitude(a);
  500. return new Vector3(a.X/Mag, a.Y/Mag, a.Z/Mag);
  501. }
  502. /// <summary>
  503. /// Returns if a vector is a zero vector (has all zero components)
  504. /// </summary>
  505. /// <returns></returns>
  506. public static bool IsZeroVector(Vector3 v)
  507. {
  508. if (v.X == 0 && v.Y == 0 && v.Z == 0)
  509. {
  510. return true;
  511. }
  512. return false;
  513. }
  514. # endregion
  515. public static Quaternion Axes2Rot(Vector3 fwd, Vector3 left, Vector3 up)
  516. {
  517. float s;
  518. float tr = (float) (fwd.X + left.Y + up.Z + 1.0);
  519. if (tr >= 1.0)
  520. {
  521. s = (float) (0.5/Math.Sqrt(tr));
  522. return new Quaternion(
  523. (left.Z - up.Y)*s,
  524. (up.X - fwd.Z)*s,
  525. (fwd.Y - left.X)*s,
  526. (float) 0.25/s);
  527. }
  528. else
  529. {
  530. float max = (left.Y > up.Z) ? left.Y : up.Z;
  531. if (max < fwd.X)
  532. {
  533. s = (float) (Math.Sqrt(fwd.X - (left.Y + up.Z) + 1.0));
  534. float x = (float) (s*0.5);
  535. s = (float) (0.5/s);
  536. return new Quaternion(
  537. x,
  538. (fwd.Y + left.X)*s,
  539. (up.X + fwd.Z)*s,
  540. (left.Z - up.Y)*s);
  541. }
  542. else if (max == left.Y)
  543. {
  544. s = (float) (Math.Sqrt(left.Y - (up.Z + fwd.X) + 1.0));
  545. float y = (float) (s*0.5);
  546. s = (float) (0.5/s);
  547. return new Quaternion(
  548. (fwd.Y + left.X)*s,
  549. y,
  550. (left.Z + up.Y)*s,
  551. (up.X - fwd.Z)*s);
  552. }
  553. else
  554. {
  555. s = (float) (Math.Sqrt(up.Z - (fwd.X + left.Y) + 1.0));
  556. float z = (float) (s*0.5);
  557. s = (float) (0.5/s);
  558. return new Quaternion(
  559. (up.X + fwd.Z)*s,
  560. (left.Z + up.Y)*s,
  561. z,
  562. (fwd.Y - left.X)*s);
  563. }
  564. }
  565. }
  566. public static Random RandomClass
  567. {
  568. get { return randomClass; }
  569. }
  570. public static T Clamp<T>(T x, T min, T max)
  571. where T : IComparable<T>
  572. {
  573. return x.CompareTo(max) > 0
  574. ? max
  575. : x.CompareTo(min) < 0
  576. ? min
  577. : x;
  578. }
  579. public static uint GetNextXferID()
  580. {
  581. uint id = 0;
  582. lock (XferLock)
  583. {
  584. id = nextXferID;
  585. nextXferID++;
  586. }
  587. return id;
  588. }
  589. /// <summary>
  590. /// Debug utility function to convert unbroken strings of XML into something human readable for occasional debugging purposes.
  591. /// Please don't delete me even if I appear currently unused!
  592. /// </summary>
  593. /// <param name="rawXml"></param>
  594. /// <returns></returns>
  595. public static string GetFormattedXml(string rawXml)
  596. {
  597. XmlDocument xd = new XmlDocument();
  598. xd.LoadXml(rawXml);
  599. StringBuilder sb = new StringBuilder();
  600. StringWriter sw = new StringWriter(sb);
  601. XmlTextWriter xtw = new XmlTextWriter(sw) {Formatting = Formatting.Indented};
  602. try
  603. {
  604. xd.WriteTo(xtw);
  605. }
  606. finally
  607. {
  608. xtw.Close();
  609. }
  610. return sb.ToString();
  611. }
  612. public static bool IsEnvironmentSupported(ref string reason)
  613. {
  614. // Must have .NET 2.0 (Generics / libsl)
  615. if (Environment.Version.Major < 2)
  616. {
  617. reason = ".NET 1.0/1.1 lacks components that are used by Aurora";
  618. return false;
  619. }
  620. // Windows 95/98/ME are unsupported
  621. if (Environment.OSVersion.Platform == PlatformID.Win32Windows ||
  622. Environment.OSVersion.Platform == PlatformID.Win32S ||
  623. Environment.OSVersion.Platform == PlatformID.WinCE)
  624. {
  625. reason = "Windows 95/98/ME will not run Aurora";
  626. return false;
  627. }
  628. // Windows 2000 / Pre-SP2 XP
  629. if (Environment.OSVersion.Platform == PlatformID.Win32NT &&
  630. Environment.OSVersion.Version.Major == 5 &&
  631. Environment.OSVersion.Version.Minor == 0)
  632. {
  633. reason = "Please update to Windows XP Service Pack 2 or Server 2003 with .NET 3.5 installed";
  634. return false;
  635. }
  636. if (Environment.OSVersion.Platform == PlatformID.Win32NT &&
  637. Environment.Version.Major < 4 &&
  638. Environment.Version.Build < 50727) //.net 3.5
  639. {
  640. reason = ".NET versions before 3.5 lack components that are used by Aurora";
  641. return false;
  642. }
  643. return true;
  644. }
  645. public static bool IsLinux
  646. {
  647. get
  648. {
  649. int p = (int) Environment.OSVersion.Platform;
  650. return (p == 4) || (p == 6) || (p == 128);
  651. }
  652. }
  653. public static int UnixTimeSinceEpoch()
  654. {
  655. return ToUnixTime(DateTime.UtcNow);
  656. }
  657. public static int ToUnixTime(DateTime stamp)
  658. {
  659. TimeSpan t = stamp.ToUniversalTime() - UnixEpoch;
  660. return (int) t.TotalSeconds;
  661. }
  662. public static DateTime ToDateTime(ulong seconds)
  663. {
  664. DateTime epoch = UnixEpoch;
  665. return epoch.AddSeconds(seconds);
  666. }
  667. public static DateTime ToDateTime(int seconds)
  668. {
  669. DateTime epoch = UnixEpoch;
  670. return epoch.AddSeconds(seconds);
  671. }
  672. /// <summary>
  673. /// Return an md5 hash of the given string
  674. /// </summary>
  675. /// <param name="data"></param>
  676. /// <returns></returns>
  677. public static string Md5Hash(string data)
  678. {
  679. byte[] dataMd5 = ComputeMD5Hash(data);
  680. StringBuilder sb = new StringBuilder();
  681. foreach (byte t in dataMd5)
  682. sb.AppendFormat("{0:x2}", t);
  683. return sb.ToString();
  684. }
  685. private static byte[] ComputeMD5Hash(string data)
  686. {
  687. MD5 md5 = MD5.Create();
  688. return md5.ComputeHash(Encoding.Default.GetBytes(data));
  689. }
  690. /// <summary>
  691. /// Return an SHA1 hash of the given string
  692. /// </summary>
  693. /// <param name="data"></param>
  694. /// <returns></returns>
  695. public static string SHA1Hash(string data)
  696. {
  697. byte[] hash = ComputeSHA1Hash(data);
  698. return BitConverter.ToString(hash).Replace("-", String.Empty);
  699. }
  700. private static byte[] ComputeSHA1Hash(string src)
  701. {
  702. SHA1CryptoServiceProvider SHA1 = new SHA1CryptoServiceProvider();
  703. return SHA1.ComputeHash(Encoding.Default.GetBytes(src));
  704. }
  705. public static int fast_distance2d(int x, int y)
  706. {
  707. x = Math.Abs(x);
  708. y = Math.Abs(y);
  709. int min = Math.Min(x, y);
  710. return (x + y - (min >> 1) - (min >> 2) + (min >> 4));
  711. }
  712. // Inclusive, within range test (true if equal to the endpoints)
  713. public static bool InRange<T>(T x, T min, T max)
  714. where T : IComparable<T>
  715. {
  716. return x.CompareTo(max) <= 0 && x.CompareTo(min) >= 0;
  717. }
  718. // Clamp the maximum magnitude of a vector
  719. public static Vector3 ClampV(Vector3 x, float max)
  720. {
  721. Vector3 ret = x;
  722. float lenSq = x.LengthSquared();
  723. if (lenSq > (max*max))
  724. {
  725. x = x/x.Length()*max;
  726. }
  727. return x;
  728. }
  729. public static string FieldToString(byte[] bytes)
  730. {
  731. return FieldToString(bytes, String.Empty);
  732. }
  733. /// <summary>
  734. /// Convert a variable length field (byte array) to a string, with a
  735. /// field name prepended to each line of the output
  736. /// </summary>
  737. /// <remarks>
  738. /// If the byte array has unprintable characters in it, a
  739. /// hex dump will be put in the string instead
  740. /// </remarks>
  741. /// <param name="bytes">The byte array to convert to a string</param>
  742. /// <param name="fieldName">A field name to prepend to each line of output</param>
  743. /// <returns>
  744. /// An ASCII string or a string containing a hex dump, minus
  745. /// the null terminator
  746. /// </returns>
  747. public static string FieldToString(byte[] bytes, string fieldName)
  748. {
  749. // Check for a common case
  750. if (bytes.Length == 0) return String.Empty;
  751. StringBuilder output = new StringBuilder();
  752. bool printable = bytes.All(t => (t >= 0x20 && t <= 0x7E) || t == 0x09 || t == 0x0D || t == 0x0A || t == 0x00);
  753. if (printable)
  754. {
  755. if (fieldName.Length > 0)
  756. {
  757. output.Append(fieldName);
  758. output.Append(": ");
  759. }
  760. output.Append(CleanString(UTF8.GetString(bytes, 0, bytes.Length - 1)));
  761. }
  762. else
  763. {
  764. for (int i = 0; i < bytes.Length; i += 16)
  765. {
  766. if (i != 0)
  767. output.Append(Environment.NewLine);
  768. if (fieldName.Length > 0)
  769. {
  770. output.Append(fieldName);
  771. output.Append(": ");
  772. }
  773. for (int j = 0; j < 16; j++)
  774. {
  775. output.Append((i + j) < bytes.Length ? String.Format("{0:X2} ", bytes[i + j]) : " ");
  776. }
  777. for (int j = 0; j < 16 && (i + j) < bytes.Length; j++)
  778. {
  779. if (bytes[i + j] >= 0x20 && bytes[i + j] < 0x7E)
  780. output.Append((char) bytes[i + j]);
  781. else
  782. output.Append(".");
  783. }
  784. }
  785. }
  786. return output.ToString();
  787. }
  788. /// <summary>
  789. /// Removes all invalid path chars (OS dependent)
  790. /// </summary>
  791. /// <param name="path">path</param>
  792. /// <returns>safe path</returns>
  793. public static string safePath(string path)
  794. {
  795. return Regex.Replace(path, regexInvalidPathChars, String.Empty);
  796. }
  797. /// <summary>
  798. /// Removes all invalid filename chars (OS dependent)
  799. /// </summary>
  800. /// <param name="filename">filename</param>
  801. /// <returns>safe filename</returns>
  802. public static string safeFileName(string filename)
  803. {
  804. return Regex.Replace(filename, regexInvalidFileChars, String.Empty);
  805. }
  806. //
  807. // directory locations
  808. //
  809. public static string homeDir()
  810. {
  811. string temp;
  812. // string personal=(Environment.GetFolderPath(Environment.SpecialFolder.Personal));
  813. // temp = Path.Combine(personal,".OpenSim");
  814. temp = ".";
  815. return temp;
  816. }
  817. public static string configDir()
  818. {
  819. return ".";
  820. }
  821. public static string dataDir()
  822. {
  823. return ".";
  824. }
  825. public static string logDir()
  826. {
  827. return ".";
  828. }
  829. // From: http://coercedcode.blogspot.com/2008/03/c-generate-unique-filenames-within.html
  830. public static string GetUniqueFilename(string FileName)
  831. {
  832. int count = 0;
  833. string Name;
  834. if (File.Exists(FileName))
  835. {
  836. FileInfo f = new FileInfo(FileName);
  837. Name = !String.IsNullOrEmpty(f.Extension)
  838. ? f.FullName.Substring(0, f.FullName.LastIndexOf('.'))
  839. : f.FullName;
  840. while (File.Exists(FileName))
  841. {
  842. count++;
  843. FileName = Name + count + f.Extension;
  844. }
  845. }
  846. return FileName;
  847. }
  848. // Nini (config) related Methods
  849. public static IConfigSource ConvertDataRowToXMLConfig(DataRow row, string fileName)
  850. {
  851. if (!File.Exists(fileName))
  852. {
  853. //create new file
  854. }
  855. XmlConfigSource config = new XmlConfigSource(fileName);
  856. AddDataRowToConfig(config, row);
  857. config.Save();
  858. return config;
  859. }
  860. public static void AddDataRowToConfig(IConfigSource config, DataRow row)
  861. {
  862. config.Configs.Add((string) row[0]);
  863. for (int i = 0; i < row.Table.Columns.Count; i++)
  864. {
  865. config.Configs[(string) row[0]].Set(row.Table.Columns[i].ColumnName, row[i]);
  866. }
  867. }
  868. public static float Clip(float x, float min, float max)
  869. {
  870. return Math.Min(Math.Max(x, min), max);
  871. }
  872. public static int Clip(int x, int min, int max)
  873. {
  874. return Math.Min(Math.Max(x, min), max);
  875. }
  876. /// <summary>
  877. /// Convert an UUID to a raw uuid string. Right now this is a string without hyphens.
  878. /// </summary>
  879. /// <param name="UUID"></param>
  880. /// <returns></returns>
  881. public static String ToRawUuidString(UUID UUID)
  882. {
  883. return UUID.Guid.ToString("n");
  884. }
  885. public static string CleanString(string input)
  886. {
  887. if (input.Length == 0)
  888. return input;
  889. int clip = input.Length;
  890. // Test for ++ string terminator
  891. int pos = input.IndexOf("\0");
  892. if (pos != -1 && pos < clip)
  893. clip = pos;
  894. // Test for CR
  895. pos = input.IndexOf("\r");
  896. if (pos != -1 && pos < clip)
  897. clip = pos;
  898. // Test for LF
  899. pos = input.IndexOf("\n");
  900. if (pos != -1 && pos < clip)
  901. clip = pos;
  902. // Truncate string before first end-of-line character found
  903. return input.Substring(0, clip);
  904. }
  905. /// <summary>
  906. /// returns the contents of /etc/issue on Unix Systems
  907. /// Use this for where it's absolutely necessary to implement platform specific stuff
  908. /// </summary>
  909. /// <returns></returns>
  910. public static string ReadEtcIssue()
  911. {
  912. try
  913. {
  914. StreamReader sr = new StreamReader("/etc/issue.net");
  915. string issue = sr.ReadToEnd();
  916. sr.Close();
  917. return issue;
  918. }
  919. catch (Exception)
  920. {
  921. return "";
  922. }
  923. }
  924. public static void SerializeToFile(string filename, Object obj)
  925. {
  926. IFormatter formatter = new BinaryFormatter();
  927. Stream stream = null;
  928. try
  929. {
  930. stream = new FileStream(
  931. filename, FileMode.Create,
  932. FileAccess.Write, FileShare.None);
  933. formatter.Serialize(stream, obj);
  934. }
  935. catch (Exception e)
  936. {
  937. MainConsole.Instance.Error(e.ToString());
  938. }
  939. finally
  940. {
  941. if (stream != null)
  942. {
  943. stream.Close();
  944. }
  945. }
  946. }
  947. public static Object DeserializeFromFile(string filename)
  948. {
  949. IFormatter formatter = new BinaryFormatter();
  950. Stream stream = null;
  951. Object ret = null;
  952. try
  953. {
  954. stream = new FileStream(
  955. filename, FileMode.Open,
  956. FileAccess.Read, FileShare.None);
  957. ret = formatter.Deserialize(stream);
  958. }
  959. catch (Exception e)
  960. {
  961. MainConsole.Instance.Error(e.ToString());
  962. }
  963. finally
  964. {
  965. if (stream != null)
  966. {
  967. stream.Close();
  968. }
  969. }
  970. return ret;
  971. }
  972. public static void Compress7ZipFile(string path, string destination)
  973. {
  974. ProcessStartInfo p = new ProcessStartInfo();
  975. string pa = Path.GetDirectoryName(Assembly.GetAssembly(typeof (Util)).CodeBase);
  976. if (pa != null)
  977. {
  978. p.FileName = Path.Combine(pa, "7za.exe");
  979. p.Arguments = "a -y -tgzip \"" + destination + "\" \"" + path + "\" -mx=9";
  980. p.WindowStyle = ProcessWindowStyle.Hidden;
  981. Process x = Process.Start(p);
  982. x.WaitForExit();
  983. }
  984. }
  985. public static void UnCompress7ZipFile(string path, string destination)
  986. {
  987. ProcessStartInfo p = new ProcessStartInfo();
  988. string pa = Path.GetDirectoryName(Assembly.GetAssembly(typeof (Util)).CodeBase);
  989. if (pa != null)
  990. {
  991. p.FileName = Path.Combine(pa, "7za.exe");
  992. p.Arguments = "e -y \"" + path + "\" -o\"" + destination + "\" -mx=9";
  993. p.WindowStyle = ProcessWindowStyle.Hidden;
  994. Process x = Process.Start(p);
  995. x.WaitForExit();
  996. }
  997. }
  998. public static string Compress(string text)
  999. {
  1000. byte[] buffer = UTF8.GetBytes(text);
  1001. MemoryStream memory = new MemoryStream();
  1002. using (GZipStream compressor = new GZipStream(memory, CompressionMode.Compress, true))
  1003. {
  1004. compressor.Write(buffer, 0, buffer.Length);
  1005. }
  1006. memory.Position = 0;
  1007. byte[] compressed = new byte[memory.Length];
  1008. memory.Read(compressed, 0, compressed.Length);
  1009. byte[] compressedBuffer = new byte[compressed.Length + 4];
  1010. Buffer.BlockCopy(compressed, 0, compressedBuffer, 4, compressed.Length);
  1011. Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, compressedBuffer, 0, 4);
  1012. return Convert.ToBase64String(compressedBuffer);
  1013. }
  1014. public static byte[] CompressBytes(byte[] buffer)
  1015. {
  1016. MemoryStream memory = new MemoryStream();
  1017. using (GZipStream compressor = new GZipStream(memory, CompressionMode.Compress, true))
  1018. {
  1019. compressor.Write(buffer, 0, buffer.Length);
  1020. }
  1021. memory.Position = 0;
  1022. byte[] compressed = new byte[memory.Length];
  1023. memory.Read(compressed, 0, compressed.Length);
  1024. byte[] compressedBuffer = new byte[compressed.Length + 4];
  1025. Buffer.BlockCopy(compressed, 0, compressedBuffer, 4, compressed.Length);
  1026. Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, compressedBuffer, 0, 4);
  1027. return compressedBuffer;
  1028. }
  1029. public static string Decompress(string compressedText)
  1030. {
  1031. byte[] compressedBuffer = Convert.FromBase64String(compressedText);
  1032. using (MemoryStream memory = new MemoryStream())
  1033. {
  1034. int msgLength = BitConverter.ToInt32(compressedBuffer, 0);
  1035. memory.Write(compressedBuffer, 4, compressedBuffer.Length - 4);
  1036. byte[] buffer = new byte[msgLength];
  1037. memory.Position = 0;
  1038. using (GZipStream decompressor = new GZipStream(memory, CompressionMode.Decompress))
  1039. {
  1040. decompressor.Read(buffer, 0, buffer.Length);
  1041. }
  1042. return UTF8.GetString(buffer);
  1043. }
  1044. }
  1045. public static Stream DecompressStream(Stream compressedStream)
  1046. {
  1047. byte[] compressedBuffer = ReadToEnd(compressedStream);
  1048. using (MemoryStream memory = new MemoryStream())
  1049. {
  1050. int msgLength = BitConverter.ToInt32(compressedBuffer, 0);
  1051. memory.Write(compressedBuffer, 4, compressedBuffer.Length - 4);
  1052. byte[] buffer = new byte[msgLength];
  1053. memory.Position = 0;
  1054. using (GZipStream decompressor = new GZipStream(memory, CompressionMode.Decompress))
  1055. {
  1056. decompressor.Read(buffer, 0, buffer.Length);
  1057. }
  1058. return new MemoryStream(buffer);
  1059. }
  1060. }
  1061. public static byte[] ReadToEnd(System.IO.Stream stream)
  1062. {
  1063. byte[] readBuffer = new byte[4096];
  1064. int totalBytesRead = 0;
  1065. int bytesRead;
  1066. while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
  1067. {
  1068. totalBytesRead += bytesRead;
  1069. if (totalBytesRead == readBuffer.Length)
  1070. {
  1071. int nextByte = stream.ReadByte();
  1072. if (nextByte != -1)
  1073. {
  1074. byte[] temp = new byte[readBuffer.Length*2];
  1075. Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
  1076. Buffer.SetByte(temp, totalBytesRead, (byte) nextByte);
  1077. readBuffer = temp;
  1078. totalBytesRead++;
  1079. }
  1080. }
  1081. }
  1082. byte[] buffer = readBuffer;
  1083. if (readBuffer.Length != totalBytesRead)
  1084. {
  1085. buffer = new byte[totalBytesRead];
  1086. Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
  1087. }
  1088. return buffer;
  1089. }
  1090. /// <summary>
  1091. /// Converts a byte array in big endian order into an ulong.
  1092. /// </summary>
  1093. /// <param name="bytes">
  1094. /// The array of bytes
  1095. /// </param>
  1096. /// <returns>
  1097. /// The extracted ulong
  1098. /// </returns>
  1099. public static ulong BytesToUInt64Big(byte[] bytes)
  1100. {
  1101. if (bytes.Length < 8) return 0;
  1102. return ((ulong) bytes[0] << 56) | ((ulong) bytes[1] << 48) | ((ulong) bytes[2] << 40) |
  1103. ((ulong) bytes[3] << 32) |
  1104. ((ulong) bytes[4] << 24) | ((ulong) bytes[5] << 16) | ((ulong) bytes[6] << 8) | bytes[7];
  1105. }
  1106. // used for RemoteParcelRequest (for "About Landmark")
  1107. public static UUID BuildFakeParcelID(ulong regionHandle, uint x, uint y)
  1108. {
  1109. byte[] bytes =
  1110. {
  1111. (byte) regionHandle, (byte) (regionHandle >> 8), (byte) (regionHandle >> 16),
  1112. (byte) (regionHandle >> 24),
  1113. (byte) (regionHandle >> 32), (byte) (regionHandle >> 40), (byte) (regionHandle >> 48),
  1114. (byte) (regionHandle << 56),
  1115. (byte) x, (byte) (x >> 8), 0, 0,
  1116. (byte) y, (byte) (y >> 8), 0, 0
  1117. };
  1118. return new UUID(bytes, 0);
  1119. }
  1120. public static UUID BuildFakeParcelID(ulong regionHandle, uint x, uint y, uint z)
  1121. {
  1122. byte[] bytes =
  1123. {
  1124. (byte) regionHandle, (byte) (regionHandle >> 8), (byte) (regionHandle >> 16),
  1125. (byte) (regionHandle >> 24),
  1126. (byte) (regionHandle >> 32), (byte) (regionHandle >> 40), (byte) (regionHandle >> 48),
  1127. (byte) (regionHandle << 56),
  1128. (byte) x, (byte) (x >> 8), (byte) z, (byte) (z >> 8),
  1129. (byte) y, (byte) (y >> 8), 0, 0
  1130. };
  1131. return new UUID(bytes, 0);
  1132. }
  1133. public static void ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y)
  1134. {
  1135. byte[] bytes = parcelID.GetBytes();
  1136. regionHandle = Utils.BytesToUInt64(bytes);
  1137. x = Utils.BytesToUInt(bytes, 8) & 0xffff;
  1138. y = Utils.BytesToUInt(bytes, 12) & 0xffff;
  1139. }
  1140. public static void ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y, out uint z)
  1141. {
  1142. byte[] bytes = parcelID.GetBytes();
  1143. regionHandle = Utils.BytesToUInt64(bytes);
  1144. x = Utils.BytesToUInt(bytes, 8) & 0xffff;
  1145. z = (Utils.BytesToUInt(bytes, 8) & 0xffff0000) >> 16;
  1146. y = Utils.BytesToUInt(bytes, 12) & 0xffff;
  1147. }
  1148. public static void FakeParcelIDToGlobalPosition(UUID parcelID, out uint x, out uint y)
  1149. {
  1150. ulong regionHandle;
  1151. uint rx, ry;
  1152. ParseFakeParcelID(parcelID, out regionHandle, out x, out y);
  1153. Utils.LongToUInts(regionHandle, out rx, out ry);
  1154. x += rx;
  1155. y += ry;
  1156. }
  1157. /// <summary>
  1158. /// Get operating system information if available. Returns only the first 45 characters of information
  1159. /// </summary>
  1160. /// <returns>
  1161. /// Operating system information. Returns an empty string if none was available.
  1162. /// </returns>
  1163. public static string GetOperatingSystemInformation()
  1164. {
  1165. string os = String.Empty;
  1166. os = Environment.OSVersion.Platform != PlatformID.Unix ? Environment.OSVersion.ToString() : ReadEtcIssue();
  1167. if (os.Length > 45)
  1168. {
  1169. os = os.Substring(0, 45);
  1170. }
  1171. return os;
  1172. }
  1173. public static string GetRuntimeInformation()
  1174. {
  1175. string ru = String.Empty;
  1176. switch (Environment.OSVersion.Platform)
  1177. {
  1178. case PlatformID.Unix:
  1179. ru = "Unix/Mono";
  1180. break;
  1181. case PlatformID.MacOSX:
  1182. ru = "OSX/Mono";
  1183. break;
  1184. default:
  1185. ru = Type.GetType("Mono.Runtime") != null ? "Win/Mono" : "Win/.NET";
  1186. break;
  1187. }
  1188. return ru;
  1189. }
  1190. public static RuntimeEnvironment GetRuntimeEnvironment()
  1191. {
  1192. switch (Environment.OSVersion.Platform)
  1193. {
  1194. case PlatformID.Unix:
  1195. return RuntimeEnvironment.Mono;
  1196. case PlatformID.MacOSX:
  1197. return RuntimeEnvironment.Mono;
  1198. default:
  1199. return Type.GetType("Mono.Runtime") != null
  1200. ? RuntimeEnvironment.WinMono
  1201. : RuntimeEnvironment.NET;
  1202. }
  1203. }
  1204. /// <summary>

Large files files are truncated, but you can click here to view the full file