aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework')
-rw-r--r--OpenSim/Framework/Util.cs3968
1 files changed, 2001 insertions, 1967 deletions
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index b2e5c7b..deda62a 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -1,383 +1,383 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 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 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 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Data; 31using System.Data;
32using System.Diagnostics; 32using System.Diagnostics;
33using System.Globalization; 33using System.Globalization;
34using System.IO; 34using System.IO;
35using System.IO.Compression; 35using System.IO.Compression;
36using System.Net; 36using System.Net;
37using System.Net.Sockets; 37using System.Net.Sockets;
38using System.Reflection; 38using System.Reflection;
39using System.Runtime.InteropServices; 39using System.Runtime.InteropServices;
40using System.Runtime.Serialization; 40using System.Runtime.Serialization;
41using System.Runtime.Serialization.Formatters.Binary; 41using System.Runtime.Serialization.Formatters.Binary;
42using System.Security.Cryptography; 42using System.Security.Cryptography;
43using System.Text; 43using System.Text;
44using System.Text.RegularExpressions; 44using System.Text.RegularExpressions;
45using System.Xml; 45using System.Xml;
46using System.Threading; 46using System.Threading;
47using log4net; 47using log4net;
48using Nini.Config; 48using Nini.Config;
49using Nwc.XmlRpc; 49using Nwc.XmlRpc;
50using OpenMetaverse; 50using OpenMetaverse;
51using OpenMetaverse.StructuredData; 51using OpenMetaverse.StructuredData;
52using Amib.Threading; 52using Amib.Threading;
53 53
54namespace OpenSim.Framework 54namespace OpenSim.Framework
55{ 55{
56 /// <summary> 56 /// <summary>
57 /// The method used by Util.FireAndForget for asynchronously firing events 57 /// The method used by Util.FireAndForget for asynchronously firing events
58 /// </summary> 58 /// </summary>
59 /// <remarks> 59 /// <remarks>
60 /// None is used to execute the method in the same thread that made the call. It should only be used by regression 60 /// None is used to execute the method in the same thread that made the call. It should only be used by regression
61 /// test code that relies on predictable event ordering. 61 /// test code that relies on predictable event ordering.
62 /// RegressionTest is used by regression tests. It fires the call synchronously and does not catch any exceptions. 62 /// RegressionTest is used by regression tests. It fires the call synchronously and does not catch any exceptions.
63 /// </remarks> 63 /// </remarks>
64 public enum FireAndForgetMethod 64 public enum FireAndForgetMethod
65 { 65 {
66 None, 66 None,
67 RegressionTest, 67 RegressionTest,
68 UnsafeQueueUserWorkItem, 68 UnsafeQueueUserWorkItem,
69 QueueUserWorkItem, 69 QueueUserWorkItem,
70 BeginInvoke, 70 BeginInvoke,
71 SmartThreadPool, 71 SmartThreadPool,
72 Thread, 72 Thread,
73 } 73 }
74 74
75 /// <summary> 75 /// <summary>
76 /// Miscellaneous utility functions 76 /// Miscellaneous utility functions
77 /// </summary> 77 /// </summary>
78 public class Util 78 public class Util
79 { 79 {
80 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 80 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
81 81
82 private static uint nextXferID = 5000; 82 private static uint nextXferID = 5000;
83 private static Random randomClass = new Random(); 83 private static Random randomClass = new Random();
84 84
85 // Get a list of invalid file characters (OS dependent) 85 // Get a list of invalid file characters (OS dependent)
86 private static string regexInvalidFileChars = "[" + new String(Path.GetInvalidFileNameChars()) + "]"; 86 private static string regexInvalidFileChars = "[" + new String(Path.GetInvalidFileNameChars()) + "]";
87 private static string regexInvalidPathChars = "[" + new String(Path.GetInvalidPathChars()) + "]"; 87 private static string regexInvalidPathChars = "[" + new String(Path.GetInvalidPathChars()) + "]";
88 private static object XferLock = new object(); 88 private static object XferLock = new object();
89 89
90 /// <summary> 90 /// <summary>
91 /// Thread pool used for Util.FireAndForget if FireAndForgetMethod.SmartThreadPool is used 91 /// Thread pool used for Util.FireAndForget if FireAndForgetMethod.SmartThreadPool is used
92 /// </summary> 92 /// </summary>
93 private static SmartThreadPool m_ThreadPool; 93 private static SmartThreadPool m_ThreadPool;
94 94
95 // 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 // 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.
96 private static readonly DateTime unixEpoch = 96 private static readonly DateTime unixEpoch =
97 DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime(); 97 DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime();
98 98
99 private static readonly string rawUUIDPattern 99 private static readonly string rawUUIDPattern
100 = "[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 = "[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}";
101 public static readonly Regex PermissiveUUIDPattern = new Regex(rawUUIDPattern); 101 public static readonly Regex PermissiveUUIDPattern = new Regex(rawUUIDPattern);
102 public static readonly Regex UUIDPattern = new Regex(string.Format("^{0}$", rawUUIDPattern)); 102 public static readonly Regex UUIDPattern = new Regex(string.Format("^{0}$", rawUUIDPattern));
103 103
104 public static FireAndForgetMethod DefaultFireAndForgetMethod = FireAndForgetMethod.SmartThreadPool; 104 public static FireAndForgetMethod DefaultFireAndForgetMethod = FireAndForgetMethod.SmartThreadPool;
105 public static FireAndForgetMethod FireAndForgetMethod = DefaultFireAndForgetMethod; 105 public static FireAndForgetMethod FireAndForgetMethod = DefaultFireAndForgetMethod;
106 106
107 /// <summary> 107 /// <summary>
108 /// Gets the name of the directory where the current running executable 108 /// Gets the name of the directory where the current running executable
109 /// is located 109 /// is located
110 /// </summary> 110 /// </summary>
111 /// <returns>Filesystem path to the directory containing the current 111 /// <returns>Filesystem path to the directory containing the current
112 /// executable</returns> 112 /// executable</returns>
113 public static string ExecutingDirectory() 113 public static string ExecutingDirectory()
114 { 114 {
115 return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 115 return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
116 } 116 }
117 117
118 /// <summary> 118 /// <summary>
119 /// Linear interpolates B<->C using percent A 119 /// Linear interpolates B<->C using percent A
120 /// </summary> 120 /// </summary>
121 /// <param name="a"></param> 121 /// <param name="a"></param>
122 /// <param name="b"></param> 122 /// <param name="b"></param>
123 /// <param name="c"></param> 123 /// <param name="c"></param>
124 /// <returns></returns> 124 /// <returns></returns>
125 public static double lerp(double a, double b, double c) 125 public static double lerp(double a, double b, double c)
126 { 126 {
127 return (b*a) + (c*(1 - a)); 127 return (b*a) + (c*(1 - a));
128 } 128 }
129 129
130 /// <summary> 130 /// <summary>
131 /// Bilinear Interpolate, see Lerp but for 2D using 'percents' X & Y. 131 /// Bilinear Interpolate, see Lerp but for 2D using 'percents' X & Y.
132 /// Layout: 132 /// Layout:
133 /// A B 133 /// A B
134 /// C D 134 /// C D
135 /// A<->C = Y 135 /// A<->C = Y
136 /// C<->D = X 136 /// C<->D = X
137 /// </summary> 137 /// </summary>
138 /// <param name="x"></param> 138 /// <param name="x"></param>
139 /// <param name="y"></param> 139 /// <param name="y"></param>
140 /// <param name="a"></param> 140 /// <param name="a"></param>
141 /// <param name="b"></param> 141 /// <param name="b"></param>
142 /// <param name="c"></param> 142 /// <param name="c"></param>
143 /// <param name="d"></param> 143 /// <param name="d"></param>
144 /// <returns></returns> 144 /// <returns></returns>
145 public static double lerp2D(double x, double y, double a, double b, double c, double d) 145 public static double lerp2D(double x, double y, double a, double b, double c, double d)
146 { 146 {
147 return lerp(y, lerp(x, a, b), lerp(x, c, d)); 147 return lerp(y, lerp(x, a, b), lerp(x, c, d));
148 } 148 }
149 149
150 public static Encoding UTF8 = Encoding.UTF8; 150 public static Encoding UTF8 = Encoding.UTF8;
151 151
152 /// <value> 152 /// <value>
153 /// Well known UUID for the blank texture used in the Linden SL viewer version 1.20 (and hopefully onwards) 153 /// Well known UUID for the blank texture used in the Linden SL viewer version 1.20 (and hopefully onwards)
154 /// </value> 154 /// </value>
155 public static UUID BLANK_TEXTURE_UUID = new UUID("5748decc-f629-461c-9a36-a35a221fe21f"); 155 public static UUID BLANK_TEXTURE_UUID = new UUID("5748decc-f629-461c-9a36-a35a221fe21f");
156 156
157 #region Vector Equations 157 #region Vector Equations
158 158
159 /// <summary> 159 /// <summary>
160 /// Get the distance between two 3d vectors 160 /// Get the distance between two 3d vectors
161 /// </summary> 161 /// </summary>
162 /// <param name="a">A 3d vector</param> 162 /// <param name="a">A 3d vector</param>
163 /// <param name="b">A 3d vector</param> 163 /// <param name="b">A 3d vector</param>
164 /// <returns>The distance between the two vectors</returns> 164 /// <returns>The distance between the two vectors</returns>
165 public static double GetDistanceTo(Vector3 a, Vector3 b) 165 public static double GetDistanceTo(Vector3 a, Vector3 b)
166 { 166 {
167 float dx = a.X - b.X; 167 float dx = a.X - b.X;
168 float dy = a.Y - b.Y; 168 float dy = a.Y - b.Y;
169 float dz = a.Z - b.Z; 169 float dz = a.Z - b.Z;
170 return Math.Sqrt(dx * dx + dy * dy + dz * dz); 170 return Math.Sqrt(dx * dx + dy * dy + dz * dz);
171 } 171 }
172 172
173 /// <summary> 173 /// <summary>
174 /// Returns true if the distance beween A and B is less than amount. Significantly faster than GetDistanceTo since it eliminates the Sqrt. 174 /// Returns true if the distance beween A and B is less than amount. Significantly faster than GetDistanceTo since it eliminates the Sqrt.
175 /// </summary> 175 /// </summary>
176 /// <param name="a"></param> 176 /// <param name="a"></param>
177 /// <param name="b"></param> 177 /// <param name="b"></param>
178 /// <param name="amount"></param> 178 /// <param name="amount"></param>
179 /// <returns></returns> 179 /// <returns></returns>
180 public static bool DistanceLessThan(Vector3 a, Vector3 b, double amount) 180 public static bool DistanceLessThan(Vector3 a, Vector3 b, double amount)
181 { 181 {
182 float dx = a.X - b.X; 182 float dx = a.X - b.X;
183 float dy = a.Y - b.Y; 183 float dy = a.Y - b.Y;
184 float dz = a.Z - b.Z; 184 float dz = a.Z - b.Z;
185 return (dx*dx + dy*dy + dz*dz) < (amount*amount); 185 return (dx*dx + dy*dy + dz*dz) < (amount*amount);
186 } 186 }
187 187
188 /// <summary> 188 /// <summary>
189 /// Get the magnitude of a 3d vector 189 /// Get the magnitude of a 3d vector
190 /// </summary> 190 /// </summary>
191 /// <param name="a">A 3d vector</param> 191 /// <param name="a">A 3d vector</param>
192 /// <returns>The magnitude of the vector</returns> 192 /// <returns>The magnitude of the vector</returns>
193 public static double GetMagnitude(Vector3 a) 193 public static double GetMagnitude(Vector3 a)
194 { 194 {
195 return Math.Sqrt((a.X * a.X) + (a.Y * a.Y) + (a.Z * a.Z)); 195 return Math.Sqrt((a.X * a.X) + (a.Y * a.Y) + (a.Z * a.Z));
196 } 196 }
197 197
198 /// <summary> 198 /// <summary>
199 /// Get a normalized form of a 3d vector 199 /// Get a normalized form of a 3d vector
200 /// </summary> 200 /// </summary>
201 /// <param name="a">A 3d vector</param> 201 /// <param name="a">A 3d vector</param>
202 /// <returns>A new vector which is normalized form of the vector</returns> 202 /// <returns>A new vector which is normalized form of the vector</returns>
203 /// <remarks>The vector paramater cannot be <0,0,0></remarks> 203 /// <remarks>The vector paramater cannot be <0,0,0></remarks>
204 public static Vector3 GetNormalizedVector(Vector3 a) 204 public static Vector3 GetNormalizedVector(Vector3 a)
205 { 205 {
206 if (IsZeroVector(a)) 206 if (IsZeroVector(a))
207 throw new ArgumentException("Vector paramater cannot be a zero vector."); 207 throw new ArgumentException("Vector paramater cannot be a zero vector.");
208 208
209 float Mag = (float) GetMagnitude(a); 209 float Mag = (float) GetMagnitude(a);
210 return new Vector3(a.X / Mag, a.Y / Mag, a.Z / Mag); 210 return new Vector3(a.X / Mag, a.Y / Mag, a.Z / Mag);
211 } 211 }
212 212
213 /// <summary> 213 /// <summary>
214 /// Returns if a vector is a zero vector (has all zero components) 214 /// Returns if a vector is a zero vector (has all zero components)
215 /// </summary> 215 /// </summary>
216 /// <returns></returns> 216 /// <returns></returns>
217 public static bool IsZeroVector(Vector3 v) 217 public static bool IsZeroVector(Vector3 v)
218 { 218 {
219 if (v.X == 0 && v.Y == 0 && v.Z == 0) 219 if (v.X == 0 && v.Y == 0 && v.Z == 0)
220 { 220 {
221 return true; 221 return true;
222 } 222 }
223 223
224 return false; 224 return false;
225 } 225 }
226 226
227 # endregion 227 # endregion
228 228
229 public static Quaternion Axes2Rot(Vector3 fwd, Vector3 left, Vector3 up) 229 public static Quaternion Axes2Rot(Vector3 fwd, Vector3 left, Vector3 up)
230 { 230 {
231 float s; 231 float s;
232 float tr = (float) (fwd.X + left.Y + up.Z + 1.0); 232 float tr = (float) (fwd.X + left.Y + up.Z + 1.0);
233 233
234 if (tr >= 1.0) 234 if (tr >= 1.0)
235 { 235 {
236 s = (float) (0.5 / Math.Sqrt(tr)); 236 s = (float) (0.5 / Math.Sqrt(tr));
237 return new Quaternion( 237 return new Quaternion(
238 (left.Z - up.Y) * s, 238 (left.Z - up.Y) * s,
239 (up.X - fwd.Z) * s, 239 (up.X - fwd.Z) * s,
240 (fwd.Y - left.X) * s, 240 (fwd.Y - left.X) * s,
241 (float) 0.25 / s); 241 (float) 0.25 / s);
242 } 242 }
243 else 243 else
244 { 244 {
245 float max = (left.Y > up.Z) ? left.Y : up.Z; 245 float max = (left.Y > up.Z) ? left.Y : up.Z;
246 246
247 if (max < fwd.X) 247 if (max < fwd.X)
248 { 248 {
249 s = (float) (Math.Sqrt(fwd.X - (left.Y + up.Z) + 1.0)); 249 s = (float) (Math.Sqrt(fwd.X - (left.Y + up.Z) + 1.0));
250 float x = (float) (s * 0.5); 250 float x = (float) (s * 0.5);
251 s = (float) (0.5 / s); 251 s = (float) (0.5 / s);
252 return new Quaternion( 252 return new Quaternion(
253 x, 253 x,
254 (fwd.Y + left.X) * s, 254 (fwd.Y + left.X) * s,
255 (up.X + fwd.Z) * s, 255 (up.X + fwd.Z) * s,
256 (left.Z - up.Y) * s); 256 (left.Z - up.Y) * s);
257 } 257 }
258 else if (max == left.Y) 258 else if (max == left.Y)
259 { 259 {
260 s = (float) (Math.Sqrt(left.Y - (up.Z + fwd.X) + 1.0)); 260 s = (float) (Math.Sqrt(left.Y - (up.Z + fwd.X) + 1.0));
261 float y = (float) (s * 0.5); 261 float y = (float) (s * 0.5);
262 s = (float) (0.5 / s); 262 s = (float) (0.5 / s);
263 return new Quaternion( 263 return new Quaternion(
264 (fwd.Y + left.X) * s, 264 (fwd.Y + left.X) * s,
265 y, 265 y,
266 (left.Z + up.Y) * s, 266 (left.Z + up.Y) * s,
267 (up.X - fwd.Z) * s); 267 (up.X - fwd.Z) * s);
268 } 268 }
269 else 269 else
270 { 270 {
271 s = (float) (Math.Sqrt(up.Z - (fwd.X + left.Y) + 1.0)); 271 s = (float) (Math.Sqrt(up.Z - (fwd.X + left.Y) + 1.0));
272 float z = (float) (s * 0.5); 272 float z = (float) (s * 0.5);
273 s = (float) (0.5 / s); 273 s = (float) (0.5 / s);
274 return new Quaternion( 274 return new Quaternion(
275 (up.X + fwd.Z) * s, 275 (up.X + fwd.Z) * s,
276 (left.Z + up.Y) * s, 276 (left.Z + up.Y) * s,
277 z, 277 z,
278 (fwd.Y - left.X) * s); 278 (fwd.Y - left.X) * s);
279 } 279 }
280 } 280 }
281 } 281 }
282 282
283 public static Random RandomClass 283 public static Random RandomClass
284 { 284 {
285 get { return randomClass; } 285 get { return randomClass; }
286 } 286 }
287 287
288 public static ulong UIntsToLong(uint X, uint Y) 288 public static ulong UIntsToLong(uint X, uint Y)
289 { 289 {
290 return Utils.UIntsToLong(X, Y); 290 return Utils.UIntsToLong(X, Y);
291 } 291 }
292 292
293 public static T Clamp<T>(T x, T min, T max) 293 public static T Clamp<T>(T x, T min, T max)
294 where T : IComparable<T> 294 where T : IComparable<T>
295 { 295 {
296 return x.CompareTo(max) > 0 ? max : 296 return x.CompareTo(max) > 0 ? max :
297 x.CompareTo(min) < 0 ? min : 297 x.CompareTo(min) < 0 ? min :
298 x; 298 x;
299 } 299 }
300 300
301 public static uint GetNextXferID() 301 public static uint GetNextXferID()
302 { 302 {
303 uint id = 0; 303 uint id = 0;
304 lock (XferLock) 304 lock (XferLock)
305 { 305 {
306 id = nextXferID; 306 id = nextXferID;
307 nextXferID++; 307 nextXferID++;
308 } 308 }
309 return id; 309 return id;
310 } 310 }
311 311
312 public static string GetFileName(string file) 312 public static string GetFileName(string file)
313 { 313 {
314 // Return just the filename on UNIX platforms 314 // Return just the filename on UNIX platforms
315 // TODO: this should be customisable with a prefix, but that's something to do later. 315 // TODO: this should be customisable with a prefix, but that's something to do later.
316 if (Environment.OSVersion.Platform == PlatformID.Unix) 316 if (Environment.OSVersion.Platform == PlatformID.Unix)
317 { 317 {
318 return file; 318 return file;
319 } 319 }
320 320
321 // Return %APPDATA%/OpenSim/file for 2K/XP/NT/2K3/VISTA 321 // Return %APPDATA%/OpenSim/file for 2K/XP/NT/2K3/VISTA
322 // TODO: Switch this to System.Enviroment.SpecialFolders.ApplicationData 322 // TODO: Switch this to System.Enviroment.SpecialFolders.ApplicationData
323 if (Environment.OSVersion.Platform == PlatformID.Win32NT) 323 if (Environment.OSVersion.Platform == PlatformID.Win32NT)
324 { 324 {
325 if (!Directory.Exists("%APPDATA%\\OpenSim\\")) 325 if (!Directory.Exists("%APPDATA%\\OpenSim\\"))
326 { 326 {
327 Directory.CreateDirectory("%APPDATA%\\OpenSim"); 327 Directory.CreateDirectory("%APPDATA%\\OpenSim");
328 } 328 }
329 329
330 return "%APPDATA%\\OpenSim\\" + file; 330 return "%APPDATA%\\OpenSim\\" + file;
331 } 331 }
332 332
333 // Catch all - covers older windows versions 333 // Catch all - covers older windows versions
334 // (but those probably wont work anyway) 334 // (but those probably wont work anyway)
335 return file; 335 return file;
336 } 336 }
337 337
338 /// <summary> 338 /// <summary>
339 /// Debug utility function to convert OSD into formatted XML for debugging purposes. 339 /// Debug utility function to convert OSD into formatted XML for debugging purposes.
340 /// </summary> 340 /// </summary>
341 /// <param name="osd"> 341 /// <param name="osd">
342 /// A <see cref="OSD"/> 342 /// A <see cref="OSD"/>
343 /// </param> 343 /// </param>
344 /// <returns> 344 /// <returns>
345 /// A <see cref="System.String"/> 345 /// A <see cref="System.String"/>
346 /// </returns> 346 /// </returns>
347 public static string GetFormattedXml(OSD osd) 347 public static string GetFormattedXml(OSD osd)
348 { 348 {
349 return GetFormattedXml(OSDParser.SerializeLLSDXmlString(osd)); 349 return GetFormattedXml(OSDParser.SerializeLLSDXmlString(osd));
350 } 350 }
351 351
352 /// <summary> 352 /// <summary>
353 /// Debug utility function to convert unbroken strings of XML into something human readable for occasional debugging purposes. 353 /// Debug utility function to convert unbroken strings of XML into something human readable for occasional debugging purposes.
354 /// </summary> 354 /// </summary>
355 /// <remarks> 355 /// <remarks>
356 /// Please don't delete me even if I appear currently unused! 356 /// Please don't delete me even if I appear currently unused!
357 /// </remarks> 357 /// </remarks>
358 /// <param name="rawXml"></param> 358 /// <param name="rawXml"></param>
359 /// <returns></returns> 359 /// <returns></returns>
360 public static string GetFormattedXml(string rawXml) 360 public static string GetFormattedXml(string rawXml)
361 { 361 {
362 XmlDocument xd = new XmlDocument(); 362 XmlDocument xd = new XmlDocument();
363 xd.LoadXml(rawXml); 363 xd.LoadXml(rawXml);
364 364
365 StringBuilder sb = new StringBuilder(); 365 StringBuilder sb = new StringBuilder();
366 StringWriter sw = new StringWriter(sb); 366 StringWriter sw = new StringWriter(sb);
367 367
368 XmlTextWriter xtw = new XmlTextWriter(sw); 368 XmlTextWriter xtw = new XmlTextWriter(sw);
369 xtw.Formatting = Formatting.Indented; 369 xtw.Formatting = Formatting.Indented;
370 370
371 try 371 try
372 { 372 {
373 xd.WriteTo(xtw); 373 xd.WriteTo(xtw);
374 } 374 }
375 finally 375 finally
376 { 376 {
377 xtw.Close(); 377 xtw.Close();
378 } 378 }
379 379
380 return sb.ToString(); 380 return sb.ToString();
381 } 381 }
382 382
383 /// <summary> 383 /// <summary>
@@ -392,1118 +392,1118 @@ namespace OpenSim.Framework
392 || platformId == PlatformID.Win32S 392 || platformId == PlatformID.Win32S
393 || platformId == PlatformID.Win32Windows 393 || platformId == PlatformID.Win32Windows
394 || platformId == PlatformID.WinCE); 394 || platformId == PlatformID.WinCE);
395 } 395 }
396 396
397 public static bool LoadArchSpecificWindowsDll(string libraryName) 397 public static bool LoadArchSpecificWindowsDll(string libraryName)
398 { 398 {
399 // We do this so that OpenSimulator on Windows loads the correct native library depending on whether 399 // We do this so that OpenSimulator on Windows loads the correct native library depending on whether
400 // it's running as a 32-bit process or a 64-bit one. By invoking LoadLibary here, later DLLImports 400 // it's running as a 32-bit process or a 64-bit one. By invoking LoadLibary here, later DLLImports
401 // will find it already loaded later on. 401 // will find it already loaded later on.
402 // 402 //
403 // This isn't necessary for other platforms (e.g. Mac OSX and Linux) since the DLL used can be 403 // This isn't necessary for other platforms (e.g. Mac OSX and Linux) since the DLL used can be
404 // controlled in config files. 404 // controlled in config files.
405 string nativeLibraryPath; 405 string nativeLibraryPath;
406 406
407 if (Util.Is64BitProcess()) 407 if (Util.Is64BitProcess())
408 nativeLibraryPath = "lib64/" + libraryName; 408 nativeLibraryPath = "lib64/" + libraryName;
409 else 409 else
410 nativeLibraryPath = "lib32/" + libraryName; 410 nativeLibraryPath = "lib32/" + libraryName;
411 411
412 m_log.DebugFormat("[UTIL]: Loading native Windows library at {0}", nativeLibraryPath); 412 m_log.DebugFormat("[UTIL]: Loading native Windows library at {0}", nativeLibraryPath);
413 413
414 if (Util.LoadLibrary(nativeLibraryPath) == IntPtr.Zero) 414 if (Util.LoadLibrary(nativeLibraryPath) == IntPtr.Zero)
415 { 415 {
416 m_log.ErrorFormat( 416 m_log.ErrorFormat(
417 "[UTIL]: Couldn't find native Windows library at {0}", nativeLibraryPath); 417 "[UTIL]: Couldn't find native Windows library at {0}", nativeLibraryPath);
418 418
419 return false; 419 return false;
420 } 420 }
421 else 421 else
422 { 422 {
423 return true; 423 return true;
424 } 424 }
425 } 425 }
426 426
427 public static bool IsEnvironmentSupported(ref string reason) 427 public static bool IsEnvironmentSupported(ref string reason)
428 { 428 {
429 // Must have .NET 2.0 (Generics / libsl) 429 // Must have .NET 2.0 (Generics / libsl)
430 if (Environment.Version.Major < 2) 430 if (Environment.Version.Major < 2)
431 { 431 {
432 reason = ".NET 1.0/1.1 lacks components that is used by OpenSim"; 432 reason = ".NET 1.0/1.1 lacks components that is used by OpenSim";
433 return false; 433 return false;
434 } 434 }
435 435
436 // Windows 95/98/ME are unsupported 436 // Windows 95/98/ME are unsupported
437 if (Environment.OSVersion.Platform == PlatformID.Win32Windows && 437 if (Environment.OSVersion.Platform == PlatformID.Win32Windows &&
438 Environment.OSVersion.Platform != PlatformID.Win32NT) 438 Environment.OSVersion.Platform != PlatformID.Win32NT)
439 { 439 {
440 reason = "Windows 95/98/ME will not run OpenSim"; 440 reason = "Windows 95/98/ME will not run OpenSim";
441 return false; 441 return false;
442 } 442 }
443 443
444 // Windows 2000 / Pre-SP2 XP 444 // Windows 2000 / Pre-SP2 XP
445 if (Environment.OSVersion.Version.Major == 5 && 445 if (Environment.OSVersion.Version.Major == 5 &&
446 Environment.OSVersion.Version.Minor == 0) 446 Environment.OSVersion.Version.Minor == 0)
447 { 447 {
448 reason = "Please update to Windows XP Service Pack 2 or Server2003"; 448 reason = "Please update to Windows XP Service Pack 2 or Server2003";
449 return false; 449 return false;
450 } 450 }
451 451
452 return true; 452 return true;
453 } 453 }
454 454
455 public static int UnixTimeSinceEpoch() 455 public static int UnixTimeSinceEpoch()
456 { 456 {
457 return ToUnixTime(DateTime.UtcNow); 457 return ToUnixTime(DateTime.UtcNow);
458 } 458 }
459 459
460 public static int ToUnixTime(DateTime stamp) 460 public static int ToUnixTime(DateTime stamp)
461 { 461 {
462 TimeSpan t = stamp.ToUniversalTime() - unixEpoch; 462 TimeSpan t = stamp.ToUniversalTime() - unixEpoch;
463 return (int) t.TotalSeconds; 463 return (int) t.TotalSeconds;
464 } 464 }
465 465
466 public static DateTime ToDateTime(ulong seconds) 466 public static DateTime ToDateTime(ulong seconds)
467 { 467 {
468 DateTime epoch = unixEpoch; 468 DateTime epoch = unixEpoch;
469 return epoch.AddSeconds(seconds); 469 return epoch.AddSeconds(seconds);
470 } 470 }
471 471
472 public static DateTime ToDateTime(int seconds) 472 public static DateTime ToDateTime(int seconds)
473 { 473 {
474 DateTime epoch = unixEpoch; 474 DateTime epoch = unixEpoch;
475 return epoch.AddSeconds(seconds); 475 return epoch.AddSeconds(seconds);
476 } 476 }
477 477
478 /// <summary> 478 /// <summary>
479 /// Return an md5 hash of the given string 479 /// Return an md5 hash of the given string
480 /// </summary> 480 /// </summary>
481 /// <param name="data"></param> 481 /// <param name="data"></param>
482 /// <returns></returns> 482 /// <returns></returns>
483 public static string Md5Hash(string data) 483 public static string Md5Hash(string data)
484 { 484 {
485 byte[] dataMd5 = ComputeMD5Hash(data); 485 byte[] dataMd5 = ComputeMD5Hash(data);
486 StringBuilder sb = new StringBuilder(); 486 StringBuilder sb = new StringBuilder();
487 for (int i = 0; i < dataMd5.Length; i++) 487 for (int i = 0; i < dataMd5.Length; i++)
488 sb.AppendFormat("{0:x2}", dataMd5[i]); 488 sb.AppendFormat("{0:x2}", dataMd5[i]);
489 return sb.ToString(); 489 return sb.ToString();
490 } 490 }
491 491
492 private static byte[] ComputeMD5Hash(string data) 492 private static byte[] ComputeMD5Hash(string data)
493 { 493 {
494 MD5 md5 = MD5.Create(); 494 MD5 md5 = MD5.Create();
495 return md5.ComputeHash(Encoding.Default.GetBytes(data)); 495 return md5.ComputeHash(Encoding.Default.GetBytes(data));
496 } 496 }
497 497
498 /// <summary> 498 /// <summary>
499 /// Return an SHA1 hash 499 /// Return an SHA1 hash
500 /// </summary> 500 /// </summary>
501 /// <param name="data"></param> 501 /// <param name="data"></param>
502 /// <returns></returns> 502 /// <returns></returns>
503 public static string SHA1Hash(string data) 503 public static string SHA1Hash(string data)
504 { 504 {
505 return SHA1Hash(Encoding.Default.GetBytes(data)); 505 return SHA1Hash(Encoding.Default.GetBytes(data));
506 } 506 }
507 507
508 /// <summary> 508 /// <summary>
509 /// Return an SHA1 hash 509 /// Return an SHA1 hash
510 /// </summary> 510 /// </summary>
511 /// <param name="data"></param> 511 /// <param name="data"></param>
512 /// <returns></returns> 512 /// <returns></returns>
513 public static string SHA1Hash(byte[] data) 513 public static string SHA1Hash(byte[] data)
514 { 514 {
515 byte[] hash = ComputeSHA1Hash(data); 515 byte[] hash = ComputeSHA1Hash(data);
516 return BitConverter.ToString(hash).Replace("-", String.Empty); 516 return BitConverter.ToString(hash).Replace("-", String.Empty);
517 } 517 }
518 518
519 private static byte[] ComputeSHA1Hash(byte[] src) 519 private static byte[] ComputeSHA1Hash(byte[] src)
520 { 520 {
521 SHA1CryptoServiceProvider SHA1 = new SHA1CryptoServiceProvider(); 521 SHA1CryptoServiceProvider SHA1 = new SHA1CryptoServiceProvider();
522 return SHA1.ComputeHash(src); 522 return SHA1.ComputeHash(src);
523 } 523 }
524 524
525 public static int fast_distance2d(int x, int y) 525 public static int fast_distance2d(int x, int y)
526 { 526 {
527 x = Math.Abs(x); 527 x = Math.Abs(x);
528 y = Math.Abs(y); 528 y = Math.Abs(y);
529 529
530 int min = Math.Min(x, y); 530 int min = Math.Min(x, y);
531 531
532 return (x + y - (min >> 1) - (min >> 2) + (min >> 4)); 532 return (x + y - (min >> 1) - (min >> 2) + (min >> 4));
533 } 533 }
534 534
535 /// <summary> 535 /// <summary>
536 /// Are the co-ordinates of the new region visible from the old region? 536 /// Are the co-ordinates of the new region visible from the old region?
537 /// </summary> 537 /// </summary>
538 /// <param name="oldx">Old region x-coord</param> 538 /// <param name="oldx">Old region x-coord</param>
539 /// <param name="newx">New region x-coord</param> 539 /// <param name="newx">New region x-coord</param>
540 /// <param name="oldy">Old region y-coord</param> 540 /// <param name="oldy">Old region y-coord</param>
541 /// <param name="newy">New region y-coord</param> 541 /// <param name="newy">New region y-coord</param>
542 /// <returns></returns> 542 /// <returns></returns>
543 public static bool IsOutsideView(float drawdist, uint oldx, uint newx, uint oldy, uint newy) 543 public static bool IsOutsideView(float drawdist, uint oldx, uint newx, uint oldy, uint newy)
544 { 544 {
545 int dd = (int)((drawdist + Constants.RegionSize - 1) / Constants.RegionSize); 545 int dd = (int)((drawdist + Constants.RegionSize - 1) / Constants.RegionSize);
546 546
547 int startX = (int)oldx - dd; 547 int startX = (int)oldx - dd;
548 int startY = (int)oldy - dd; 548 int startY = (int)oldy - dd;
549 549
550 int endX = (int)oldx + dd; 550 int endX = (int)oldx + dd;
551 int endY = (int)oldy + dd; 551 int endY = (int)oldy + dd;
552 552
553 return (newx < startX || endX < newx || newy < startY || endY < newy); 553 return (newx < startX || endX < newx || newy < startY || endY < newy);
554 } 554 }
555 555
556 public static string FieldToString(byte[] bytes) 556 public static string FieldToString(byte[] bytes)
557 { 557 {
558 return FieldToString(bytes, String.Empty); 558 return FieldToString(bytes, String.Empty);
559 } 559 }
560 560
561 /// <summary> 561 /// <summary>
562 /// Convert a variable length field (byte array) to a string, with a 562 /// Convert a variable length field (byte array) to a string, with a
563 /// field name prepended to each line of the output 563 /// field name prepended to each line of the output
564 /// </summary> 564 /// </summary>
565 /// <remarks>If the byte array has unprintable characters in it, a 565 /// <remarks>If the byte array has unprintable characters in it, a
566 /// hex dump will be put in the string instead</remarks> 566 /// hex dump will be put in the string instead</remarks>
567 /// <param name="bytes">The byte array to convert to a string</param> 567 /// <param name="bytes">The byte array to convert to a string</param>
568 /// <param name="fieldName">A field name to prepend to each line of output</param> 568 /// <param name="fieldName">A field name to prepend to each line of output</param>
569 /// <returns>An ASCII string or a string containing a hex dump, minus 569 /// <returns>An ASCII string or a string containing a hex dump, minus
570 /// the null terminator</returns> 570 /// the null terminator</returns>
571 public static string FieldToString(byte[] bytes, string fieldName) 571 public static string FieldToString(byte[] bytes, string fieldName)
572 { 572 {
573 // Check for a common case 573 // Check for a common case
574 if (bytes.Length == 0) return String.Empty; 574 if (bytes.Length == 0) return String.Empty;
575 575
576 StringBuilder output = new StringBuilder(); 576 StringBuilder output = new StringBuilder();
577 bool printable = true; 577 bool printable = true;
578 578
579 for (int i = 0; i < bytes.Length; ++i) 579 for (int i = 0; i < bytes.Length; ++i)
580 { 580 {
581 // Check if there are any unprintable characters in the array 581 // Check if there are any unprintable characters in the array
582 if ((bytes[i] < 0x20 || bytes[i] > 0x7E) && bytes[i] != 0x09 582 if ((bytes[i] < 0x20 || bytes[i] > 0x7E) && bytes[i] != 0x09
583 && bytes[i] != 0x0D && bytes[i] != 0x0A && bytes[i] != 0x00) 583 && bytes[i] != 0x0D && bytes[i] != 0x0A && bytes[i] != 0x00)
584 { 584 {
585 printable = false; 585 printable = false;
586 break; 586 break;
587 } 587 }
588 } 588 }
589 589
590 if (printable) 590 if (printable)
591 { 591 {
592 if (fieldName.Length > 0) 592 if (fieldName.Length > 0)
593 { 593 {
594 output.Append(fieldName); 594 output.Append(fieldName);
595 output.Append(": "); 595 output.Append(": ");
596 } 596 }
597 597
598 output.Append(CleanString(Util.UTF8.GetString(bytes, 0, bytes.Length - 1))); 598 output.Append(CleanString(Util.UTF8.GetString(bytes, 0, bytes.Length - 1)));
599 } 599 }
600 else 600 else
601 { 601 {
602 for (int i = 0; i < bytes.Length; i += 16) 602 for (int i = 0; i < bytes.Length; i += 16)
603 { 603 {
604 if (i != 0) 604 if (i != 0)
605 output.Append(Environment.NewLine); 605 output.Append(Environment.NewLine);
606 if (fieldName.Length > 0) 606 if (fieldName.Length > 0)
607 { 607 {
608 output.Append(fieldName); 608 output.Append(fieldName);
609 output.Append(": "); 609 output.Append(": ");
610 } 610 }
611 611
612 for (int j = 0; j < 16; j++) 612 for (int j = 0; j < 16; j++)
613 { 613 {
614 if ((i + j) < bytes.Length) 614 if ((i + j) < bytes.Length)
615 output.Append(String.Format("{0:X2} ", bytes[i + j])); 615 output.Append(String.Format("{0:X2} ", bytes[i + j]));
616 else 616 else
617 output.Append(" "); 617 output.Append(" ");
618 } 618 }
619 619
620 for (int j = 0; j < 16 && (i + j) < bytes.Length; j++) 620 for (int j = 0; j < 16 && (i + j) < bytes.Length; j++)
621 { 621 {
622 if (bytes[i + j] >= 0x20 && bytes[i + j] < 0x7E) 622 if (bytes[i + j] >= 0x20 && bytes[i + j] < 0x7E)
623 output.Append((char) bytes[i + j]); 623 output.Append((char) bytes[i + j]);
624 else 624 else
625 output.Append("."); 625 output.Append(".");
626 } 626 }
627 } 627 }
628 } 628 }
629 629
630 return output.ToString(); 630 return output.ToString();
631 } 631 }
632 632
633 /// <summary> 633 /// <summary>
634 /// Converts a URL to a IPAddress 634 /// Converts a URL to a IPAddress
635 /// </summary> 635 /// </summary>
636 /// <param name="url">URL Standard Format</param> 636 /// <param name="url">URL Standard Format</param>
637 /// <returns>A resolved IP Address</returns> 637 /// <returns>A resolved IP Address</returns>
638 public static IPAddress GetHostFromURL(string url) 638 public static IPAddress GetHostFromURL(string url)
639 { 639 {
640 return GetHostFromDNS(url.Split(new char[] {'/', ':'})[3]); 640 return GetHostFromDNS(url.Split(new char[] {'/', ':'})[3]);
641 } 641 }
642 642
643 /// <summary> 643 /// <summary>
644 /// Returns a IP address from a specified DNS, favouring IPv4 addresses. 644 /// Returns a IP address from a specified DNS, favouring IPv4 addresses.
645 /// </summary> 645 /// </summary>
646 /// <param name="dnsAddress">DNS Hostname</param> 646 /// <param name="dnsAddress">DNS Hostname</param>
647 /// <returns>An IP address, or null</returns> 647 /// <returns>An IP address, or null</returns>
648 public static IPAddress GetHostFromDNS(string dnsAddress) 648 public static IPAddress GetHostFromDNS(string dnsAddress)
649 { 649 {
650 // Is it already a valid IP? No need to look it up. 650 // Is it already a valid IP? No need to look it up.
651 IPAddress ipa; 651 IPAddress ipa;
652 if (IPAddress.TryParse(dnsAddress, out ipa)) 652 if (IPAddress.TryParse(dnsAddress, out ipa))
653 return ipa; 653 return ipa;
654 654
655 IPAddress[] hosts = null; 655 IPAddress[] hosts = null;
656 656
657 // Not an IP, lookup required 657 // Not an IP, lookup required
658 try 658 try
659 { 659 {
660 hosts = Dns.GetHostEntry(dnsAddress).AddressList; 660 hosts = Dns.GetHostEntry(dnsAddress).AddressList;
661 } 661 }
662 catch (Exception e) 662 catch (Exception e)
663 { 663 {
664 m_log.WarnFormat("[UTIL]: An error occurred while resolving host name {0}, {1}", dnsAddress, e); 664 m_log.WarnFormat("[UTIL]: An error occurred while resolving host name {0}, {1}", dnsAddress, e);
665 665
666 // Still going to throw the exception on for now, since this was what was happening in the first place 666 // Still going to throw the exception on for now, since this was what was happening in the first place
667 throw e; 667 throw e;
668 } 668 }
669 669
670 foreach (IPAddress host in hosts) 670 foreach (IPAddress host in hosts)
671 { 671 {
672 if (host.AddressFamily == AddressFamily.InterNetwork) 672 if (host.AddressFamily == AddressFamily.InterNetwork)
673 { 673 {
674 return host; 674 return host;
675 } 675 }
676 } 676 }
677 677
678 if (hosts.Length > 0) 678 if (hosts.Length > 0)
679 return hosts[0]; 679 return hosts[0];
680 680
681 return null; 681 return null;
682 } 682 }
683 683
684 public static Uri GetURI(string protocol, string hostname, int port, string path) 684 public static Uri GetURI(string protocol, string hostname, int port, string path)
685 { 685 {
686 return new UriBuilder(protocol, hostname, port, path).Uri; 686 return new UriBuilder(protocol, hostname, port, path).Uri;
687 } 687 }
688 688
689 /// <summary> 689 /// <summary>
690 /// Gets a list of all local system IP addresses 690 /// Gets a list of all local system IP addresses
691 /// </summary> 691 /// </summary>
692 /// <returns></returns> 692 /// <returns></returns>
693 public static IPAddress[] GetLocalHosts() 693 public static IPAddress[] GetLocalHosts()
694 { 694 {
695 return Dns.GetHostAddresses(Dns.GetHostName()); 695 return Dns.GetHostAddresses(Dns.GetHostName());
696 } 696 }
697 697
698 public static IPAddress GetLocalHost() 698 public static IPAddress GetLocalHost()
699 { 699 {
700 IPAddress[] iplist = GetLocalHosts(); 700 IPAddress[] iplist = GetLocalHosts();
701 701
702 if (iplist.Length == 0) // No accessible external interfaces 702 if (iplist.Length == 0) // No accessible external interfaces
703 { 703 {
704 IPAddress[] loopback = Dns.GetHostAddresses("localhost"); 704 IPAddress[] loopback = Dns.GetHostAddresses("localhost");
705 IPAddress localhost = loopback[0]; 705 IPAddress localhost = loopback[0];
706 706
707 return localhost; 707 return localhost;
708 } 708 }
709 709
710 foreach (IPAddress host in iplist) 710 foreach (IPAddress host in iplist)
711 { 711 {
712 if (!IPAddress.IsLoopback(host) && host.AddressFamily == AddressFamily.InterNetwork) 712 if (!IPAddress.IsLoopback(host) && host.AddressFamily == AddressFamily.InterNetwork)
713 { 713 {
714 return host; 714 return host;
715 } 715 }
716 } 716 }
717 717
718 if (iplist.Length > 0) 718 if (iplist.Length > 0)
719 { 719 {
720 foreach (IPAddress host in iplist) 720 foreach (IPAddress host in iplist)
721 { 721 {
722 if (host.AddressFamily == AddressFamily.InterNetwork) 722 if (host.AddressFamily == AddressFamily.InterNetwork)
723 return host; 723 return host;
724 } 724 }
725 // Well all else failed... 725 // Well all else failed...
726 return iplist[0]; 726 return iplist[0];
727 } 727 }
728 728
729 return null; 729 return null;
730 } 730 }
731 731
732 /// <summary> 732 /// <summary>
733 /// Removes all invalid path chars (OS dependent) 733 /// Removes all invalid path chars (OS dependent)
734 /// </summary> 734 /// </summary>
735 /// <param name="path">path</param> 735 /// <param name="path">path</param>
736 /// <returns>safe path</returns> 736 /// <returns>safe path</returns>
737 public static string safePath(string path) 737 public static string safePath(string path)
738 { 738 {
739 return Regex.Replace(path, regexInvalidPathChars, String.Empty); 739 return Regex.Replace(path, regexInvalidPathChars, String.Empty);
740 } 740 }
741 741
742 /// <summary> 742 /// <summary>
743 /// Removes all invalid filename chars (OS dependent) 743 /// Removes all invalid filename chars (OS dependent)
744 /// </summary> 744 /// </summary>
745 /// <param name="path">filename</param> 745 /// <param name="path">filename</param>
746 /// <returns>safe filename</returns> 746 /// <returns>safe filename</returns>
747 public static string safeFileName(string filename) 747 public static string safeFileName(string filename)
748 { 748 {
749 return Regex.Replace(filename, regexInvalidFileChars, String.Empty); 749 return Regex.Replace(filename, regexInvalidFileChars, String.Empty);
750 ; 750 ;
751 } 751 }
752 752
753 // 753 //
754 // directory locations 754 // directory locations
755 // 755 //
756 756
757 public static string homeDir() 757 public static string homeDir()
758 { 758 {
759 string temp; 759 string temp;
760 // string personal=(Environment.GetFolderPath(Environment.SpecialFolder.Personal)); 760 // string personal=(Environment.GetFolderPath(Environment.SpecialFolder.Personal));
761 // temp = Path.Combine(personal,".OpenSim"); 761 // temp = Path.Combine(personal,".OpenSim");
762 temp = "."; 762 temp = ".";
763 return temp; 763 return temp;
764 } 764 }
765 765
766 public static string assetsDir() 766 public static string assetsDir()
767 { 767 {
768 return Path.Combine(configDir(), "assets"); 768 return Path.Combine(configDir(), "assets");
769 } 769 }
770 770
771 public static string inventoryDir() 771 public static string inventoryDir()
772 { 772 {
773 return Path.Combine(configDir(), "inventory"); 773 return Path.Combine(configDir(), "inventory");
774 } 774 }
775 775
776 public static string configDir() 776 public static string configDir()
777 { 777 {
778 return "."; 778 return ".";
779 } 779 }
780 780
781 public static string dataDir() 781 public static string dataDir()
782 { 782 {
783 return "."; 783 return ".";
784 } 784 }
785 785
786 public static string logDir() 786 public static string logDir()
787 { 787 {
788 return "."; 788 return ".";
789 } 789 }
790 790
791 // From: http://coercedcode.blogspot.com/2008/03/c-generate-unique-filenames-within.html 791 // From: http://coercedcode.blogspot.com/2008/03/c-generate-unique-filenames-within.html
792 public static string GetUniqueFilename(string FileName) 792 public static string GetUniqueFilename(string FileName)
793 { 793 {
794 int count = 0; 794 int count = 0;
795 string Name; 795 string Name;
796 796
797 if (File.Exists(FileName)) 797 if (File.Exists(FileName))
798 { 798 {
799 FileInfo f = new FileInfo(FileName); 799 FileInfo f = new FileInfo(FileName);
800 800
801 if (!String.IsNullOrEmpty(f.Extension)) 801 if (!String.IsNullOrEmpty(f.Extension))
802 { 802 {
803 Name = f.FullName.Substring(0, f.FullName.LastIndexOf('.')); 803 Name = f.FullName.Substring(0, f.FullName.LastIndexOf('.'));
804 } 804 }
805 else 805 else
806 { 806 {
807 Name = f.FullName; 807 Name = f.FullName;
808 } 808 }
809 809
810 while (File.Exists(FileName)) 810 while (File.Exists(FileName))
811 { 811 {
812 count++; 812 count++;
813 FileName = Name + count + f.Extension; 813 FileName = Name + count + f.Extension;
814 } 814 }
815 } 815 }
816 return FileName; 816 return FileName;
817 } 817 }
818 818
819 // Nini (config) related Methods 819 // Nini (config) related Methods
820 public static IConfigSource ConvertDataRowToXMLConfig(DataRow row, string fileName) 820 public static IConfigSource ConvertDataRowToXMLConfig(DataRow row, string fileName)
821 { 821 {
822 if (!File.Exists(fileName)) 822 if (!File.Exists(fileName))
823 { 823 {
824 //create new file 824 //create new file
825 } 825 }
826 XmlConfigSource config = new XmlConfigSource(fileName); 826 XmlConfigSource config = new XmlConfigSource(fileName);
827 AddDataRowToConfig(config, row); 827 AddDataRowToConfig(config, row);
828 config.Save(); 828 config.Save();
829 829
830 return config; 830 return config;
831 } 831 }
832 832
833 public static void AddDataRowToConfig(IConfigSource config, DataRow row) 833 public static void AddDataRowToConfig(IConfigSource config, DataRow row)
834 { 834 {
835 config.Configs.Add((string) row[0]); 835 config.Configs.Add((string) row[0]);
836 for (int i = 0; i < row.Table.Columns.Count; i++) 836 for (int i = 0; i < row.Table.Columns.Count; i++)
837 { 837 {
838 config.Configs[(string) row[0]].Set(row.Table.Columns[i].ColumnName, row[i]); 838 config.Configs[(string) row[0]].Set(row.Table.Columns[i].ColumnName, row[i]);
839 } 839 }
840 } 840 }
841 841
842 public static float Clip(float x, float min, float max) 842 public static float Clip(float x, float min, float max)
843 { 843 {
844 return Math.Min(Math.Max(x, min), max); 844 return Math.Min(Math.Max(x, min), max);
845 } 845 }
846 846
847 public static int Clip(int x, int min, int max) 847 public static int Clip(int x, int min, int max)
848 { 848 {
849 return Math.Min(Math.Max(x, min), max); 849 return Math.Min(Math.Max(x, min), max);
850 } 850 }
851 851
852 /// <summary> 852 /// <summary>
853 /// Convert an UUID to a raw uuid string. Right now this is a string without hyphens. 853 /// Convert an UUID to a raw uuid string. Right now this is a string without hyphens.
854 /// </summary> 854 /// </summary>
855 /// <param name="UUID"></param> 855 /// <param name="UUID"></param>
856 /// <returns></returns> 856 /// <returns></returns>
857 public static String ToRawUuidString(UUID UUID) 857 public static String ToRawUuidString(UUID UUID)
858 { 858 {
859 return UUID.Guid.ToString("n"); 859 return UUID.Guid.ToString("n");
860 } 860 }
861 861
862 public static string CleanString(string input) 862 public static string CleanString(string input)
863 { 863 {
864 if (input.Length == 0) 864 if (input.Length == 0)
865 return input; 865 return input;
866 866
867 int clip = input.Length; 867 int clip = input.Length;
868 868
869 // Test for ++ string terminator 869 // Test for ++ string terminator
870 int pos = input.IndexOf("\0"); 870 int pos = input.IndexOf("\0");
871 if (pos != -1 && pos < clip) 871 if (pos != -1 && pos < clip)
872 clip = pos; 872 clip = pos;
873 873
874 // Test for CR 874 // Test for CR
875 pos = input.IndexOf("\r"); 875 pos = input.IndexOf("\r");
876 if (pos != -1 && pos < clip) 876 if (pos != -1 && pos < clip)
877 clip = pos; 877 clip = pos;
878 878
879 // Test for LF 879 // Test for LF
880 pos = input.IndexOf("\n"); 880 pos = input.IndexOf("\n");
881 if (pos != -1 && pos < clip) 881 if (pos != -1 && pos < clip)
882 clip = pos; 882 clip = pos;
883 883
884 // Truncate string before first end-of-line character found 884 // Truncate string before first end-of-line character found
885 return input.Substring(0, clip); 885 return input.Substring(0, clip);
886 } 886 }
887 887
888 /// <summary> 888 /// <summary>
889 /// returns the contents of /etc/issue on Unix Systems 889 /// returns the contents of /etc/issue on Unix Systems
890 /// Use this for where it's absolutely necessary to implement platform specific stuff 890 /// Use this for where it's absolutely necessary to implement platform specific stuff
891 /// </summary> 891 /// </summary>
892 /// <returns></returns> 892 /// <returns></returns>
893 public static string ReadEtcIssue() 893 public static string ReadEtcIssue()
894 { 894 {
895 try 895 try
896 { 896 {
897 StreamReader sr = new StreamReader("/etc/issue.net"); 897 StreamReader sr = new StreamReader("/etc/issue.net");
898 string issue = sr.ReadToEnd(); 898 string issue = sr.ReadToEnd();
899 sr.Close(); 899 sr.Close();
900 return issue; 900 return issue;
901 } 901 }
902 catch (Exception) 902 catch (Exception)
903 { 903 {
904 return ""; 904 return "";
905 } 905 }
906 } 906 }
907 907
908 public static void SerializeToFile(string filename, Object obj) 908 public static void SerializeToFile(string filename, Object obj)
909 { 909 {
910 IFormatter formatter = new BinaryFormatter(); 910 IFormatter formatter = new BinaryFormatter();
911 Stream stream = null; 911 Stream stream = null;
912 912
913 try 913 try
914 { 914 {
915 stream = new FileStream( 915 stream = new FileStream(
916 filename, FileMode.Create, 916 filename, FileMode.Create,
917 FileAccess.Write, FileShare.None); 917 FileAccess.Write, FileShare.None);
918 918
919 formatter.Serialize(stream, obj); 919 formatter.Serialize(stream, obj);
920 } 920 }
921 catch (Exception e) 921 catch (Exception e)
922 { 922 {
923 m_log.Error(e.ToString()); 923 m_log.Error(e.ToString());
924 } 924 }
925 finally 925 finally
926 { 926 {
927 if (stream != null) 927 if (stream != null)
928 { 928 {
929 stream.Close(); 929 stream.Close();
930 } 930 }
931 } 931 }
932 } 932 }
933 933
934 public static Object DeserializeFromFile(string filename) 934 public static Object DeserializeFromFile(string filename)
935 { 935 {
936 IFormatter formatter = new BinaryFormatter(); 936 IFormatter formatter = new BinaryFormatter();
937 Stream stream = null; 937 Stream stream = null;
938 Object ret = null; 938 Object ret = null;
939 939
940 try 940 try
941 { 941 {
942 stream = new FileStream( 942 stream = new FileStream(
943 filename, FileMode.Open, 943 filename, FileMode.Open,
944 FileAccess.Read, FileShare.None); 944 FileAccess.Read, FileShare.None);
945 945
946 ret = formatter.Deserialize(stream); 946 ret = formatter.Deserialize(stream);
947 } 947 }
948 catch (Exception e) 948 catch (Exception e)
949 { 949 {
950 m_log.Error(e.ToString()); 950 m_log.Error(e.ToString());
951 } 951 }
952 finally 952 finally
953 { 953 {
954 if (stream != null) 954 if (stream != null)
955 { 955 {
956 stream.Close(); 956 stream.Close();
957 } 957 }
958 } 958 }
959 959
960 return ret; 960 return ret;
961 } 961 }
962 962
963 public static string Compress(string text) 963 public static string Compress(string text)
964 { 964 {
965 byte[] buffer = Util.UTF8.GetBytes(text); 965 byte[] buffer = Util.UTF8.GetBytes(text);
966 MemoryStream memory = new MemoryStream(); 966 MemoryStream memory = new MemoryStream();
967 using (GZipStream compressor = new GZipStream(memory, CompressionMode.Compress, true)) 967 using (GZipStream compressor = new GZipStream(memory, CompressionMode.Compress, true))
968 { 968 {
969 compressor.Write(buffer, 0, buffer.Length); 969 compressor.Write(buffer, 0, buffer.Length);
970 } 970 }
971 971
972 memory.Position = 0; 972 memory.Position = 0;
973 973
974 byte[] compressed = new byte[memory.Length]; 974 byte[] compressed = new byte[memory.Length];
975 memory.Read(compressed, 0, compressed.Length); 975 memory.Read(compressed, 0, compressed.Length);
976 976
977 byte[] compressedBuffer = new byte[compressed.Length + 4]; 977 byte[] compressedBuffer = new byte[compressed.Length + 4];
978 Buffer.BlockCopy(compressed, 0, compressedBuffer, 4, compressed.Length); 978 Buffer.BlockCopy(compressed, 0, compressedBuffer, 4, compressed.Length);
979 Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, compressedBuffer, 0, 4); 979 Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, compressedBuffer, 0, 4);
980 return Convert.ToBase64String(compressedBuffer); 980 return Convert.ToBase64String(compressedBuffer);
981 } 981 }
982 982
983 public static string Decompress(string compressedText) 983 public static string Decompress(string compressedText)
984 { 984 {
985 byte[] compressedBuffer = Convert.FromBase64String(compressedText); 985 byte[] compressedBuffer = Convert.FromBase64String(compressedText);
986 using (MemoryStream memory = new MemoryStream()) 986 using (MemoryStream memory = new MemoryStream())
987 { 987 {
988 int msgLength = BitConverter.ToInt32(compressedBuffer, 0); 988 int msgLength = BitConverter.ToInt32(compressedBuffer, 0);
989 memory.Write(compressedBuffer, 4, compressedBuffer.Length - 4); 989 memory.Write(compressedBuffer, 4, compressedBuffer.Length - 4);
990 990
991 byte[] buffer = new byte[msgLength]; 991 byte[] buffer = new byte[msgLength];
992 992
993 memory.Position = 0; 993 memory.Position = 0;
994 using (GZipStream decompressor = new GZipStream(memory, CompressionMode.Decompress)) 994 using (GZipStream decompressor = new GZipStream(memory, CompressionMode.Decompress))
995 { 995 {
996 decompressor.Read(buffer, 0, buffer.Length); 996 decompressor.Read(buffer, 0, buffer.Length);
997 } 997 }
998 998
999 return Util.UTF8.GetString(buffer); 999 return Util.UTF8.GetString(buffer);
1000 } 1000 }
1001 } 1001 }
1002 1002
1003 public static XmlRpcResponse XmlRpcCommand(string url, string methodName, params object[] args) 1003 public static XmlRpcResponse XmlRpcCommand(string url, string methodName, params object[] args)
1004 { 1004 {
1005 return SendXmlRpcCommand(url, methodName, args); 1005 return SendXmlRpcCommand(url, methodName, args);
1006 } 1006 }
1007 1007
1008 public static XmlRpcResponse SendXmlRpcCommand(string url, string methodName, object[] args) 1008 public static XmlRpcResponse SendXmlRpcCommand(string url, string methodName, object[] args)
1009 { 1009 {
1010 XmlRpcRequest client = new XmlRpcRequest(methodName, args); 1010 XmlRpcRequest client = new XmlRpcRequest(methodName, args);
1011 return client.Send(url, 6000); 1011 return client.Send(url, 6000);
1012 } 1012 }
1013 1013
1014 /// <summary> 1014 /// <summary>
1015 /// Returns an error message that the user could not be found in the database 1015 /// Returns an error message that the user could not be found in the database
1016 /// </summary> 1016 /// </summary>
1017 /// <returns>XML string consisting of a error element containing individual error(s)</returns> 1017 /// <returns>XML string consisting of a error element containing individual error(s)</returns>
1018 public static XmlRpcResponse CreateUnknownUserErrorResponse() 1018 public static XmlRpcResponse CreateUnknownUserErrorResponse()
1019 { 1019 {
1020 XmlRpcResponse response = new XmlRpcResponse(); 1020 XmlRpcResponse response = new XmlRpcResponse();
1021 Hashtable responseData = new Hashtable(); 1021 Hashtable responseData = new Hashtable();
1022 responseData["error_type"] = "unknown_user"; 1022 responseData["error_type"] = "unknown_user";
1023 responseData["error_desc"] = "The user requested is not in the database"; 1023 responseData["error_desc"] = "The user requested is not in the database";
1024 1024
1025 response.Value = responseData; 1025 response.Value = responseData;
1026 return response; 1026 return response;
1027 } 1027 }
1028 1028
1029 /// <summary> 1029 /// <summary>
1030 /// Converts a byte array in big endian order into an ulong. 1030 /// Converts a byte array in big endian order into an ulong.
1031 /// </summary> 1031 /// </summary>
1032 /// <param name="bytes"> 1032 /// <param name="bytes">
1033 /// The array of bytes 1033 /// The array of bytes
1034 /// </param> 1034 /// </param>
1035 /// <returns> 1035 /// <returns>
1036 /// The extracted ulong 1036 /// The extracted ulong
1037 /// </returns> 1037 /// </returns>
1038 public static ulong BytesToUInt64Big(byte[] bytes) 1038 public static ulong BytesToUInt64Big(byte[] bytes)
1039 { 1039 {
1040 if (bytes.Length < 8) return 0; 1040 if (bytes.Length < 8) return 0;
1041 return ((ulong)bytes[0] << 56) | ((ulong)bytes[1] << 48) | ((ulong)bytes[2] << 40) | ((ulong)bytes[3] << 32) | 1041 return ((ulong)bytes[0] << 56) | ((ulong)bytes[1] << 48) | ((ulong)bytes[2] << 40) | ((ulong)bytes[3] << 32) |
1042 ((ulong)bytes[4] << 24) | ((ulong)bytes[5] << 16) | ((ulong)bytes[6] << 8) | (ulong)bytes[7]; 1042 ((ulong)bytes[4] << 24) | ((ulong)bytes[5] << 16) | ((ulong)bytes[6] << 8) | (ulong)bytes[7];
1043 } 1043 }
1044 1044
1045 // used for RemoteParcelRequest (for "About Landmark") 1045 // used for RemoteParcelRequest (for "About Landmark")
1046 public static UUID BuildFakeParcelID(ulong regionHandle, uint x, uint y) 1046 public static UUID BuildFakeParcelID(ulong regionHandle, uint x, uint y)
1047 { 1047 {
1048 byte[] bytes = 1048 byte[] bytes =
1049 { 1049 {
1050 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24), 1050 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
1051 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56), 1051 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56),
1052 (byte)x, (byte)(x >> 8), 0, 0, 1052 (byte)x, (byte)(x >> 8), 0, 0,
1053 (byte)y, (byte)(y >> 8), 0, 0 }; 1053 (byte)y, (byte)(y >> 8), 0, 0 };
1054 return new UUID(bytes, 0); 1054 return new UUID(bytes, 0);
1055 } 1055 }
1056 1056
1057 public static UUID BuildFakeParcelID(ulong regionHandle, uint x, uint y, uint z) 1057 public static UUID BuildFakeParcelID(ulong regionHandle, uint x, uint y, uint z)
1058 { 1058 {
1059 byte[] bytes = 1059 byte[] bytes =
1060 { 1060 {
1061 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24), 1061 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
1062 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56), 1062 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56),
1063 (byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8), 1063 (byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8),
1064 (byte)y, (byte)(y >> 8), 0, 0 }; 1064 (byte)y, (byte)(y >> 8), 0, 0 };
1065 return new UUID(bytes, 0); 1065 return new UUID(bytes, 0);
1066 } 1066 }
1067 1067
1068 public static void ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y) 1068 public static void ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y)
1069 { 1069 {
1070 byte[] bytes = parcelID.GetBytes(); 1070 byte[] bytes = parcelID.GetBytes();
1071 regionHandle = Utils.BytesToUInt64(bytes); 1071 regionHandle = Utils.BytesToUInt64(bytes);
1072 x = Utils.BytesToUInt(bytes, 8) & 0xffff; 1072 x = Utils.BytesToUInt(bytes, 8) & 0xffff;
1073 y = Utils.BytesToUInt(bytes, 12) & 0xffff; 1073 y = Utils.BytesToUInt(bytes, 12) & 0xffff;
1074 } 1074 }
1075 1075
1076 public static void ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y, out uint z) 1076 public static void ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y, out uint z)
1077 { 1077 {
1078 byte[] bytes = parcelID.GetBytes(); 1078 byte[] bytes = parcelID.GetBytes();
1079 regionHandle = Utils.BytesToUInt64(bytes); 1079 regionHandle = Utils.BytesToUInt64(bytes);
1080 x = Utils.BytesToUInt(bytes, 8) & 0xffff; 1080 x = Utils.BytesToUInt(bytes, 8) & 0xffff;
1081 z = (Utils.BytesToUInt(bytes, 8) & 0xffff0000) >> 16; 1081 z = (Utils.BytesToUInt(bytes, 8) & 0xffff0000) >> 16;
1082 y = Utils.BytesToUInt(bytes, 12) & 0xffff; 1082 y = Utils.BytesToUInt(bytes, 12) & 0xffff;
1083 } 1083 }
1084 1084
1085 public static void FakeParcelIDToGlobalPosition(UUID parcelID, out uint x, out uint y) 1085 public static void FakeParcelIDToGlobalPosition(UUID parcelID, out uint x, out uint y)
1086 { 1086 {
1087 ulong regionHandle; 1087 ulong regionHandle;
1088 uint rx, ry; 1088 uint rx, ry;
1089 1089
1090 ParseFakeParcelID(parcelID, out regionHandle, out x, out y); 1090 ParseFakeParcelID(parcelID, out regionHandle, out x, out y);
1091 Utils.LongToUInts(regionHandle, out rx, out ry); 1091 Utils.LongToUInts(regionHandle, out rx, out ry);
1092 1092
1093 x += rx; 1093 x += rx;
1094 y += ry; 1094 y += ry;
1095 } 1095 }
1096 1096
1097 /// <summary> 1097 /// <summary>
1098 /// Get operating system information if available. Returns only the first 45 characters of information 1098 /// Get operating system information if available. Returns only the first 45 characters of information
1099 /// </summary> 1099 /// </summary>
1100 /// <returns> 1100 /// <returns>
1101 /// Operating system information. Returns an empty string if none was available. 1101 /// Operating system information. Returns an empty string if none was available.
1102 /// </returns> 1102 /// </returns>
1103 public static string GetOperatingSystemInformation() 1103 public static string GetOperatingSystemInformation()
1104 { 1104 {
1105 string os = String.Empty; 1105 string os = String.Empty;
1106 1106
1107 if (Environment.OSVersion.Platform != PlatformID.Unix) 1107 if (Environment.OSVersion.Platform != PlatformID.Unix)
1108 { 1108 {
1109 os = Environment.OSVersion.ToString(); 1109 os = Environment.OSVersion.ToString();
1110 } 1110 }
1111 else 1111 else
1112 { 1112 {
1113 os = ReadEtcIssue(); 1113 os = ReadEtcIssue();
1114 } 1114 }
1115 1115
1116 if (os.Length > 45) 1116 if (os.Length > 45)
1117 { 1117 {
1118 os = os.Substring(0, 45); 1118 os = os.Substring(0, 45);
1119 } 1119 }
1120 1120
1121 return os; 1121 return os;
1122 } 1122 }
1123 1123
1124 public static string GetRuntimeInformation() 1124 public static string GetRuntimeInformation()
1125 { 1125 {
1126 string ru = String.Empty; 1126 string ru = String.Empty;
1127 1127
1128 if (Environment.OSVersion.Platform == PlatformID.Unix) 1128 if (Environment.OSVersion.Platform == PlatformID.Unix)
1129 ru = "Unix/Mono"; 1129 ru = "Unix/Mono";
1130 else 1130 else
1131 if (Environment.OSVersion.Platform == PlatformID.MacOSX) 1131 if (Environment.OSVersion.Platform == PlatformID.MacOSX)
1132 ru = "OSX/Mono"; 1132 ru = "OSX/Mono";
1133 else 1133 else
1134 { 1134 {
1135 if (Type.GetType("Mono.Runtime") != null) 1135 if (Type.GetType("Mono.Runtime") != null)
1136 ru = "Win/Mono"; 1136 ru = "Win/Mono";
1137 else 1137 else
1138 ru = "Win/.NET"; 1138 ru = "Win/.NET";
1139 } 1139 }
1140 1140
1141 return ru; 1141 return ru;
1142 } 1142 }
1143 1143
1144 /// <summary> 1144 /// <summary>
1145 /// Is the given string a UUID? 1145 /// Is the given string a UUID?
1146 /// </summary> 1146 /// </summary>
1147 /// <param name="s"></param> 1147 /// <param name="s"></param>
1148 /// <returns></returns> 1148 /// <returns></returns>
1149 public static bool isUUID(string s) 1149 public static bool isUUID(string s)
1150 { 1150 {
1151 return UUIDPattern.IsMatch(s); 1151 return UUIDPattern.IsMatch(s);
1152 } 1152 }
1153 1153
1154 public static string GetDisplayConnectionString(string connectionString) 1154 public static string GetDisplayConnectionString(string connectionString)
1155 { 1155 {
1156 int passPosition = 0; 1156 int passPosition = 0;
1157 int passEndPosition = 0; 1157 int passEndPosition = 0;
1158 string displayConnectionString = null; 1158 string displayConnectionString = null;
1159 1159
1160 // hide the password in the connection string 1160 // hide the password in the connection string
1161 passPosition = connectionString.IndexOf("password", StringComparison.OrdinalIgnoreCase); 1161 passPosition = connectionString.IndexOf("password", StringComparison.OrdinalIgnoreCase);
1162 passPosition = connectionString.IndexOf("=", passPosition); 1162 passPosition = connectionString.IndexOf("=", passPosition);
1163 if (passPosition < connectionString.Length) 1163 if (passPosition < connectionString.Length)
1164 passPosition += 1; 1164 passPosition += 1;
1165 passEndPosition = connectionString.IndexOf(";", passPosition); 1165 passEndPosition = connectionString.IndexOf(";", passPosition);
1166 1166
1167 displayConnectionString = connectionString.Substring(0, passPosition); 1167 displayConnectionString = connectionString.Substring(0, passPosition);
1168 displayConnectionString += "***"; 1168 displayConnectionString += "***";
1169 displayConnectionString += connectionString.Substring(passEndPosition, connectionString.Length - passEndPosition); 1169 displayConnectionString += connectionString.Substring(passEndPosition, connectionString.Length - passEndPosition);
1170 1170
1171 return displayConnectionString; 1171 return displayConnectionString;
1172 } 1172 }
1173 1173
1174 public static T ReadSettingsFromIniFile<T>(IConfig config, T settingsClass) 1174 public static T ReadSettingsFromIniFile<T>(IConfig config, T settingsClass)
1175 { 1175 {
1176 Type settingsType = settingsClass.GetType(); 1176 Type settingsType = settingsClass.GetType();
1177 1177
1178 FieldInfo[] fieldInfos = settingsType.GetFields(); 1178 FieldInfo[] fieldInfos = settingsType.GetFields();
1179 foreach (FieldInfo fieldInfo in fieldInfos) 1179 foreach (FieldInfo fieldInfo in fieldInfos)
1180 { 1180 {
1181 if (!fieldInfo.IsStatic) 1181 if (!fieldInfo.IsStatic)
1182 { 1182 {
1183 if (fieldInfo.FieldType == typeof(System.String)) 1183 if (fieldInfo.FieldType == typeof(System.String))
1184 { 1184 {
1185 fieldInfo.SetValue(settingsClass, config.Get(fieldInfo.Name, (string)fieldInfo.GetValue(settingsClass))); 1185 fieldInfo.SetValue(settingsClass, config.Get(fieldInfo.Name, (string)fieldInfo.GetValue(settingsClass)));
1186 } 1186 }
1187 else if (fieldInfo.FieldType == typeof(System.Boolean)) 1187 else if (fieldInfo.FieldType == typeof(System.Boolean))
1188 { 1188 {
1189 fieldInfo.SetValue(settingsClass, config.GetBoolean(fieldInfo.Name, (bool)fieldInfo.GetValue(settingsClass))); 1189 fieldInfo.SetValue(settingsClass, config.GetBoolean(fieldInfo.Name, (bool)fieldInfo.GetValue(settingsClass)));
1190 } 1190 }
1191 else if (fieldInfo.FieldType == typeof(System.Int32)) 1191 else if (fieldInfo.FieldType == typeof(System.Int32))
1192 { 1192 {
1193 fieldInfo.SetValue(settingsClass, config.GetInt(fieldInfo.Name, (int)fieldInfo.GetValue(settingsClass))); 1193 fieldInfo.SetValue(settingsClass, config.GetInt(fieldInfo.Name, (int)fieldInfo.GetValue(settingsClass)));
1194 } 1194 }
1195 else if (fieldInfo.FieldType == typeof(System.Single)) 1195 else if (fieldInfo.FieldType == typeof(System.Single))
1196 { 1196 {
1197 fieldInfo.SetValue(settingsClass, config.GetFloat(fieldInfo.Name, (float)fieldInfo.GetValue(settingsClass))); 1197 fieldInfo.SetValue(settingsClass, config.GetFloat(fieldInfo.Name, (float)fieldInfo.GetValue(settingsClass)));
1198 } 1198 }
1199 else if (fieldInfo.FieldType == typeof(System.UInt32)) 1199 else if (fieldInfo.FieldType == typeof(System.UInt32))
1200 { 1200 {
1201 fieldInfo.SetValue(settingsClass, Convert.ToUInt32(config.Get(fieldInfo.Name, ((uint)fieldInfo.GetValue(settingsClass)).ToString()))); 1201 fieldInfo.SetValue(settingsClass, Convert.ToUInt32(config.Get(fieldInfo.Name, ((uint)fieldInfo.GetValue(settingsClass)).ToString())));
1202 } 1202 }
1203 } 1203 }
1204 } 1204 }
1205 1205
1206 PropertyInfo[] propertyInfos = settingsType.GetProperties(); 1206 PropertyInfo[] propertyInfos = settingsType.GetProperties();
1207 foreach (PropertyInfo propInfo in propertyInfos) 1207 foreach (PropertyInfo propInfo in propertyInfos)
1208 { 1208 {
1209 if ((propInfo.CanRead) && (propInfo.CanWrite)) 1209 if ((propInfo.CanRead) && (propInfo.CanWrite))
1210 { 1210 {
1211 if (propInfo.PropertyType == typeof(System.String)) 1211 if (propInfo.PropertyType == typeof(System.String))
1212 { 1212 {
1213 propInfo.SetValue(settingsClass, config.Get(propInfo.Name, (string)propInfo.GetValue(settingsClass, null)), null); 1213 propInfo.SetValue(settingsClass, config.Get(propInfo.Name, (string)propInfo.GetValue(settingsClass, null)), null);
1214 } 1214 }
1215 else if (propInfo.PropertyType == typeof(System.Boolean)) 1215 else if (propInfo.PropertyType == typeof(System.Boolean))
1216 { 1216 {
1217 propInfo.SetValue(settingsClass, config.GetBoolean(propInfo.Name, (bool)propInfo.GetValue(settingsClass, null)), null); 1217 propInfo.SetValue(settingsClass, config.GetBoolean(propInfo.Name, (bool)propInfo.GetValue(settingsClass, null)), null);
1218 } 1218 }
1219 else if (propInfo.PropertyType == typeof(System.Int32)) 1219 else if (propInfo.PropertyType == typeof(System.Int32))
1220 { 1220 {
1221 propInfo.SetValue(settingsClass, config.GetInt(propInfo.Name, (int)propInfo.GetValue(settingsClass, null)), null); 1221 propInfo.SetValue(settingsClass, config.GetInt(propInfo.Name, (int)propInfo.GetValue(settingsClass, null)), null);
1222 } 1222 }
1223 else if (propInfo.PropertyType == typeof(System.Single)) 1223 else if (propInfo.PropertyType == typeof(System.Single))
1224 { 1224 {
1225 propInfo.SetValue(settingsClass, config.GetFloat(propInfo.Name, (float)propInfo.GetValue(settingsClass, null)), null); 1225 propInfo.SetValue(settingsClass, config.GetFloat(propInfo.Name, (float)propInfo.GetValue(settingsClass, null)), null);
1226 } 1226 }
1227 if (propInfo.PropertyType == typeof(System.UInt32)) 1227 if (propInfo.PropertyType == typeof(System.UInt32))
1228 { 1228 {
1229 propInfo.SetValue(settingsClass, Convert.ToUInt32(config.Get(propInfo.Name, ((uint)propInfo.GetValue(settingsClass, null)).ToString())), null); 1229 propInfo.SetValue(settingsClass, Convert.ToUInt32(config.Get(propInfo.Name, ((uint)propInfo.GetValue(settingsClass, null)).ToString())), null);
1230 } 1230 }
1231 } 1231 }
1232 } 1232 }
1233 1233
1234 return settingsClass; 1234 return settingsClass;
1235 } 1235 }
1236 1236
1237 public static string Base64ToString(string str) 1237 public static string Base64ToString(string str)
1238 { 1238 {
1239 UTF8Encoding encoder = new UTF8Encoding(); 1239 UTF8Encoding encoder = new UTF8Encoding();
1240 Decoder utf8Decode = encoder.GetDecoder(); 1240 Decoder utf8Decode = encoder.GetDecoder();
1241 1241
1242 byte[] todecode_byte = Convert.FromBase64String(str); 1242 byte[] todecode_byte = Convert.FromBase64String(str);
1243 int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length); 1243 int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
1244 char[] decoded_char = new char[charCount]; 1244 char[] decoded_char = new char[charCount];
1245 utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0); 1245 utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
1246 string result = new String(decoded_char); 1246 string result = new String(decoded_char);
1247 return result; 1247 return result;
1248 } 1248 }
1249 1249
1250 public static Guid GetHashGuid(string data, string salt) 1250 public static Guid GetHashGuid(string data, string salt)
1251 { 1251 {
1252 byte[] hash = ComputeMD5Hash(data + salt); 1252 byte[] hash = ComputeMD5Hash(data + salt);
1253 1253
1254 //string s = BitConverter.ToString(hash); 1254 //string s = BitConverter.ToString(hash);
1255 1255
1256 Guid guid = new Guid(hash); 1256 Guid guid = new Guid(hash);
1257 1257
1258 return guid; 1258 return guid;
1259 } 1259 }
1260 1260
1261 public static byte ConvertMaturityToAccessLevel(uint maturity) 1261 public static byte ConvertMaturityToAccessLevel(uint maturity)
1262 { 1262 {
1263 byte retVal = 0; 1263 byte retVal = 0;
1264 switch (maturity) 1264 switch (maturity)
1265 { 1265 {
1266 case 0: //PG 1266 case 0: //PG
1267 retVal = 13; 1267 retVal = 13;
1268 break; 1268 break;
1269 case 1: //Mature 1269 case 1: //Mature
1270 retVal = 21; 1270 retVal = 21;
1271 break; 1271 break;
1272 case 2: // Adult 1272 case 2: // Adult
1273 retVal = 42; 1273 retVal = 42;
1274 break; 1274 break;
1275 } 1275 }
1276 1276
1277 return retVal; 1277 return retVal;
1278 1278
1279 } 1279 }
1280 1280
1281 public static uint ConvertAccessLevelToMaturity(byte maturity) 1281 public static uint ConvertAccessLevelToMaturity(byte maturity)
1282 { 1282 {
1283 if (maturity <= 13) 1283 if (maturity <= 13)
1284 return 0; 1284 return 0;
1285 else if (maturity <= 21) 1285 else if (maturity <= 21)
1286 return 1; 1286 return 1;
1287 else 1287 else
1288 return 2; 1288 return 2;
1289 } 1289 }
1290 1290
1291 /// <summary> 1291 /// <summary>
1292 /// Produces an OSDMap from its string representation on a stream 1292 /// Produces an OSDMap from its string representation on a stream
1293 /// </summary> 1293 /// </summary>
1294 /// <param name="data">The stream</param> 1294 /// <param name="data">The stream</param>
1295 /// <param name="length">The size of the data on the stream</param> 1295 /// <param name="length">The size of the data on the stream</param>
1296 /// <returns>The OSDMap or an exception</returns> 1296 /// <returns>The OSDMap or an exception</returns>
1297 public static OSDMap GetOSDMap(Stream stream, int length) 1297 public static OSDMap GetOSDMap(Stream stream, int length)
1298 { 1298 {
1299 byte[] data = new byte[length]; 1299 byte[] data = new byte[length];
1300 stream.Read(data, 0, length); 1300 stream.Read(data, 0, length);
1301 string strdata = Util.UTF8.GetString(data); 1301 string strdata = Util.UTF8.GetString(data);
1302 OSDMap args = null; 1302 OSDMap args = null;
1303 OSD buffer; 1303 OSD buffer;
1304 buffer = OSDParser.DeserializeJson(strdata); 1304 buffer = OSDParser.DeserializeJson(strdata);
1305 if (buffer.Type == OSDType.Map) 1305 if (buffer.Type == OSDType.Map)
1306 { 1306 {
1307 args = (OSDMap)buffer; 1307 args = (OSDMap)buffer;
1308 return args; 1308 return args;
1309 } 1309 }
1310 return null; 1310 return null;
1311 } 1311 }
1312 1312
1313 public static OSDMap GetOSDMap(string data) 1313 public static OSDMap GetOSDMap(string data)
1314 { 1314 {
1315 OSDMap args = null; 1315 OSDMap args = null;
1316 try 1316 try
1317 { 1317 {
1318 OSD buffer; 1318 OSD buffer;
1319 // We should pay attention to the content-type, but let's assume we know it's Json 1319 // We should pay attention to the content-type, but let's assume we know it's Json
1320 buffer = OSDParser.DeserializeJson(data); 1320 buffer = OSDParser.DeserializeJson(data);
1321 if (buffer.Type == OSDType.Map) 1321 if (buffer.Type == OSDType.Map)
1322 { 1322 {
1323 args = (OSDMap)buffer; 1323 args = (OSDMap)buffer;
1324 return args; 1324 return args;
1325 } 1325 }
1326 else 1326 else
1327 { 1327 {
1328 // uh? 1328 // uh?
1329 m_log.Debug(("[UTILS]: Got OSD of unexpected type " + buffer.Type.ToString())); 1329 m_log.Debug(("[UTILS]: Got OSD of unexpected type " + buffer.Type.ToString()));
1330 return null; 1330 return null;
1331 } 1331 }
1332 } 1332 }
1333 catch (Exception ex) 1333 catch (Exception ex)
1334 { 1334 {
1335 m_log.Debug("[UTILS]: exception on GetOSDMap " + ex.Message); 1335 m_log.Debug("[UTILS]: exception on GetOSDMap " + ex.Message);
1336 return null; 1336 return null;
1337 } 1337 }
1338 } 1338 }
1339 1339
1340 public static string[] Glob(string path) 1340 public static string[] Glob(string path)
1341 { 1341 {
1342 string vol=String.Empty; 1342 string vol=String.Empty;
1343 1343
1344 if (Path.VolumeSeparatorChar != Path.DirectorySeparatorChar) 1344 if (Path.VolumeSeparatorChar != Path.DirectorySeparatorChar)
1345 { 1345 {
1346 string[] vcomps = path.Split(new char[] {Path.VolumeSeparatorChar}, 2, StringSplitOptions.RemoveEmptyEntries); 1346 string[] vcomps = path.Split(new char[] {Path.VolumeSeparatorChar}, 2, StringSplitOptions.RemoveEmptyEntries);
1347 1347
1348 if (vcomps.Length > 1) 1348 if (vcomps.Length > 1)
1349 { 1349 {
1350 path = vcomps[1]; 1350 path = vcomps[1];
1351 vol = vcomps[0]; 1351 vol = vcomps[0];
1352 } 1352 }
1353 } 1353 }
1354 1354
1355 string[] comps = path.Split(new char[] {Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar}, StringSplitOptions.RemoveEmptyEntries); 1355 string[] comps = path.Split(new char[] {Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar}, StringSplitOptions.RemoveEmptyEntries);
1356 1356
1357 // Glob 1357 // Glob
1358 1358
1359 path = vol; 1359 path = vol;
1360 if (vol != String.Empty) 1360 if (vol != String.Empty)
1361 path += new String(new char[] {Path.VolumeSeparatorChar, Path.DirectorySeparatorChar}); 1361 path += new String(new char[] {Path.VolumeSeparatorChar, Path.DirectorySeparatorChar});
1362 else 1362 else
1363 path = new String(new char[] {Path.DirectorySeparatorChar}); 1363 path = new String(new char[] {Path.DirectorySeparatorChar});
1364 1364
1365 List<string> paths = new List<string>(); 1365 List<string> paths = new List<string>();
1366 List<string> found = new List<string>(); 1366 List<string> found = new List<string>();
1367 paths.Add(path); 1367 paths.Add(path);
1368 1368
1369 int compIndex = -1; 1369 int compIndex = -1;
1370 foreach (string c in comps) 1370 foreach (string c in comps)
1371 { 1371 {
1372 compIndex++; 1372 compIndex++;
1373 1373
1374 List<string> addpaths = new List<string>(); 1374 List<string> addpaths = new List<string>();
1375 foreach (string p in paths) 1375 foreach (string p in paths)
1376 { 1376 {
1377 string[] dirs = Directory.GetDirectories(p, c); 1377 string[] dirs = Directory.GetDirectories(p, c);
1378 1378
1379 if (dirs.Length != 0) 1379 if (dirs.Length != 0)
1380 { 1380 {
1381 foreach (string dir in dirs) 1381 foreach (string dir in dirs)
1382 addpaths.Add(Path.Combine(path, dir)); 1382 addpaths.Add(Path.Combine(path, dir));
1383 } 1383 }
1384 1384
1385 // Only add files if that is the last path component 1385 // Only add files if that is the last path component
1386 if (compIndex == comps.Length - 1) 1386 if (compIndex == comps.Length - 1)
1387 { 1387 {
1388 string[] files = Directory.GetFiles(p, c); 1388 string[] files = Directory.GetFiles(p, c);
1389 foreach (string f in files) 1389 foreach (string f in files)
1390 found.Add(f); 1390 found.Add(f);
1391 } 1391 }
1392 } 1392 }
1393 paths = addpaths; 1393 paths = addpaths;
1394 } 1394 }
1395 1395
1396 return found.ToArray(); 1396 return found.ToArray();
1397 } 1397 }
1398 1398
1399 public static string ServerURI(string uri) 1399 public static string ServerURI(string uri)
1400 { 1400 {
1401 if (uri == string.Empty) 1401 if (uri == string.Empty)
1402 return string.Empty; 1402 return string.Empty;
1403 1403
1404 // Get rid of eventual slashes at the end 1404 // Get rid of eventual slashes at the end
1405 uri = uri.TrimEnd('/'); 1405 uri = uri.TrimEnd('/');
1406 1406
1407 IPAddress ipaddr1 = null; 1407 IPAddress ipaddr1 = null;
1408 string port1 = ""; 1408 string port1 = "";
1409 try 1409 try
1410 { 1410 {
1411 ipaddr1 = Util.GetHostFromURL(uri); 1411 ipaddr1 = Util.GetHostFromURL(uri);
1412 } 1412 }
1413 catch { } 1413 catch { }
1414 1414
1415 try 1415 try
1416 { 1416 {
1417 port1 = uri.Split(new char[] { ':' })[2]; 1417 port1 = uri.Split(new char[] { ':' })[2];
1418 } 1418 }
1419 catch { } 1419 catch { }
1420 1420
1421 // We tried our best to convert the domain names to IP addresses 1421 // We tried our best to convert the domain names to IP addresses
1422 return (ipaddr1 != null) ? "http://" + ipaddr1.ToString() + ":" + port1 : uri; 1422 return (ipaddr1 != null) ? "http://" + ipaddr1.ToString() + ":" + port1 : uri;
1423 } 1423 }
1424 1424
1425 /// <summary> 1425 /// <summary>
1426 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 256 bytes if necessary. 1426 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 256 bytes if necessary.
1427 /// </summary> 1427 /// </summary>
1428 /// <param name="str"> 1428 /// <param name="str">
1429 /// If null or empty, then an bytes[0] is returned. 1429 /// If null or empty, then an bytes[0] is returned.
1430 /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0] 1430 /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0]
1431 /// </param> 1431 /// </param>
1432 /// <param name="args"> 1432 /// <param name="args">
1433 /// Arguments to substitute into the string via the {} mechanism. 1433 /// Arguments to substitute into the string via the {} mechanism.
1434 /// </param> 1434 /// </param>
1435 /// <returns></returns> 1435 /// <returns></returns>
1436 public static byte[] StringToBytes256(string str, params object[] args) 1436 public static byte[] StringToBytes256(string str, params object[] args)
1437 { 1437 {
1438 return StringToBytes256(string.Format(str, args)); 1438 return StringToBytes256(string.Format(str, args));
1439 } 1439 }
1440 1440
1441 /// <summary> 1441 /// <summary>
1442 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 256 bytes if necessary. 1442 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 256 bytes if necessary.
1443 /// </summary> 1443 /// </summary>
1444 /// <param name="str"> 1444 /// <param name="str">
1445 /// If null or empty, then an bytes[0] is returned. 1445 /// If null or empty, then an bytes[0] is returned.
1446 /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0] 1446 /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0]
1447 /// </param> 1447 /// </param>
1448 /// <returns></returns> 1448 /// <returns></returns>
1449 public static byte[] StringToBytes256(string str) 1449 public static byte[] StringToBytes256(string str)
1450 { 1450 {
1451 if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; } 1451 if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; }
1452 if (str.Length > 254) str = str.Remove(254); 1452 if (str.Length > 254) str = str.Remove(254);
1453 if (!str.EndsWith("\0")) { str += "\0"; } 1453 if (!str.EndsWith("\0")) { str += "\0"; }
1454 1454
1455 // Because this is UTF-8 encoding and not ASCII, it's possible we 1455 // Because this is UTF-8 encoding and not ASCII, it's possible we
1456 // might have gotten an oversized array even after the string trim 1456 // might have gotten an oversized array even after the string trim
1457 byte[] data = UTF8.GetBytes(str); 1457 byte[] data = UTF8.GetBytes(str);
1458 if (data.Length > 256) 1458 if (data.Length > 256)
1459 { 1459 {
1460 Array.Resize<byte>(ref data, 256); 1460 Array.Resize<byte>(ref data, 256);
1461 data[255] = 0; 1461 data[255] = 0;
1462 } 1462 }
1463 1463
1464 return data; 1464 return data;
1465 } 1465 }
1466 1466
1467 /// <summary> 1467 /// <summary>
1468 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 1024 bytes if necessary. 1468 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 1024 bytes if necessary.
1469 /// </summary> 1469 /// </summary>
1470 /// <param name="str"> 1470 /// <param name="str">
1471 /// If null or empty, then an bytes[0] is returned. 1471 /// If null or empty, then an bytes[0] is returned.
1472 /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0] 1472 /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0]
1473 /// </param> 1473 /// </param>
1474 /// <param name="args"> 1474 /// <param name="args">
1475 /// Arguments to substitute into the string via the {} mechanism. 1475 /// Arguments to substitute into the string via the {} mechanism.
1476 /// </param> 1476 /// </param>
1477 /// <returns></returns> 1477 /// <returns></returns>
1478 public static byte[] StringToBytes1024(string str, params object[] args) 1478 public static byte[] StringToBytes1024(string str, params object[] args)
1479 { 1479 {
1480 return StringToBytes1024(string.Format(str, args)); 1480 return StringToBytes1024(string.Format(str, args));
1481 } 1481 }
1482 1482
1483 /// <summary> 1483 /// <summary>
1484 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 1024 bytes if necessary. 1484 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 1024 bytes if necessary.
1485 /// </summary> 1485 /// </summary>
1486 /// <param name="str"> 1486 /// <param name="str">
1487 /// If null or empty, then an bytes[0] is returned. 1487 /// If null or empty, then an bytes[0] is returned.
1488 /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0] 1488 /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0]
1489 /// </param> 1489 /// </param>
1490 /// <returns></returns> 1490 /// <returns></returns>
1491 public static byte[] StringToBytes1024(string str) 1491 public static byte[] StringToBytes1024(string str)
1492 { 1492 {
1493 if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; } 1493 if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; }
1494 if (str.Length > 1023) str = str.Remove(1023); 1494 if (str.Length > 1023) str = str.Remove(1023);
1495 if (!str.EndsWith("\0")) { str += "\0"; } 1495 if (!str.EndsWith("\0")) { str += "\0"; }
1496 1496
1497 // Because this is UTF-8 encoding and not ASCII, it's possible we 1497 // Because this is UTF-8 encoding and not ASCII, it's possible we
1498 // might have gotten an oversized array even after the string trim 1498 // might have gotten an oversized array even after the string trim
1499 byte[] data = UTF8.GetBytes(str); 1499 byte[] data = UTF8.GetBytes(str);
1500 if (data.Length > 1024) 1500 if (data.Length > 1024)
1501 { 1501 {
1502 Array.Resize<byte>(ref data, 1024); 1502 Array.Resize<byte>(ref data, 1024);
1503 data[1023] = 0; 1503 data[1023] = 0;
1504 } 1504 }
1505 1505
1506 return data; 1506 return data;
1507 } 1507 }
1508 1508
1509 /// <summary> 1509 /// <summary>
@@ -1525,479 +1525,513 @@ namespace OpenSim.Framework
1525 public static bool Is64BitProcess() 1525 public static bool Is64BitProcess()
1526 { 1526 {
1527 return IntPtr.Size == 8; 1527 return IntPtr.Size == 8;
1528 } 1528 }
1529 1529
1530 #region FireAndForget Threading Pattern 1530 #region FireAndForget Threading Pattern
1531 1531
1532 /// <summary> 1532 /// <summary>
1533 /// Created to work around a limitation in Mono with nested delegates 1533 /// Created to work around a limitation in Mono with nested delegates
1534 /// </summary> 1534 /// </summary>
1535 private sealed class FireAndForgetWrapper 1535 private sealed class FireAndForgetWrapper
1536 { 1536 {
1537 private static volatile FireAndForgetWrapper instance; 1537 private static volatile FireAndForgetWrapper instance;
1538 private static object syncRoot = new Object(); 1538 private static object syncRoot = new Object();
1539 1539
1540 public static FireAndForgetWrapper Instance { 1540 public static FireAndForgetWrapper Instance {
1541 get { 1541 get {
1542 1542
1543 if (instance == null) 1543 if (instance == null)
1544 { 1544 {
1545 lock (syncRoot) 1545 lock (syncRoot)
1546 { 1546 {
1547 if (instance == null) 1547 if (instance == null)
1548 { 1548 {
1549 instance = new FireAndForgetWrapper(); 1549 instance = new FireAndForgetWrapper();
1550 } 1550 }
1551 } 1551 }
1552 } 1552 }
1553 1553
1554 return instance; 1554 return instance;
1555 } 1555 }
1556 } 1556 }
1557 1557
1558 public void FireAndForget(System.Threading.WaitCallback callback) 1558 public void FireAndForget(System.Threading.WaitCallback callback)
1559 { 1559 {
1560 callback.BeginInvoke(null, EndFireAndForget, callback); 1560 callback.BeginInvoke(null, EndFireAndForget, callback);
1561 } 1561 }
1562 1562
1563 public void FireAndForget(System.Threading.WaitCallback callback, object obj) 1563 public void FireAndForget(System.Threading.WaitCallback callback, object obj)
1564 { 1564 {
1565 callback.BeginInvoke(obj, EndFireAndForget, callback); 1565 callback.BeginInvoke(obj, EndFireAndForget, callback);
1566 } 1566 }
1567 1567
1568 private static void EndFireAndForget(IAsyncResult ar) 1568 private static void EndFireAndForget(IAsyncResult ar)
1569 { 1569 {
1570 System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState; 1570 System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState;
1571 1571
1572 try { callback.EndInvoke(ar); } 1572 try { callback.EndInvoke(ar); }
1573 catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); } 1573 catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); }
1574 1574
1575 ar.AsyncWaitHandle.Close(); 1575 ar.AsyncWaitHandle.Close();
1576 } 1576 }
1577 } 1577 }
1578 1578
1579 public static void FireAndForget(System.Threading.WaitCallback callback) 1579 public static void FireAndForget(System.Threading.WaitCallback callback)
1580 { 1580 {
1581 FireAndForget(callback, null); 1581 FireAndForget(callback, null);
1582 } 1582 }
1583 1583
1584 public static void InitThreadPool(int maxThreads) 1584 public static void InitThreadPool(int maxThreads)
1585 { 1585 {
1586 if (maxThreads < 2) 1586 if (maxThreads < 2)
1587 throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2"); 1587 throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2");
1588 if (m_ThreadPool != null) 1588 if (m_ThreadPool != null)
1589 throw new InvalidOperationException("SmartThreadPool is already initialized"); 1589 throw new InvalidOperationException("SmartThreadPool is already initialized");
1590 1590
1591 m_ThreadPool = new SmartThreadPool(2000, maxThreads, 2); 1591 m_ThreadPool = new SmartThreadPool(2000, maxThreads, 2);
1592 } 1592 }
1593 1593
1594 public static int FireAndForgetCount() 1594 public static int FireAndForgetCount()
1595 { 1595 {
1596 const int MAX_SYSTEM_THREADS = 200; 1596 const int MAX_SYSTEM_THREADS = 200;
1597 1597
1598 switch (FireAndForgetMethod) 1598 switch (FireAndForgetMethod)
1599 { 1599 {
1600 case FireAndForgetMethod.UnsafeQueueUserWorkItem: 1600 case FireAndForgetMethod.UnsafeQueueUserWorkItem:
1601 case FireAndForgetMethod.QueueUserWorkItem: 1601 case FireAndForgetMethod.QueueUserWorkItem:
1602 case FireAndForgetMethod.BeginInvoke: 1602 case FireAndForgetMethod.BeginInvoke:
1603 int workerThreads, iocpThreads; 1603 int workerThreads, iocpThreads;
1604 ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads); 1604 ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
1605 return workerThreads; 1605 return workerThreads;
1606 case FireAndForgetMethod.SmartThreadPool: 1606 case FireAndForgetMethod.SmartThreadPool:
1607 return m_ThreadPool.MaxThreads - m_ThreadPool.InUseThreads; 1607 return m_ThreadPool.MaxThreads - m_ThreadPool.InUseThreads;
1608 case FireAndForgetMethod.Thread: 1608 case FireAndForgetMethod.Thread:
1609 return MAX_SYSTEM_THREADS - System.Diagnostics.Process.GetCurrentProcess().Threads.Count; 1609 return MAX_SYSTEM_THREADS - System.Diagnostics.Process.GetCurrentProcess().Threads.Count;
1610 default: 1610 default:
1611 throw new NotImplementedException(); 1611 throw new NotImplementedException();
1612 } 1612 }
1613 } 1613 }
1614 1614
1615 public static void FireAndForget(System.Threading.WaitCallback callback, object obj) 1615 public static void FireAndForget(System.Threading.WaitCallback callback, object obj)
1616 { 1616 {
1617 WaitCallback realCallback; 1617 WaitCallback realCallback;
1618 1618
1619 if (FireAndForgetMethod == FireAndForgetMethod.RegressionTest) 1619 if (FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
1620 { 1620 {
1621 // If we're running regression tests, then we want any exceptions to rise up to the test code. 1621 // If we're running regression tests, then we want any exceptions to rise up to the test code.
1622 realCallback = o => { Culture.SetCurrentCulture(); callback(o); }; 1622 realCallback = o => { Culture.SetCurrentCulture(); callback(o); };
1623 } 1623 }
1624 else 1624 else
1625 { 1625 {
1626 // When OpenSim interacts with a database or sends data over the wire, it must send this in en_US culture 1626 // When OpenSim interacts with a database or sends data over the wire, it must send this in en_US culture
1627 // so that we don't encounter problems where, for instance, data is saved with a culture that uses commas 1627 // so that we don't encounter problems where, for instance, data is saved with a culture that uses commas
1628 // for decimals places but is read by a culture that treats commas as number seperators. 1628 // for decimals places but is read by a culture that treats commas as number seperators.
1629 realCallback = o => 1629 realCallback = o =>
1630 { 1630 {
1631 Culture.SetCurrentCulture(); 1631 Culture.SetCurrentCulture();
1632 1632
1633 try 1633 try
1634 { 1634 {
1635 callback(o); 1635 callback(o);
1636 } 1636 }
1637 catch (Exception e) 1637 catch (Exception e)
1638 { 1638 {
1639 m_log.ErrorFormat( 1639 m_log.ErrorFormat(
1640 "[UTIL]: Continuing after async_call_method thread terminated with exception {0}{1}", 1640 "[UTIL]: Continuing after async_call_method thread terminated with exception {0}{1}",
1641 e.Message, e.StackTrace); 1641 e.Message, e.StackTrace);
1642 } 1642 }
1643 }; 1643 };
1644 } 1644 }
1645 1645
1646 switch (FireAndForgetMethod) 1646 switch (FireAndForgetMethod)
1647 { 1647 {
1648 case FireAndForgetMethod.RegressionTest: 1648 case FireAndForgetMethod.RegressionTest:
1649 case FireAndForgetMethod.None: 1649 case FireAndForgetMethod.None:
1650 realCallback.Invoke(obj); 1650 realCallback.Invoke(obj);
1651 break; 1651 break;
1652 case FireAndForgetMethod.UnsafeQueueUserWorkItem: 1652 case FireAndForgetMethod.UnsafeQueueUserWorkItem:
1653 ThreadPool.UnsafeQueueUserWorkItem(realCallback, obj); 1653 ThreadPool.UnsafeQueueUserWorkItem(realCallback, obj);
1654 break; 1654 break;
1655 case FireAndForgetMethod.QueueUserWorkItem: 1655 case FireAndForgetMethod.QueueUserWorkItem:
1656 ThreadPool.QueueUserWorkItem(realCallback, obj); 1656 ThreadPool.QueueUserWorkItem(realCallback, obj);
1657 break; 1657 break;
1658 case FireAndForgetMethod.BeginInvoke: 1658 case FireAndForgetMethod.BeginInvoke:
1659 FireAndForgetWrapper wrapper = FireAndForgetWrapper.Instance; 1659 FireAndForgetWrapper wrapper = FireAndForgetWrapper.Instance;
1660 wrapper.FireAndForget(realCallback, obj); 1660 wrapper.FireAndForget(realCallback, obj);
1661 break; 1661 break;
1662 case FireAndForgetMethod.SmartThreadPool: 1662 case FireAndForgetMethod.SmartThreadPool:
1663 if (m_ThreadPool == null) 1663 if (m_ThreadPool == null)
1664 m_ThreadPool = new SmartThreadPool(2000, 15, 2); 1664 m_ThreadPool = new SmartThreadPool(2000, 15, 2);
1665 m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { realCallback, obj }); 1665 m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { realCallback, obj });
1666 break; 1666 break;
1667 case FireAndForgetMethod.Thread: 1667 case FireAndForgetMethod.Thread:
1668 Thread thread = new Thread(delegate(object o) { realCallback(o); }); 1668 Thread thread = new Thread(delegate(object o) { realCallback(o); });
1669 thread.Start(obj); 1669 thread.Start(obj);
1670 break; 1670 break;
1671 default: 1671 default:
1672 throw new NotImplementedException(); 1672 throw new NotImplementedException();
1673 } 1673 }
1674 } 1674 }
1675 1675
1676 /// <summary> 1676 /// <summary>
1677 /// Get a thread pool report. 1677 /// Get a thread pool report.
1678 /// </summary> 1678 /// </summary>
1679 /// <returns></returns> 1679 /// <returns></returns>
1680 public static string GetThreadPoolReport() 1680 public static string GetThreadPoolReport()
1681 { 1681 {
1682 string threadPoolUsed = null; 1682 string threadPoolUsed = null;
1683 int maxThreads = 0; 1683 int maxThreads = 0;
1684 int minThreads = 0; 1684 int minThreads = 0;
1685 int allocatedThreads = 0; 1685 int allocatedThreads = 0;
1686 int inUseThreads = 0; 1686 int inUseThreads = 0;
1687 int waitingCallbacks = 0; 1687 int waitingCallbacks = 0;
1688 int completionPortThreads = 0; 1688 int completionPortThreads = 0;
1689 1689
1690 StringBuilder sb = new StringBuilder(); 1690 StringBuilder sb = new StringBuilder();
1691 if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) 1691 if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
1692 { 1692 {
1693 threadPoolUsed = "SmartThreadPool"; 1693 threadPoolUsed = "SmartThreadPool";
1694 maxThreads = m_ThreadPool.MaxThreads; 1694 maxThreads = m_ThreadPool.MaxThreads;
1695 minThreads = m_ThreadPool.MinThreads; 1695 minThreads = m_ThreadPool.MinThreads;
1696 inUseThreads = m_ThreadPool.InUseThreads; 1696 inUseThreads = m_ThreadPool.InUseThreads;
1697 allocatedThreads = m_ThreadPool.ActiveThreads; 1697 allocatedThreads = m_ThreadPool.ActiveThreads;
1698 waitingCallbacks = m_ThreadPool.WaitingCallbacks; 1698 waitingCallbacks = m_ThreadPool.WaitingCallbacks;
1699 } 1699 }
1700 else if ( 1700 else if (
1701 FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem 1701 FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem
1702 || FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem) 1702 || FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
1703 { 1703 {
1704 threadPoolUsed = "BuiltInThreadPool"; 1704 threadPoolUsed = "BuiltInThreadPool";
1705 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads); 1705 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
1706 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads); 1706 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
1707 int availableThreads; 1707 int availableThreads;
1708 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads); 1708 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
1709 inUseThreads = maxThreads - availableThreads; 1709 inUseThreads = maxThreads - availableThreads;
1710 allocatedThreads = -1; 1710 allocatedThreads = -1;
1711 waitingCallbacks = -1; 1711 waitingCallbacks = -1;
1712 } 1712 }
1713 1713
1714 if (threadPoolUsed != null) 1714 if (threadPoolUsed != null)
1715 { 1715 {
1716 sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed); 1716 sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
1717 sb.AppendFormat("Max threads : {0}\n", maxThreads); 1717 sb.AppendFormat("Max threads : {0}\n", maxThreads);
1718 sb.AppendFormat("Min threads : {0}\n", minThreads); 1718 sb.AppendFormat("Min threads : {0}\n", minThreads);
1719 sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString()); 1719 sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
1720 sb.AppendFormat("In use threads : {0}\n", inUseThreads); 1720 sb.AppendFormat("In use threads : {0}\n", inUseThreads);
1721 sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString()); 1721 sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
1722 } 1722 }
1723 else 1723 else
1724 { 1724 {
1725 sb.AppendFormat("Thread pool not used\n"); 1725 sb.AppendFormat("Thread pool not used\n");
1726 } 1726 }
1727 1727
1728 return sb.ToString(); 1728 return sb.ToString();
1729 } 1729 }
1730 1730
1731 private static object SmartThreadPoolCallback(object o) 1731 private static object SmartThreadPoolCallback(object o)
1732 { 1732 {
1733 object[] array = (object[])o; 1733 object[] array = (object[])o;
1734 WaitCallback callback = (WaitCallback)array[0]; 1734 WaitCallback callback = (WaitCallback)array[0];
1735 object obj = array[1]; 1735 object obj = array[1];
1736 1736
1737 callback(obj); 1737 callback(obj);
1738 return null; 1738 return null;
1739 } 1739 }
1740 1740
1741 #endregion FireAndForget Threading Pattern 1741 #endregion FireAndForget Threading Pattern
1742 1742
1743 /// <summary> 1743 /// <summary>
1744 /// Environment.TickCount is an int but it counts all 32 bits so it goes positive 1744 /// Environment.TickCount is an int but it counts all 32 bits so it goes positive
1745 /// and negative every 24.9 days. This trims down TickCount so it doesn't wrap 1745 /// and negative every 24.9 days. This trims down TickCount so it doesn't wrap
1746 /// for the callers. 1746 /// for the callers.
1747 /// This trims it to a 12 day interval so don't let your frame time get too long. 1747 /// This trims it to a 12 day interval so don't let your frame time get too long.
1748 /// </summary> 1748 /// </summary>
1749 /// <returns></returns> 1749 /// <returns></returns>
1750 public static Int32 EnvironmentTickCount() 1750 public static Int32 EnvironmentTickCount()
1751 { 1751 {
1752 return Environment.TickCount & EnvironmentTickCountMask; 1752 return Environment.TickCount & EnvironmentTickCountMask;
1753 } 1753 }
1754 const Int32 EnvironmentTickCountMask = 0x3fffffff; 1754 const Int32 EnvironmentTickCountMask = 0x3fffffff;
1755 1755
1756 /// <summary> 1756 /// <summary>
1757 /// Environment.TickCount is an int but it counts all 32 bits so it goes positive 1757 /// Environment.TickCount is an int but it counts all 32 bits so it goes positive
1758 /// and negative every 24.9 days. Subtracts the passed value (previously fetched by 1758 /// and negative every 24.9 days. Subtracts the passed value (previously fetched by
1759 /// 'EnvironmentTickCount()') and accounts for any wrapping. 1759 /// 'EnvironmentTickCount()') and accounts for any wrapping.
1760 /// </summary> 1760 /// </summary>
1761 /// <param name="newValue"></param> 1761 /// <param name="newValue"></param>
1762 /// <param name="prevValue"></param> 1762 /// <param name="prevValue"></param>
1763 /// <returns>subtraction of passed prevValue from current Environment.TickCount</returns> 1763 /// <returns>subtraction of passed prevValue from current Environment.TickCount</returns>
1764 public static Int32 EnvironmentTickCountSubtract(Int32 newValue, Int32 prevValue) 1764 public static Int32 EnvironmentTickCountSubtract(Int32 newValue, Int32 prevValue)
1765 { 1765 {
1766 Int32 diff = newValue - prevValue; 1766 Int32 diff = newValue - prevValue;
1767 return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1); 1767 return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1);
1768 } 1768 }
1769 1769
1770 /// <summary> 1770 /// <summary>
1771 /// Environment.TickCount is an int but it counts all 32 bits so it goes positive 1771 /// Environment.TickCount is an int but it counts all 32 bits so it goes positive
1772 /// and negative every 24.9 days. Subtracts the passed value (previously fetched by 1772 /// and negative every 24.9 days. Subtracts the passed value (previously fetched by
1773 /// 'EnvironmentTickCount()') and accounts for any wrapping. 1773 /// 'EnvironmentTickCount()') and accounts for any wrapping.
1774 /// </summary> 1774 /// </summary>
1775 /// <returns>subtraction of passed prevValue from current Environment.TickCount</returns> 1775 /// <returns>subtraction of passed prevValue from current Environment.TickCount</returns>
1776 public static Int32 EnvironmentTickCountSubtract(Int32 prevValue) 1776 public static Int32 EnvironmentTickCountSubtract(Int32 prevValue)
1777 { 1777 {
1778 return EnvironmentTickCountSubtract(EnvironmentTickCount(), prevValue); 1778 return EnvironmentTickCountSubtract(EnvironmentTickCount(), prevValue);
1779 } 1779 }
1780 1780
1781 // Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount 1781 // Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount
1782 // Assumes both tcA and tcB came from previous calls to Util.EnvironmentTickCount(). 1782 // Assumes both tcA and tcB came from previous calls to Util.EnvironmentTickCount().
1783 // A positive return value indicates A occured later than B 1783 // A positive return value indicates A occured later than B
1784 public static Int32 EnvironmentTickCountCompare(Int32 tcA, Int32 tcB) 1784 public static Int32 EnvironmentTickCountCompare(Int32 tcA, Int32 tcB)
1785 { 1785 {
1786 // A, B and TC are all between 0 and 0x3fffffff 1786 // A, B and TC are all between 0 and 0x3fffffff
1787 int tc = EnvironmentTickCount(); 1787 int tc = EnvironmentTickCount();
1788 1788
1789 if (tc - tcA >= 0) 1789 if (tc - tcA >= 0)
1790 tcA += EnvironmentTickCountMask + 1; 1790 tcA += EnvironmentTickCountMask + 1;
1791 1791
1792 if (tc - tcB >= 0) 1792 if (tc - tcB >= 0)
1793 tcB += EnvironmentTickCountMask + 1; 1793 tcB += EnvironmentTickCountMask + 1;
1794 1794
1795 return tcA - tcB; 1795 return tcA - tcB;
1796 } 1796 }
1797 1797
1798 /// <summary> 1798 /// <summary>
1799 /// Prints the call stack at any given point. Useful for debugging. 1799 /// Prints the call stack at any given point. Useful for debugging.
1800 /// </summary> 1800 /// </summary>
1801 public static void PrintCallStack() 1801 public static void PrintCallStack()
1802 { 1802 {
1803 StackTrace stackTrace = new StackTrace(true); // get call stack 1803 StackTrace stackTrace = new StackTrace(true); // get call stack
1804 StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) 1804 StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
1805 1805
1806 // write call stack method names 1806 // write call stack method names
1807 foreach (StackFrame stackFrame in stackFrames) 1807 foreach (StackFrame stackFrame in stackFrames)
1808 { 1808 {
1809 MethodBase mb = stackFrame.GetMethod(); 1809 MethodBase mb = stackFrame.GetMethod();
1810 m_log.DebugFormat("{0}.{1}:{2}", mb.DeclaringType, mb.Name, stackFrame.GetFileLineNumber()); // write method name 1810 m_log.DebugFormat("{0}.{1}:{2}", mb.DeclaringType, mb.Name, stackFrame.GetFileLineNumber()); // write method name
1811 } 1811 }
1812 } 1812 }
1813 1813
1814 /// <summary> 1814 /// <summary>
1815 /// Gets the client IP address 1815 /// Gets the client IP address
1816 /// </summary> 1816 /// </summary>
1817 /// <param name="xff"></param> 1817 /// <param name="xff"></param>
1818 /// <returns></returns> 1818 /// <returns></returns>
1819 public static IPEndPoint GetClientIPFromXFF(string xff) 1819 public static IPEndPoint GetClientIPFromXFF(string xff)
1820 { 1820 {
1821 if (xff == string.Empty) 1821 if (xff == string.Empty)
1822 return null; 1822 return null;
1823 1823
1824 string[] parts = xff.Split(new char[] { ',' }); 1824 string[] parts = xff.Split(new char[] { ',' });
1825 if (parts.Length > 0) 1825 if (parts.Length > 0)
1826 { 1826 {
1827 try 1827 try
1828 { 1828 {
1829 return new IPEndPoint(IPAddress.Parse(parts[0]), 0); 1829 return new IPEndPoint(IPAddress.Parse(parts[0]), 0);
1830 } 1830 }
1831 catch (Exception e) 1831 catch (Exception e)
1832 { 1832 {
1833 m_log.WarnFormat("[UTIL]: Exception parsing XFF header {0}: {1}", xff, e.Message); 1833 m_log.WarnFormat("[UTIL]: Exception parsing XFF header {0}: {1}", xff, e.Message);
1834 } 1834 }
1835 } 1835 }
1836 1836
1837 return null; 1837 return null;
1838 } 1838 }
1839 1839
1840 public static string GetCallerIP(Hashtable req) 1840 public static string GetCallerIP(Hashtable req)
1841 { 1841 {
1842 if (req.ContainsKey("headers")) 1842 if (req.ContainsKey("headers"))
1843 { 1843 {
1844 try 1844 try
1845 { 1845 {
1846 Hashtable headers = (Hashtable)req["headers"]; 1846 Hashtable headers = (Hashtable)req["headers"];
1847 if (headers.ContainsKey("remote_addr") && headers["remote_addr"] != null) 1847 if (headers.ContainsKey("remote_addr") && headers["remote_addr"] != null)
1848 return headers["remote_addr"].ToString(); 1848 return headers["remote_addr"].ToString();
1849 } 1849 }
1850 catch (Exception e) 1850 catch (Exception e)
1851 { 1851 {
1852 m_log.WarnFormat("[UTIL]: exception in GetCallerIP: {0}", e.Message); 1852 m_log.WarnFormat("[UTIL]: exception in GetCallerIP: {0}", e.Message);
1853 } 1853 }
1854 } 1854 }
1855 return string.Empty; 1855 return string.Empty;
1856 } 1856 }
1857 1857
1858 #region Xml Serialization Utilities 1858 #region Xml Serialization Utilities
1859 public static bool ReadBoolean(XmlTextReader reader) 1859 public static bool ReadBoolean(XmlTextReader reader)
1860 { 1860 {
1861 reader.ReadStartElement(); 1861 reader.ReadStartElement();
1862 bool result = Boolean.Parse(reader.ReadContentAsString().ToLower()); 1862 bool result = Boolean.Parse(reader.ReadContentAsString().ToLower());
1863 reader.ReadEndElement(); 1863 reader.ReadEndElement();
1864 1864
1865 return result; 1865 return result;
1866 } 1866 }
1867 1867
1868 public static UUID ReadUUID(XmlTextReader reader, string name) 1868 public static UUID ReadUUID(XmlTextReader reader, string name)
1869 { 1869 {
1870 UUID id; 1870 UUID id;
1871 string idStr; 1871 string idStr;
1872 1872
1873 reader.ReadStartElement(name); 1873 reader.ReadStartElement(name);
1874 1874
1875 if (reader.Name == "Guid") 1875 if (reader.Name == "Guid")
1876 idStr = reader.ReadElementString("Guid"); 1876 idStr = reader.ReadElementString("Guid");
1877 else if (reader.Name == "UUID") 1877 else if (reader.Name == "UUID")
1878 idStr = reader.ReadElementString("UUID"); 1878 idStr = reader.ReadElementString("UUID");
1879 else // no leading tag 1879 else // no leading tag
1880 idStr = reader.ReadContentAsString(); 1880 idStr = reader.ReadContentAsString();
1881 UUID.TryParse(idStr, out id); 1881 UUID.TryParse(idStr, out id);
1882 reader.ReadEndElement(); 1882 reader.ReadEndElement();
1883 1883
1884 return id; 1884 return id;
1885 } 1885 }
1886 1886
1887 public static Vector3 ReadVector(XmlTextReader reader, string name) 1887 public static Vector3 ReadVector(XmlTextReader reader, string name)
1888 { 1888 {
1889 Vector3 vec; 1889 Vector3 vec;
1890 1890
1891 reader.ReadStartElement(name); 1891 reader.ReadStartElement(name);
1892 vec.X = reader.ReadElementContentAsFloat(reader.Name, String.Empty); // X or x 1892 vec.X = reader.ReadElementContentAsFloat(reader.Name, String.Empty); // X or x
1893 vec.Y = reader.ReadElementContentAsFloat(reader.Name, String.Empty); // Y or y 1893 vec.Y = reader.ReadElementContentAsFloat(reader.Name, String.Empty); // Y or y
1894 vec.Z = reader.ReadElementContentAsFloat(reader.Name, String.Empty); // Z or z 1894 vec.Z = reader.ReadElementContentAsFloat(reader.Name, String.Empty); // Z or z
1895 reader.ReadEndElement(); 1895 reader.ReadEndElement();
1896 1896
1897 return vec; 1897 return vec;
1898 } 1898 }
1899 1899
1900 public static Quaternion ReadQuaternion(XmlTextReader reader, string name) 1900 public static Quaternion ReadQuaternion(XmlTextReader reader, string name)
1901 { 1901 {
1902 Quaternion quat = new Quaternion(); 1902 Quaternion quat = new Quaternion();
1903 1903
1904 reader.ReadStartElement(name); 1904 reader.ReadStartElement(name);
1905 while (reader.NodeType != XmlNodeType.EndElement) 1905 while (reader.NodeType != XmlNodeType.EndElement)
1906 { 1906 {
1907 switch (reader.Name.ToLower()) 1907 switch (reader.Name.ToLower())
1908 { 1908 {
1909 case "x": 1909 case "x":
1910 quat.X = reader.ReadElementContentAsFloat(reader.Name, String.Empty); 1910 quat.X = reader.ReadElementContentAsFloat(reader.Name, String.Empty);
1911 break; 1911 break;
1912 case "y": 1912 case "y":
1913 quat.Y = reader.ReadElementContentAsFloat(reader.Name, String.Empty); 1913 quat.Y = reader.ReadElementContentAsFloat(reader.Name, String.Empty);
1914 break; 1914 break;
1915 case "z": 1915 case "z":
1916 quat.Z = reader.ReadElementContentAsFloat(reader.Name, String.Empty); 1916 quat.Z = reader.ReadElementContentAsFloat(reader.Name, String.Empty);
1917 break; 1917 break;
1918 case "w": 1918 case "w":
1919 quat.W = reader.ReadElementContentAsFloat(reader.Name, String.Empty); 1919 quat.W = reader.ReadElementContentAsFloat(reader.Name, String.Empty);
1920 break; 1920 break;
1921 } 1921 }
1922 } 1922 }
1923 1923
1924 reader.ReadEndElement(); 1924 reader.ReadEndElement();
1925 1925
1926 return quat; 1926 return quat;
1927 } 1927 }
1928 1928
1929 public static T ReadEnum<T>(XmlTextReader reader, string name) 1929 public static T ReadEnum<T>(XmlTextReader reader, string name)
1930 { 1930 {
1931 string value = reader.ReadElementContentAsString(name, String.Empty); 1931 string value = reader.ReadElementContentAsString(name, String.Empty);
1932 // !!!!! to deal with flags without commas 1932 // !!!!! to deal with flags without commas
1933 if (value.Contains(" ") && !value.Contains(",")) 1933 if (value.Contains(" ") && !value.Contains(","))
1934 value = value.Replace(" ", ", "); 1934 value = value.Replace(" ", ", ");
1935 1935
1936 return (T)Enum.Parse(typeof(T), value); ; 1936 return (T)Enum.Parse(typeof(T), value); ;
1937 } 1937 }
1938 #endregion 1938 #endregion
1939 1939
1940 #region Universal User Identifiers 1940 #region Universal User Identifiers
1941 /// <summary> 1941 /// <summary>
1942 /// </summary> 1942 /// </summary>
1943 /// <param name="value">uuid[;endpoint[;name]]</param> 1943 /// <param name="value">uuid[;endpoint[;first last[;secret]]]</param>
1944 /// <param name="uuid"></param> 1944 /// <param name="uuid">the uuid part</param>
1945 /// <param name="url"></param> 1945 /// <param name="url">the endpoint part (e.g. http://foo.com)</param>
1946 /// <param name="firstname"></param> 1946 /// <param name="firstname">the first name part (e.g. Test)</param>
1947 /// <param name="lastname"></param> 1947 /// <param name="lastname">the last name part (e.g User)</param>
1948 public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret) 1948 /// <param name="secret">the secret part</param>
1949 { 1949 public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret)
1950 uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty; 1950 {
1951 1951 uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty;
1952 string[] parts = value.Split(';'); 1952
1953 if (parts.Length >= 1) 1953 string[] parts = value.Split(';');
1954 if (!UUID.TryParse(parts[0], out uuid)) 1954 if (parts.Length >= 1)
1955 return false; 1955 if (!UUID.TryParse(parts[0], out uuid))
1956 1956 return false;
1957 if (parts.Length >= 2) 1957
1958 url = parts[1]; 1958 if (parts.Length >= 2)
1959 1959 url = parts[1];
1960 if (parts.Length >= 3) 1960
1961 { 1961 if (parts.Length >= 3)
1962 string[] name = parts[2].Split(); 1962 {
1963 if (name.Length == 2) 1963 string[] name = parts[2].Split();
1964 { 1964 if (name.Length == 2)
1965 firstname = name[0]; 1965 {
1966 lastname = name[1]; 1966 firstname = name[0];
1967 } 1967 lastname = name[1];
1968 } 1968 }
1969 if (parts.Length >= 4) 1969 }
1970 secret = parts[3]; 1970 if (parts.Length >= 4)
1971 1971 secret = parts[3];
1972 return true; 1972
1973 } 1973 return true;
1974 1974 }
1975 /// <summary> 1975
1976 /// 1976 /// <summary>
1977 /// </summary> 1977 /// Produces a universal (HG) system-facing identifier given the information
1978 /// <param name="acircuit"></param> 1978 /// </summary>
1979 /// <returns>uuid[;endpoint[;name]]</returns> 1979 /// <param name="acircuit"></param>
1980 public static string ProduceUserUniversalIdentifier(AgentCircuitData acircuit) 1980 /// <returns>uuid[;homeURI[;first last]]</returns>
1981 { 1981 public static string ProduceUserUniversalIdentifier(AgentCircuitData acircuit)
1982 if (acircuit.ServiceURLs.ContainsKey("HomeURI")) 1982 {
1983 { 1983 if (acircuit.ServiceURLs.ContainsKey("HomeURI"))
1984 string agentsURI = acircuit.ServiceURLs["HomeURI"].ToString(); 1984 return UniversalIdentifier(acircuit.AgentID, acircuit.firstname, acircuit.lastname, acircuit.ServiceURLs["HomeURI"].ToString());
1985 if (!agentsURI.EndsWith("/")) 1985 else
1986 agentsURI += "/"; 1986 return acircuit.AgentID.ToString();
1987 1987 }
1988 // This is ugly, but there's no other way, given that the name is changed 1988
1989 // in the agent circuit data for foreigners 1989 /// <summary>
1990 if (acircuit.lastname.Contains("@")) 1990 /// Produces a universal (HG) system-facing identifier given the information
1991 { 1991 /// </summary>
1992 string[] parts = acircuit.firstname.Split(new char[] { '.' }); 1992 /// <param name="id">UUID of the user</param>
1993 if (parts.Length == 2) 1993 /// <param name="firstName">first name (e.g Test)</param>
1994 return acircuit.AgentID.ToString() + ";" + agentsURI + ";" + parts[0] + " " + parts[1]; 1994 /// <param name="lastName">last name (e.g. User)</param>
1995 } 1995 /// <param name="homeURI">homeURI (e.g. http://foo.com)</param>
1996 return acircuit.AgentID.ToString() + ";" + agentsURI + ";" + acircuit.firstname + " " + acircuit.lastname; 1996 /// <returns>a string of the form uuid[;homeURI[;first last]]</returns>
1997 } 1997 public static string UniversalIdentifier(UUID id, String firstName, String lastName, String homeURI)
1998 else 1998 {
1999 return acircuit.AgentID.ToString(); 1999 string agentsURI = homeURI;
2000 } 2000 if (!agentsURI.EndsWith("/"))
2001 #endregion 2001 agentsURI += "/";
2002 } 2002
2003} 2003 // This is ugly, but there's no other way, given that the name is changed
2004 // in the agent circuit data for foreigners
2005 if (lastName.Contains("@"))
2006 {
2007 string[] parts = firstName.Split(new char[] { '.' });
2008 if (parts.Length == 2)
2009 return id.ToString() + ";" + agentsURI + ";" + parts[0] + " " + parts[1];
2010 }
2011 return id.ToString() + ";" + agentsURI + ";" + firstName + " " + lastName;
2012
2013 }
2014
2015 /// <summary>
2016 /// Produces a universal (HG) user-facing name given the information
2017 /// </summary>
2018 /// <param name="firstName"></param>
2019 /// <param name="lastName"></param>
2020 /// <param name="homeURI"></param>
2021 /// <returns>string of the form first.last @foo.com or first last</returns>
2022 public static string UniversalName(String firstName, String lastName, String homeURI)
2023 {
2024 Uri uri = null;
2025 try
2026 {
2027 uri = new Uri(homeURI);
2028 }
2029 catch (UriFormatException)
2030 {
2031 return firstName + " " + lastName;
2032 }
2033 return firstName + "." + lastName + " " + "@" + uri.Authority;
2034 }
2035 #endregion
2036 }
2037}