clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27  
28 using System;
29 using System.Collections.Generic;
30 using System.IO;
31 using System.Reflection;
32 using System.Xml;
33 using log4net;
34 using OpenMetaverse;
35  
36 namespace OpenSim.Framework
37 {
38 public static class SLUtil
39 {
40 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41  
42 /// <summary>
43 /// Asset types used only in OpenSim.
44 /// To avoid clashing with the code numbers used in Second Life, use only negative numbers here.
45 /// </summary>
46 public enum OpenSimAssetType : sbyte
47 {
48 Material = -2
49 }
50  
51  
52 #region SL / file extension / content-type conversions
53  
54 /// <summary>
55 /// Returns the Enum entry corresponding to the given code, regardless of whether it belongs
56 /// to the AssetType or OpenSimAssetType enums.
57 /// </summary>
58 public static object AssetTypeFromCode(sbyte assetType)
59 {
60 if (Enum.IsDefined(typeof(OpenMetaverse.AssetType), assetType))
61 return (OpenMetaverse.AssetType)assetType;
62 else if (Enum.IsDefined(typeof(OpenSimAssetType), assetType))
63 return (OpenSimAssetType)assetType;
64 else
65 return OpenMetaverse.AssetType.Unknown;
66 }
67  
68 private class TypeMapping
69 {
70 private sbyte assetType;
71 private InventoryType inventoryType;
72 private string contentType;
73 private string contentType2;
74 private string extension;
75  
76 public sbyte AssetTypeCode
77 {
78 get { return assetType; }
79 }
80  
81 public object AssetType
82 {
83 get { return AssetTypeFromCode(assetType); }
84 }
85  
86 public InventoryType InventoryType
87 {
88 get { return inventoryType; }
89 }
90  
91 public string ContentType
92 {
93 get { return contentType; }
94 }
95  
96 public string ContentType2
97 {
98 get { return contentType2; }
99 }
100  
101 public string Extension
102 {
103 get { return extension; }
104 }
105  
106 private TypeMapping(sbyte assetType, InventoryType inventoryType, string contentType, string contentType2, string extension)
107 {
108 this.assetType = assetType;
109 this.inventoryType = inventoryType;
110 this.contentType = contentType;
111 this.contentType2 = contentType2;
112 this.extension = extension;
113 }
114  
115 public TypeMapping(AssetType assetType, InventoryType inventoryType, string contentType, string contentType2, string extension)
116 : this((sbyte)assetType, inventoryType, contentType, contentType2, extension)
117 {
118 }
119  
120 public TypeMapping(AssetType assetType, InventoryType inventoryType, string contentType, string extension)
121 : this((sbyte)assetType, inventoryType, contentType, null, extension)
122 {
123 }
124  
125 public TypeMapping(OpenSimAssetType assetType, InventoryType inventoryType, string contentType, string extension)
126 : this((sbyte)assetType, inventoryType, contentType, null, extension)
127 {
128 }
129 }
130  
131 /// <summary>
132 /// Maps between AssetType, InventoryType and Content-Type.
133 /// Where more than one possibility exists, the first one takes precedence. E.g.:
134 /// AssetType "AssetType.Texture" -> Content-Type "image-xj2c"
135 /// Content-Type "image/x-j2c" -> InventoryType "InventoryType.Texture"
136 /// </summary>
137 private static TypeMapping[] MAPPINGS = new TypeMapping[] {
138 new TypeMapping(AssetType.Unknown, InventoryType.Unknown, "application/octet-stream", "bin"),
139 new TypeMapping(AssetType.Texture, InventoryType.Texture, "image/x-j2c", "image/jp2", "j2c"),
140 new TypeMapping(AssetType.Texture, InventoryType.Snapshot, "image/x-j2c", "image/jp2", "j2c"),
141 new TypeMapping(AssetType.TextureTGA, InventoryType.Texture, "image/tga", "tga"),
142 new TypeMapping(AssetType.ImageTGA, InventoryType.Texture, "image/tga", "tga"),
143 new TypeMapping(AssetType.ImageJPEG, InventoryType.Texture, "image/jpeg", "jpg"),
144 new TypeMapping(AssetType.Sound, InventoryType.Sound, "audio/ogg", "application/ogg", "ogg"),
145 new TypeMapping(AssetType.SoundWAV, InventoryType.Sound, "audio/x-wav", "wav"),
146 new TypeMapping(AssetType.CallingCard, InventoryType.CallingCard, "application/vnd.ll.callingcard", "application/x-metaverse-callingcard", "callingcard"),
147 new TypeMapping(AssetType.Landmark, InventoryType.Landmark, "application/vnd.ll.landmark", "application/x-metaverse-landmark", "landmark"),
148 new TypeMapping(AssetType.Clothing, InventoryType.Wearable, "application/vnd.ll.clothing", "application/x-metaverse-clothing", "clothing"),
149 new TypeMapping(AssetType.Object, InventoryType.Object, "application/vnd.ll.primitive", "application/x-metaverse-primitive", "primitive"),
150 new TypeMapping(AssetType.Object, InventoryType.Attachment, "application/vnd.ll.primitive", "application/x-metaverse-primitive", "primitive"),
151 new TypeMapping(AssetType.Notecard, InventoryType.Notecard, "application/vnd.ll.notecard", "application/x-metaverse-notecard", "notecard"),
152 new TypeMapping(AssetType.Folder, InventoryType.Folder, "application/vnd.ll.folder", "folder"),
153 new TypeMapping(AssetType.RootFolder, InventoryType.RootCategory, "application/vnd.ll.rootfolder", "rootfolder"),
154 new TypeMapping(AssetType.LSLText, InventoryType.LSL, "application/vnd.ll.lsltext", "application/x-metaverse-lsl", "lsl"),
155 new TypeMapping(AssetType.LSLBytecode, InventoryType.LSL, "application/vnd.ll.lslbyte", "application/x-metaverse-lso", "lso"),
156 new TypeMapping(AssetType.Bodypart, InventoryType.Wearable, "application/vnd.ll.bodypart", "application/x-metaverse-bodypart", "bodypart"),
157 new TypeMapping(AssetType.TrashFolder, InventoryType.Folder, "application/vnd.ll.trashfolder", "trashfolder"),
158 new TypeMapping(AssetType.SnapshotFolder, InventoryType.Folder, "application/vnd.ll.snapshotfolder", "snapshotfolder"),
159 new TypeMapping(AssetType.LostAndFoundFolder, InventoryType.Folder, "application/vnd.ll.lostandfoundfolder", "lostandfoundfolder"),
160 new TypeMapping(AssetType.Animation, InventoryType.Animation, "application/vnd.ll.animation", "application/x-metaverse-animation", "animation"),
161 new TypeMapping(AssetType.Gesture, InventoryType.Gesture, "application/vnd.ll.gesture", "application/x-metaverse-gesture", "gesture"),
162 new TypeMapping(AssetType.Simstate, InventoryType.Snapshot, "application/x-metaverse-simstate", "simstate"),
163 new TypeMapping(AssetType.FavoriteFolder, InventoryType.Unknown, "application/vnd.ll.favoritefolder", "favoritefolder"),
164 new TypeMapping(AssetType.Link, InventoryType.Unknown, "application/vnd.ll.link", "link"),
165 new TypeMapping(AssetType.LinkFolder, InventoryType.Unknown, "application/vnd.ll.linkfolder", "linkfolder"),
166 new TypeMapping(AssetType.CurrentOutfitFolder, InventoryType.Unknown, "application/vnd.ll.currentoutfitfolder", "currentoutfitfolder"),
167 new TypeMapping(AssetType.OutfitFolder, InventoryType.Unknown, "application/vnd.ll.outfitfolder", "outfitfolder"),
168 new TypeMapping(AssetType.MyOutfitsFolder, InventoryType.Unknown, "application/vnd.ll.myoutfitsfolder", "myoutfitsfolder"),
169 new TypeMapping(AssetType.Mesh, InventoryType.Mesh, "application/vnd.ll.mesh", "llm"),
170  
171 new TypeMapping(OpenSimAssetType.Material, InventoryType.Unknown, "application/llsd+xml", "material")
172 };
173  
174 private static Dictionary<sbyte, string> asset2Content;
175 private static Dictionary<sbyte, string> asset2Extension;
176 private static Dictionary<InventoryType, string> inventory2Content;
177 private static Dictionary<string, sbyte> content2Asset;
178 private static Dictionary<string, InventoryType> content2Inventory;
179  
180 static SLUtil()
181 {
182 asset2Content = new Dictionary<sbyte, string>();
183 asset2Extension = new Dictionary<sbyte, string>();
184 inventory2Content = new Dictionary<InventoryType, string>();
185 content2Asset = new Dictionary<string, sbyte>();
186 content2Inventory = new Dictionary<string, InventoryType>();
187  
188 foreach (TypeMapping mapping in MAPPINGS)
189 {
190 sbyte assetType = mapping.AssetTypeCode;
191 if (!asset2Content.ContainsKey(assetType))
192 asset2Content.Add(assetType, mapping.ContentType);
193 if (!asset2Extension.ContainsKey(assetType))
194 asset2Extension.Add(assetType, mapping.Extension);
195 if (!inventory2Content.ContainsKey(mapping.InventoryType))
196 inventory2Content.Add(mapping.InventoryType, mapping.ContentType);
197 if (!content2Asset.ContainsKey(mapping.ContentType))
198 content2Asset.Add(mapping.ContentType, assetType);
199 if (!content2Inventory.ContainsKey(mapping.ContentType))
200 content2Inventory.Add(mapping.ContentType, mapping.InventoryType);
201  
202 if (mapping.ContentType2 != null)
203 {
204 if (!content2Asset.ContainsKey(mapping.ContentType2))
205 content2Asset.Add(mapping.ContentType2, assetType);
206 if (!content2Inventory.ContainsKey(mapping.ContentType2))
207 content2Inventory.Add(mapping.ContentType2, mapping.InventoryType);
208 }
209 }
210 }
211  
212 public static string SLAssetTypeToContentType(int assetType)
213 {
214 string contentType;
215 if (!asset2Content.TryGetValue((sbyte)assetType, out contentType))
216 contentType = asset2Content[(sbyte)AssetType.Unknown];
217 return contentType;
218 }
219  
220 public static string SLInvTypeToContentType(int invType)
221 {
222 string contentType;
223 if (!inventory2Content.TryGetValue((InventoryType)invType, out contentType))
224 contentType = inventory2Content[InventoryType.Unknown];
225 return contentType;
226 }
227  
228 public static sbyte ContentTypeToSLAssetType(string contentType)
229 {
230 sbyte assetType;
231 if (!content2Asset.TryGetValue(contentType, out assetType))
232 assetType = (sbyte)AssetType.Unknown;
233 return (sbyte)assetType;
234 }
235  
236 public static sbyte ContentTypeToSLInvType(string contentType)
237 {
238 InventoryType invType;
239 if (!content2Inventory.TryGetValue(contentType, out invType))
240 invType = InventoryType.Unknown;
241 return (sbyte)invType;
242 }
243  
244 public static string SLAssetTypeToExtension(int assetType)
245 {
246 string extension;
247 if (!asset2Extension.TryGetValue((sbyte)assetType, out extension))
248 extension = asset2Extension[(sbyte)AssetType.Unknown];
249 return extension;
250 }
251  
252 #endregion SL / file extension / content-type conversions
253  
254 /// <summary>
255 /// Parse a notecard in Linden format to a string of ordinary text.
256 /// </summary>
257 /// <param name="rawInput"></param>
258 /// <returns></returns>
259 public static string ParseNotecardToString(string rawInput)
260 {
261 string[] output = ParseNotecardToList(rawInput).ToArray();
262  
263 // foreach (string line in output)
264 // m_log.DebugFormat("[PARSE NOTECARD]: ParseNotecardToString got line {0}", line);
265  
266 return string.Join("\n", output);
267 }
268  
269 /// <summary>
270 /// Parse a notecard in Linden format to a list of ordinary lines.
271 /// </summary>
272 /// <param name="rawInput"></param>
273 /// <returns></returns>
274 public static List<string> ParseNotecardToList(string rawInput)
275 {
276 string[] input;
277 int idx = 0;
278 int level = 0;
279 List<string> output = new List<string>();
280 string[] words;
281  
282 //The Linden format always ends with a } after the input data.
283 //Strip off trailing } so there is nothing after the input data.
284 int i = rawInput.LastIndexOf("}");
285 rawInput = rawInput.Remove(i, rawInput.Length-i);
286 input = rawInput.Replace("\r", "").Split('\n');
287  
288 while (idx < input.Length)
289 {
290 if (input[idx] == "{")
291 {
292 level++;
293 idx++;
294 continue;
295 }
296  
297 if (input[idx]== "}")
298 {
299 level--;
300 idx++;
301 continue;
302 }
303  
304 switch (level)
305 {
306 case 0:
307 words = input[idx].Split(' '); // Linden text ver
308 // Notecards are created *really* empty. Treat that as "no text" (just like after saving an empty notecard)
309 if (words.Length < 3)
310 return output;
311  
312 int version = int.Parse(words[3]);
313 if (version != 2)
314 return output;
315 break;
316 case 1:
317 words = input[idx].Split(' ');
318 if (words[0] == "LLEmbeddedItems")
319 break;
320 if (words[0] == "Text")
321 {
322 idx++; //Now points to first line of notecard text
323  
324 //Number of lines in notecard.
325 int lines = input.Length - idx;
326 int line = 0;
327  
328 while (line < lines)
329 {
330 // m_log.DebugFormat("[PARSE NOTECARD]: Adding line {0}", input[idx]);
331 output.Add(input[idx]);
332 idx++;
333 line++;
334 }
335  
336 return output;
337 }
338 break;
339 case 2:
340 words = input[idx].Split(' '); // count
341 if (words[0] == "count")
342 {
343 int c = int.Parse(words[1]);
344 if (c > 0)
345 return output;
346 break;
347 }
348 break;
349 }
350 idx++;
351 }
352  
353 return output;
354 }
355 }
356 }