Util.cs 37 KB

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