Util.cs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  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.Generic;
  29. using System.Data;
  30. using System.Globalization;
  31. using System.IO;
  32. using System.IO.Compression;
  33. using System.Net;
  34. using System.Net.Sockets;
  35. using System.Reflection;
  36. using System.Runtime.Serialization;
  37. using System.Runtime.Serialization.Formatters.Binary;
  38. using System.Security.Cryptography;
  39. using System.Text;
  40. using System.Text.RegularExpressions;
  41. using System.Xml;
  42. using log4net;
  43. using Nini.Config;
  44. using Nwc.XmlRpc;
  45. using OpenMetaverse;
  46. namespace OpenSim.Framework
  47. {
  48. /// <summary>
  49. /// Miscellaneous utility functions
  50. /// </summary>
  51. public class Util
  52. {
  53. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  54. private static uint nextXferID = 5000;
  55. private static Random randomClass = new Random();
  56. // Get a list of invalid file characters (OS dependent)
  57. private static string regexInvalidFileChars = "[" + new String(Path.GetInvalidFileNameChars()) + "]";
  58. private static string regexInvalidPathChars = "[" + new String(Path.GetInvalidPathChars()) + "]";
  59. private static object XferLock = new object();
  60. // 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.
  61. private static readonly DateTime unixEpoch =
  62. DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime();
  63. public static readonly Regex UUIDPattern
  64. = 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}$");
  65. /// <value>
  66. /// Well known UUID for the blank texture used in the Linden SL viewer version 1.20 (and hopefully onwards)
  67. /// </value>
  68. public static UUID BLANK_TEXTURE_UUID = new UUID("5748decc-f629-461c-9a36-a35a221fe21f");
  69. #region Vector Equations
  70. /// <summary>
  71. /// Get the distance between two 3d vectors
  72. /// </summary>
  73. /// <param name="a">A 3d vector</param>
  74. /// <param name="b">A 3d vector</param>
  75. /// <returns>The distance between the two vectors</returns>
  76. public static double GetDistanceTo(Vector3 a, Vector3 b)
  77. {
  78. float dx = a.X - b.X;
  79. float dy = a.Y - b.Y;
  80. float dz = a.Z - b.Z;
  81. return Math.Sqrt(dx * dx + dy * dy + dz * dz);
  82. }
  83. /// <summary>
  84. /// Returns true if the distance beween A and B is less than amount. Significantly faster than GetDistanceTo since it eliminates the Sqrt.
  85. /// </summary>
  86. /// <param name="a"></param>
  87. /// <param name="b"></param>
  88. /// <param name="amount"></param>
  89. /// <returns></returns>
  90. public static bool DistanceLessThan(Vector3 a, Vector3 b, double amount)
  91. {
  92. float dx = a.X - b.X;
  93. float dy = a.Y - b.Y;
  94. float dz = a.Z - b.Z;
  95. return (dx*dx + dy*dy + dz*dz) < (amount*amount);
  96. }
  97. /// <summary>
  98. /// Get the magnitude of a 3d vector
  99. /// </summary>
  100. /// <param name="a">A 3d vector</param>
  101. /// <returns>The magnitude of the vector</returns>
  102. public static double GetMagnitude(Vector3 a)
  103. {
  104. return Math.Sqrt((a.X * a.X) + (a.Y * a.Y) + (a.Z * a.Z));
  105. }
  106. /// <summary>
  107. /// Get a normalized form of a 3d vector
  108. /// </summary>
  109. /// <param name="a">A 3d vector</param>
  110. /// <returns>A new vector which is normalized form of the vector</returns>
  111. /// <remarks>The vector paramater cannot be <0,0,0></remarks>
  112. public static Vector3 GetNormalizedVector(Vector3 a)
  113. {
  114. if (IsZeroVector(a))
  115. throw new ArgumentException("Vector paramater cannot be a zero vector.");
  116. float Mag = (float) GetMagnitude(a);
  117. return new Vector3(a.X / Mag, a.Y / Mag, a.Z / Mag);
  118. }
  119. /// <summary>
  120. /// Returns if a vector is a zero vector (has all zero components)
  121. /// </summary>
  122. /// <returns></returns>
  123. public static bool IsZeroVector(Vector3 v)
  124. {
  125. if (v.X == 0 && v.Y == 0 && v.Z == 0)
  126. {
  127. return true;
  128. }
  129. return false;
  130. }
  131. # endregion
  132. public static Quaternion Axes2Rot(Vector3 fwd, Vector3 left, Vector3 up)
  133. {
  134. float s;
  135. float tr = (float) (fwd.X + left.Y + up.Z + 1.0);
  136. if (tr >= 1.0)
  137. {
  138. s = (float) (0.5 / Math.Sqrt(tr));
  139. return new Quaternion(
  140. (left.Z - up.Y) * s,
  141. (up.X - fwd.Z) * s,
  142. (fwd.Y - left.X) * s,
  143. (float) 0.25 / s);
  144. }
  145. else
  146. {
  147. float max = (left.Y > up.Z) ? left.Y : up.Z;
  148. if (max < fwd.X)
  149. {
  150. s = (float) (Math.Sqrt(fwd.X - (left.Y + up.Z) + 1.0));
  151. float x = (float) (s * 0.5);
  152. s = (float) (0.5 / s);
  153. return new Quaternion(
  154. x,
  155. (fwd.Y + left.X) * s,
  156. (up.X + fwd.Z) * s,
  157. (left.Z - up.Y) * s);
  158. }
  159. else if (max == left.Y)
  160. {
  161. s = (float) (Math.Sqrt(left.Y - (up.Z + fwd.X) + 1.0));
  162. float y = (float) (s * 0.5);
  163. s = (float) (0.5 / s);
  164. return new Quaternion(
  165. (fwd.Y + left.X) * s,
  166. y,
  167. (left.Z + up.Y) * s,
  168. (up.X - fwd.Z) * s);
  169. }
  170. else
  171. {
  172. s = (float) (Math.Sqrt(up.Z - (fwd.X + left.Y) + 1.0));
  173. float z = (float) (s * 0.5);
  174. s = (float) (0.5 / s);
  175. return new Quaternion(
  176. (up.X + fwd.Z) * s,
  177. (left.Z + up.Y) * s,
  178. z,
  179. (fwd.Y - left.X) * s);
  180. }
  181. }
  182. }
  183. public static Random RandomClass
  184. {
  185. get { return randomClass; }
  186. }
  187. public static ulong UIntsToLong(uint X, uint Y)
  188. {
  189. return Utils.UIntsToLong(X, Y);
  190. }
  191. public static T Clamp<T>(T x, T min, T max)
  192. where T : IComparable<T>
  193. {
  194. return x.CompareTo(max) > 0 ? max :
  195. x.CompareTo(min) < 0 ? min :
  196. x;
  197. }
  198. public static uint GetNextXferID()
  199. {
  200. uint id = 0;
  201. lock (XferLock)
  202. {
  203. id = nextXferID;
  204. nextXferID++;
  205. }
  206. return id;
  207. }
  208. public static string GetFileName(string file)
  209. {
  210. // Return just the filename on UNIX platforms
  211. // TODO: this should be customisable with a prefix, but that's something to do later.
  212. if (Environment.OSVersion.Platform == PlatformID.Unix)
  213. {
  214. return file;
  215. }
  216. // Return %APPDATA%/OpenSim/file for 2K/XP/NT/2K3/VISTA
  217. // TODO: Switch this to System.Enviroment.SpecialFolders.ApplicationData
  218. if (Environment.OSVersion.Platform == PlatformID.Win32NT)
  219. {
  220. if (!Directory.Exists("%APPDATA%\\OpenSim\\"))
  221. {
  222. Directory.CreateDirectory("%APPDATA%\\OpenSim");
  223. }
  224. return "%APPDATA%\\OpenSim\\" + file;
  225. }
  226. // Catch all - covers older windows versions
  227. // (but those probably wont work anyway)
  228. return file;
  229. }
  230. /// <summary>
  231. /// Debug utility function to convert unbroken strings of XML into something human readable for occasional debugging purposes.
  232. ///
  233. /// Please don't delete me even if I appear currently unused!
  234. /// </summary>
  235. /// <param name="rawXml"></param>
  236. /// <returns></returns>
  237. public static string GetFormattedXml(string rawXml)
  238. {
  239. XmlDocument xd = new XmlDocument();
  240. xd.LoadXml(rawXml);
  241. StringBuilder sb = new StringBuilder();
  242. StringWriter sw = new StringWriter(sb);
  243. XmlTextWriter xtw = new XmlTextWriter(sw);
  244. xtw.Formatting = Formatting.Indented;
  245. try
  246. {
  247. xd.WriteTo(xtw);
  248. }
  249. finally
  250. {
  251. xtw.Close();
  252. }
  253. return sb.ToString();
  254. }
  255. public static bool IsEnvironmentSupported(ref string reason)
  256. {
  257. // Must have .NET 2.0 (Generics / libsl)
  258. if (Environment.Version.Major < 2)
  259. {
  260. reason = ".NET 1.0/1.1 lacks components that is used by OpenSim";
  261. return false;
  262. }
  263. // Windows 95/98/ME are unsupported
  264. if (Environment.OSVersion.Platform == PlatformID.Win32Windows &&
  265. Environment.OSVersion.Platform != PlatformID.Win32NT)
  266. {
  267. reason = "Windows 95/98/ME will not run OpenSim";
  268. return false;
  269. }
  270. // Windows 2000 / Pre-SP2 XP
  271. if (Environment.OSVersion.Version.Major == 5 &&
  272. Environment.OSVersion.Version.Minor == 0)
  273. {
  274. reason = "Please update to Windows XP Service Pack 2 or Server2003";
  275. return false;
  276. }
  277. return true;
  278. }
  279. public static int UnixTimeSinceEpoch()
  280. {
  281. return ToUnixTime(DateTime.UtcNow);
  282. }
  283. public static int ToUnixTime(DateTime stamp)
  284. {
  285. TimeSpan t = stamp.ToUniversalTime() - unixEpoch;
  286. return (int) t.TotalSeconds;
  287. }
  288. public static DateTime ToDateTime(ulong seconds)
  289. {
  290. DateTime epoch = unixEpoch;
  291. return epoch.AddSeconds(seconds);
  292. }
  293. public static DateTime ToDateTime(int seconds)
  294. {
  295. DateTime epoch = unixEpoch;
  296. return epoch.AddSeconds(seconds);
  297. }
  298. /// <summary>
  299. /// Return an md5 hash of the given string
  300. /// </summary>
  301. /// <param name="pass"></param>
  302. /// <returns></returns>
  303. public static string Md5Hash(string pass)
  304. {
  305. MD5 md5 = MD5CryptoServiceProvider.Create();
  306. byte[] dataMd5 = md5.ComputeHash(Encoding.Default.GetBytes(pass));
  307. StringBuilder sb = new StringBuilder();
  308. for (int i = 0; i < dataMd5.Length; i++)
  309. sb.AppendFormat("{0:x2}", dataMd5[i]);
  310. return sb.ToString();
  311. }
  312. /// <summary>
  313. /// Return an SHA1 hash of the given string
  314. /// </summary>
  315. /// <param name="src"></param>
  316. /// <returns></returns>
  317. public static string SHA1Hash(string src)
  318. {
  319. SHA1CryptoServiceProvider SHA1 = new SHA1CryptoServiceProvider();
  320. return BitConverter.ToString(SHA1.ComputeHash(Encoding.Default.GetBytes(src))).Replace("-", String.Empty);
  321. }
  322. public static int fast_distance2d(int x, int y)
  323. {
  324. x = Math.Abs(x);
  325. y = Math.Abs(y);
  326. int min = Math.Min(x, y);
  327. return (x + y - (min >> 1) - (min >> 2) + (min >> 4));
  328. }
  329. public static bool IsOutsideView(uint oldx, uint newx, uint oldy, uint newy)
  330. {
  331. // Eventually this will be a function of the draw distance / camera position too.
  332. return (((int)Math.Abs((int)(oldx - newx)) > 1) || ((int)Math.Abs((int)(oldy - newy)) > 1));
  333. }
  334. public static string FieldToString(byte[] bytes)
  335. {
  336. return FieldToString(bytes, String.Empty);
  337. }
  338. /// <summary>
  339. /// Convert a variable length field (byte array) to a string, with a
  340. /// field name prepended to each line of the output
  341. /// </summary>
  342. /// <remarks>If the byte array has unprintable characters in it, a
  343. /// hex dump will be put in the string instead</remarks>
  344. /// <param name="bytes">The byte array to convert to a string</param>
  345. /// <param name="fieldName">A field name to prepend to each line of output</param>
  346. /// <returns>An ASCII string or a string containing a hex dump, minus
  347. /// the null terminator</returns>
  348. public static string FieldToString(byte[] bytes, string fieldName)
  349. {
  350. // Check for a common case
  351. if (bytes.Length == 0) return String.Empty;
  352. StringBuilder output = new StringBuilder();
  353. bool printable = true;
  354. for (int i = 0; i < bytes.Length; ++i)
  355. {
  356. // Check if there are any unprintable characters in the array
  357. if ((bytes[i] < 0x20 || bytes[i] > 0x7E) && bytes[i] != 0x09
  358. && bytes[i] != 0x0D && bytes[i] != 0x0A && bytes[i] != 0x00)
  359. {
  360. printable = false;
  361. break;
  362. }
  363. }
  364. if (printable)
  365. {
  366. if (fieldName.Length > 0)
  367. {
  368. output.Append(fieldName);
  369. output.Append(": ");
  370. }
  371. output.Append(CleanString(UTF8Encoding.UTF8.GetString(bytes, 0, bytes.Length - 1)));
  372. }
  373. else
  374. {
  375. for (int i = 0; i < bytes.Length; i += 16)
  376. {
  377. if (i != 0)
  378. output.Append(Environment.NewLine);
  379. if (fieldName.Length > 0)
  380. {
  381. output.Append(fieldName);
  382. output.Append(": ");
  383. }
  384. for (int j = 0; j < 16; j++)
  385. {
  386. if ((i + j) < bytes.Length)
  387. output.Append(String.Format("{0:X2} ", bytes[i + j]));
  388. else
  389. output.Append(" ");
  390. }
  391. for (int j = 0; j < 16 && (i + j) < bytes.Length; j++)
  392. {
  393. if (bytes[i + j] >= 0x20 && bytes[i + j] < 0x7E)
  394. output.Append((char) bytes[i + j]);
  395. else
  396. output.Append(".");
  397. }
  398. }
  399. }
  400. return output.ToString();
  401. }
  402. /// <summary>
  403. /// Converts a URL to a IPAddress
  404. /// </summary>
  405. /// <param name="url">URL Standard Format</param>
  406. /// <returns>A resolved IP Address</returns>
  407. public static IPAddress GetHostFromURL(string url)
  408. {
  409. return GetHostFromDNS(url.Split(new char[] {'/', ':'})[3]);
  410. }
  411. /// <summary>
  412. /// Returns a IP address from a specified DNS, favouring IPv4 addresses.
  413. /// </summary>
  414. /// <param name="dnsAddress">DNS Hostname</param>
  415. /// <returns>An IP address, or null</returns>
  416. public static IPAddress GetHostFromDNS(string dnsAddress)
  417. {
  418. // Is it already a valid IP? No need to look it up.
  419. IPAddress ipa;
  420. if (IPAddress.TryParse(dnsAddress, out ipa))
  421. return ipa;
  422. IPAddress[] hosts = null;
  423. // Not an IP, lookup required
  424. try
  425. {
  426. hosts = Dns.GetHostEntry(dnsAddress).AddressList;
  427. }
  428. catch (Exception e)
  429. {
  430. m_log.ErrorFormat("[UTIL]: An error occurred while resolving {0}, {1}", dnsAddress, e);
  431. // Still going to throw the exception on for now, since this was what was happening in the first place
  432. throw e;
  433. }
  434. foreach (IPAddress host in hosts)
  435. {
  436. if (host.AddressFamily == AddressFamily.InterNetwork)
  437. {
  438. return host;
  439. }
  440. }
  441. if (hosts.Length > 0)
  442. return hosts[0];
  443. return null;
  444. }
  445. public static IPAddress GetLocalHost()
  446. {
  447. string dnsAddress = "localhost";
  448. IPAddress[] hosts = Dns.GetHostEntry(dnsAddress).AddressList;
  449. foreach (IPAddress host in hosts)
  450. {
  451. if (!IPAddress.IsLoopback(host) && host.AddressFamily == AddressFamily.InterNetwork)
  452. {
  453. return host;
  454. }
  455. }
  456. if (hosts.Length > 0)
  457. return hosts[0];
  458. return null;
  459. }
  460. /// <summary>
  461. /// Removes all invalid path chars (OS dependent)
  462. /// </summary>
  463. /// <param name="path">path</param>
  464. /// <returns>safe path</returns>
  465. public static string safePath(string path)
  466. {
  467. return Regex.Replace(path, @regexInvalidPathChars, string.Empty);
  468. }
  469. /// <summary>
  470. /// Removes all invalid filename chars (OS dependent)
  471. /// </summary>
  472. /// <param name="path">filename</param>
  473. /// <returns>safe filename</returns>
  474. public static string safeFileName(string filename)
  475. {
  476. return Regex.Replace(filename, @regexInvalidFileChars, string.Empty);
  477. ;
  478. }
  479. //
  480. // directory locations
  481. //
  482. public static string homeDir()
  483. {
  484. string temp;
  485. // string personal=(Environment.GetFolderPath(Environment.SpecialFolder.Personal));
  486. // temp = Path.Combine(personal,".OpenSim");
  487. temp = ".";
  488. return temp;
  489. }
  490. public static string assetsDir()
  491. {
  492. return Path.Combine(configDir(), "assets");
  493. }
  494. public static string inventoryDir()
  495. {
  496. return Path.Combine(configDir(), "inventory");
  497. }
  498. public static string configDir()
  499. {
  500. return ".";
  501. }
  502. public static string dataDir()
  503. {
  504. return ".";
  505. }
  506. public static string logDir()
  507. {
  508. return ".";
  509. }
  510. // From: http://coercedcode.blogspot.com/2008/03/c-generate-unique-filenames-within.html
  511. public static string GetUniqueFilename(string FileName)
  512. {
  513. int count = 0;
  514. string Name;
  515. if (File.Exists(FileName))
  516. {
  517. FileInfo f = new FileInfo(FileName);
  518. if (!string.IsNullOrEmpty(f.Extension))
  519. {
  520. Name = f.FullName.Substring(0, f.FullName.LastIndexOf('.'));
  521. }
  522. else
  523. {
  524. Name = f.FullName;
  525. }
  526. while (File.Exists(FileName))
  527. {
  528. count++;
  529. FileName = Name + count + f.Extension;
  530. }
  531. }
  532. return FileName;
  533. }
  534. // Nini (config) related Methods
  535. public static IConfigSource ConvertDataRowToXMLConfig(DataRow row, string fileName)
  536. {
  537. if (!File.Exists(fileName))
  538. {
  539. //create new file
  540. }
  541. XmlConfigSource config = new XmlConfigSource(fileName);
  542. AddDataRowToConfig(config, row);
  543. config.Save();
  544. return config;
  545. }
  546. public static void AddDataRowToConfig(IConfigSource config, DataRow row)
  547. {
  548. config.Configs.Add((string) row[0]);
  549. for (int i = 0; i < row.Table.Columns.Count; i++)
  550. {
  551. config.Configs[(string) row[0]].Set(row.Table.Columns[i].ColumnName, row[i]);
  552. }
  553. }
  554. public static float Clip(float x, float min, float max)
  555. {
  556. return Math.Min(Math.Max(x, min), max);
  557. }
  558. public static int Clip(int x, int min, int max)
  559. {
  560. return Math.Min(Math.Max(x, min), max);
  561. }
  562. /// <summary>
  563. /// Convert an UUID to a raw uuid string. Right now this is a string without hyphens.
  564. /// </summary>
  565. /// <param name="UUID"></param>
  566. /// <returns></returns>
  567. public static String ToRawUuidString(UUID UUID)
  568. {
  569. return UUID.Guid.ToString("n");
  570. }
  571. public static string CleanString(string input)
  572. {
  573. if (input.Length == 0)
  574. return input;
  575. int clip = input.Length;
  576. // Test for ++ string terminator
  577. int pos = input.IndexOf("\0");
  578. if (pos != -1 && pos < clip)
  579. clip = pos;
  580. // Test for CR
  581. pos = input.IndexOf("\r");
  582. if (pos != -1 && pos < clip)
  583. clip = pos;
  584. // Test for LF
  585. pos = input.IndexOf("\n");
  586. if (pos != -1 && pos < clip)
  587. clip = pos;
  588. // Truncate string before first end-of-line character found
  589. return input.Substring(0, clip);
  590. }
  591. /// <summary>
  592. /// returns the contents of /etc/issue on Unix Systems
  593. /// Use this for where it's absolutely necessary to implement platform specific stuff
  594. /// </summary>
  595. /// <returns></returns>
  596. public static string ReadEtcIssue()
  597. {
  598. try
  599. {
  600. StreamReader sr = new StreamReader("/etc/issue.net");
  601. string issue = sr.ReadToEnd();
  602. sr.Close();
  603. return issue;
  604. }
  605. catch (Exception)
  606. {
  607. return "";
  608. }
  609. }
  610. public static void SerializeToFile(string filename, Object obj)
  611. {
  612. IFormatter formatter = new BinaryFormatter();
  613. Stream stream = null;
  614. try
  615. {
  616. stream = new FileStream(
  617. filename, FileMode.Create,
  618. FileAccess.Write, FileShare.None);
  619. formatter.Serialize(stream, obj);
  620. }
  621. catch (Exception e)
  622. {
  623. m_log.Error(e.ToString());
  624. }
  625. finally
  626. {
  627. if (stream != null)
  628. {
  629. stream.Close();
  630. }
  631. }
  632. }
  633. public static Object DeserializeFromFile(string filename)
  634. {
  635. IFormatter formatter = new BinaryFormatter();
  636. Stream stream = null;
  637. Object ret = null;
  638. try
  639. {
  640. stream = new FileStream(
  641. filename, FileMode.Open,
  642. FileAccess.Read, FileShare.None);
  643. ret = formatter.Deserialize(stream);
  644. }
  645. catch (Exception e)
  646. {
  647. m_log.Error(e.ToString());
  648. }
  649. finally
  650. {
  651. if (stream != null)
  652. {
  653. stream.Close();
  654. }
  655. }
  656. return ret;
  657. }
  658. public static string Compress(string text)
  659. {
  660. byte[] buffer = Encoding.UTF8.GetBytes(text);
  661. MemoryStream memory = new MemoryStream();
  662. using (GZipStream compressor = new GZipStream(memory, CompressionMode.Compress, true))
  663. {
  664. compressor.Write(buffer, 0, buffer.Length);
  665. }
  666. memory.Position = 0;
  667. byte[] compressed = new byte[memory.Length];
  668. memory.Read(compressed, 0, compressed.Length);
  669. byte[] compressedBuffer = new byte[compressed.Length + 4];
  670. Buffer.BlockCopy(compressed, 0, compressedBuffer, 4, compressed.Length);
  671. Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, compressedBuffer, 0, 4);
  672. return Convert.ToBase64String(compressedBuffer);
  673. }
  674. public static string Decompress(string compressedText)
  675. {
  676. byte[] compressedBuffer = Convert.FromBase64String(compressedText);
  677. using (MemoryStream memory = new MemoryStream())
  678. {
  679. int msgLength = BitConverter.ToInt32(compressedBuffer, 0);
  680. memory.Write(compressedBuffer, 4, compressedBuffer.Length - 4);
  681. byte[] buffer = new byte[msgLength];
  682. memory.Position = 0;
  683. using (GZipStream decompressor = new GZipStream(memory, CompressionMode.Decompress))
  684. {
  685. decompressor.Read(buffer, 0, buffer.Length);
  686. }
  687. return Encoding.UTF8.GetString(buffer);
  688. }
  689. }
  690. public static XmlRpcResponse XmlRpcCommand(string url, string methodName, params object[] args)
  691. {
  692. return SendXmlRpcCommand(url, methodName, args);
  693. }
  694. public static XmlRpcResponse SendXmlRpcCommand(string url, string methodName, object[] args)
  695. {
  696. XmlRpcRequest client = new XmlRpcRequest(methodName, args);
  697. return client.Send(url, 6000);
  698. }
  699. /// <summary>
  700. /// Converts a byte array in big endian order into an ulong.
  701. /// </summary>
  702. /// <param name="bytes">
  703. /// The array of bytes
  704. /// </param>
  705. /// <returns>
  706. /// The extracted ulong
  707. /// </returns>
  708. public static ulong BytesToUInt64Big(byte[] bytes)
  709. {
  710. if (bytes.Length < 8) return 0;
  711. return ((ulong)bytes[0] << 56) | ((ulong)bytes[1] << 48) | ((ulong)bytes[2] << 40) | ((ulong)bytes[3] << 32) |
  712. ((ulong)bytes[4] << 24) | ((ulong)bytes[5] << 16) | ((ulong)bytes[6] << 8) | (ulong)bytes[7];
  713. }
  714. // used for RemoteParcelRequest (for "About Landmark")
  715. public static UUID BuildFakeParcelID(ulong regionHandle, uint x, uint y)
  716. {
  717. byte[] bytes =
  718. {
  719. (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
  720. (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56),
  721. (byte)x, (byte)(x >> 8), 0, 0,
  722. (byte)y, (byte)(y >> 8), 0, 0 };
  723. return new UUID(bytes, 0);
  724. }
  725. public static UUID BuildFakeParcelID(ulong regionHandle, uint x, uint y, uint z)
  726. {
  727. byte[] bytes =
  728. {
  729. (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
  730. (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56),
  731. (byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8),
  732. (byte)y, (byte)(y >> 8), 0, 0 };
  733. return new UUID(bytes, 0);
  734. }
  735. public static void ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y)
  736. {
  737. byte[] bytes = parcelID.GetBytes();
  738. regionHandle = Utils.BytesToUInt64(bytes);
  739. x = Utils.BytesToUInt(bytes, 8) & 0xffff;
  740. y = Utils.BytesToUInt(bytes, 12) & 0xffff;
  741. }
  742. public static void ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y, out uint z)
  743. {
  744. byte[] bytes = parcelID.GetBytes();
  745. regionHandle = Utils.BytesToUInt64(bytes);
  746. x = Utils.BytesToUInt(bytes, 8) & 0xffff;
  747. z = (Utils.BytesToUInt(bytes, 8) & 0xffff0000) >> 16;
  748. y = Utils.BytesToUInt(bytes, 12) & 0xffff;
  749. }
  750. public static void FakeParcelIDToGlobalPosition(UUID parcelID, out uint x, out uint y)
  751. {
  752. ulong regionHandle;
  753. uint rx, ry;
  754. ParseFakeParcelID(parcelID, out regionHandle, out x, out y);
  755. Utils.LongToUInts(regionHandle, out rx, out ry);
  756. x += rx;
  757. y += ry;
  758. }
  759. /// <summary>
  760. /// Get operating system information if available. Returns only the first 45 characters of information
  761. /// </summary>
  762. /// <returns>
  763. /// Operating system information. Returns an empty string if none was available.
  764. /// </returns>
  765. public static string GetOperatingSystemInformation()
  766. {
  767. string os = String.Empty;
  768. if (Environment.OSVersion.Platform != PlatformID.Unix)
  769. {
  770. os = Environment.OSVersion.ToString();
  771. }
  772. else
  773. {
  774. os = ReadEtcIssue();
  775. }
  776. if (os.Length > 45)
  777. {
  778. os = os.Substring(0, 45);
  779. }
  780. return os;
  781. }
  782. /// <summary>
  783. /// Is the given string a UUID?
  784. /// </summary>
  785. /// <param name="s"></param>
  786. /// <returns></returns>
  787. public static bool isUUID(string s)
  788. {
  789. return UUIDPattern.IsMatch(s);
  790. }
  791. public static string GetDisplayConnectionString(string connectionString)
  792. {
  793. int passPosition = 0;
  794. int passEndPosition = 0;
  795. string displayConnectionString = null;
  796. // hide the password in the connection string
  797. passPosition = connectionString.IndexOf("password", StringComparison.OrdinalIgnoreCase);
  798. passPosition = connectionString.IndexOf("=", passPosition);
  799. if (passPosition < connectionString.Length)
  800. passPosition += 1;
  801. passEndPosition = connectionString.IndexOf(";", passPosition);
  802. displayConnectionString = connectionString.Substring(0, passPosition);
  803. displayConnectionString += "***";
  804. displayConnectionString += connectionString.Substring(passEndPosition, connectionString.Length - passEndPosition);
  805. return displayConnectionString;
  806. }
  807. public static T ReadSettingsFromIniFile<T>(IConfig config, T settingsClass)
  808. {
  809. Type settingsType = settingsClass.GetType();
  810. FieldInfo[] fieldInfos = settingsType.GetFields();
  811. foreach (FieldInfo fieldInfo in fieldInfos)
  812. {
  813. if (!fieldInfo.IsStatic)
  814. {
  815. if (fieldInfo.FieldType == typeof(System.String))
  816. {
  817. fieldInfo.SetValue(settingsClass, config.Get(fieldInfo.Name, (string)fieldInfo.GetValue(settingsClass)));
  818. }
  819. else if (fieldInfo.FieldType == typeof(System.Boolean))
  820. {
  821. fieldInfo.SetValue(settingsClass, config.GetBoolean(fieldInfo.Name, (bool)fieldInfo.GetValue(settingsClass)));
  822. }
  823. else if (fieldInfo.FieldType == typeof(System.Int32))
  824. {
  825. fieldInfo.SetValue(settingsClass, config.GetInt(fieldInfo.Name, (int)fieldInfo.GetValue(settingsClass)));
  826. }
  827. else if (fieldInfo.FieldType == typeof(System.Single))
  828. {
  829. fieldInfo.SetValue(settingsClass, config.GetFloat(fieldInfo.Name, (float)fieldInfo.GetValue(settingsClass)));
  830. }
  831. else if (fieldInfo.FieldType == typeof(System.UInt32))
  832. {
  833. fieldInfo.SetValue(settingsClass, System.Convert.ToUInt32(config.Get(fieldInfo.Name, ((uint)fieldInfo.GetValue(settingsClass)).ToString())));
  834. }
  835. }
  836. }
  837. PropertyInfo[] propertyInfos = settingsType.GetProperties();
  838. foreach (PropertyInfo propInfo in propertyInfos)
  839. {
  840. if ((propInfo.CanRead) && (propInfo.CanWrite))
  841. {
  842. if (propInfo.PropertyType == typeof(System.String))
  843. {
  844. propInfo.SetValue(settingsClass, config.Get(propInfo.Name, (string)propInfo.GetValue(settingsClass, null)), null);
  845. }
  846. else if (propInfo.PropertyType == typeof(System.Boolean))
  847. {
  848. propInfo.SetValue(settingsClass, config.GetBoolean(propInfo.Name, (bool)propInfo.GetValue(settingsClass, null)), null);
  849. }
  850. else if (propInfo.PropertyType == typeof(System.Int32))
  851. {
  852. propInfo.SetValue(settingsClass, config.GetInt(propInfo.Name, (int)propInfo.GetValue(settingsClass, null)), null);
  853. }
  854. else if (propInfo.PropertyType == typeof(System.Single))
  855. {
  856. propInfo.SetValue(settingsClass, config.GetFloat(propInfo.Name, (float)propInfo.GetValue(settingsClass, null)), null);
  857. }
  858. if (propInfo.PropertyType == typeof(System.UInt32))
  859. {
  860. propInfo.SetValue(settingsClass, System.Convert.ToUInt32(config.Get(propInfo.Name, ((uint)propInfo.GetValue(settingsClass, null)).ToString())), null);
  861. }
  862. }
  863. }
  864. return settingsClass;
  865. }
  866. }
  867. }