diff options
author | ft@noemail | 2015-03-04 00:17:24 +0100 |
---|---|---|
committer | BlueWall | 2015-03-03 18:39:49 -0500 |
commit | fb48ee1cb608f5facdcd257f13a7e49c2ce52946 (patch) | |
tree | fac8f7d3437031fe7e6e4fed9e1cf13562cb3f78 /OpenSim | |
parent | Revert "corrected osMakeNotecard(string data) text length was calculated wron... (diff) | |
download | opensim-SC-fb48ee1cb608f5facdcd257f13a7e49c2ce52946.zip opensim-SC-fb48ee1cb608f5facdcd257f13a7e49c2ce52946.tar.gz opensim-SC-fb48ee1cb608f5facdcd257f13a7e49c2ce52946.tar.bz2 opensim-SC-fb48ee1cb608f5facdcd257f13a7e49c2ce52946.tar.xz |
corrected script notecard parser. It now handles notecards with inventory as well.
Signed-off-by: BlueWall <jamesh@bluewallgroup.com>
Diffstat (limited to 'OpenSim')
4 files changed, 262 insertions, 94 deletions
diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs index 9249105..027fc0e 100644 --- a/OpenSim/Framework/SLUtil.cs +++ b/OpenSim/Framework/SLUtil.cs | |||
@@ -25,13 +25,9 @@ | |||
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 | ||
28 | using OpenMetaverse; | ||
28 | using System; | 29 | using System; |
29 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
30 | using System.IO; | ||
31 | using System.Reflection; | ||
32 | using System.Xml; | ||
33 | using log4net; | ||
34 | using OpenMetaverse; | ||
35 | 31 | ||
36 | namespace OpenSim.Framework | 32 | namespace OpenSim.Framework |
37 | { | 33 | { |
@@ -251,106 +247,270 @@ namespace OpenSim.Framework | |||
251 | 247 | ||
252 | #endregion SL / file extension / content-type conversions | 248 | #endregion SL / file extension / content-type conversions |
253 | 249 | ||
254 | /// <summary> | 250 | private class NotecardReader |
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 | { | 251 | { |
261 | string[] output = ParseNotecardToList(rawInput).ToArray(); | 252 | private string rawInput; |
253 | private int lineNumber; | ||
262 | 254 | ||
263 | // foreach (string line in output) | 255 | public int LineNumber |
264 | // m_log.DebugFormat("[PARSE NOTECARD]: ParseNotecardToString got line {0}", line); | 256 | { |
265 | 257 | get | |
266 | return string.Join("\n", output); | 258 | { |
259 | return lineNumber; | ||
260 | } | ||
261 | } | ||
262 | |||
263 | public NotecardReader(string _rawInput) | ||
264 | { | ||
265 | rawInput = (string)_rawInput.Clone(); | ||
266 | lineNumber = 0; | ||
267 | } | ||
268 | |||
269 | public string getLine() | ||
270 | { | ||
271 | if(rawInput.Length == 0) | ||
272 | { | ||
273 | throw new NotANotecardFormatException(lineNumber + 1); | ||
274 | } | ||
275 | |||
276 | int pos = rawInput.IndexOf('\n'); | ||
277 | if(pos < 0) | ||
278 | { | ||
279 | pos = rawInput.Length; | ||
280 | } | ||
281 | |||
282 | /* cut line from rest */ | ||
283 | ++lineNumber; | ||
284 | string line = rawInput.Substring(0, pos); | ||
285 | if (pos + 1 >= rawInput.Length) | ||
286 | { | ||
287 | rawInput = string.Empty; | ||
288 | } | ||
289 | else | ||
290 | { | ||
291 | rawInput = rawInput.Substring(pos + 1); | ||
292 | } | ||
293 | /* clean up line from double spaces and tabs */ | ||
294 | line = line.Replace("\t", " "); | ||
295 | while(line.IndexOf(" ") >= 0) | ||
296 | { | ||
297 | line = line.Replace(" ", " "); | ||
298 | } | ||
299 | return line.Replace("\r", "").Trim(); | ||
300 | } | ||
301 | |||
302 | public string getBlock(int length) | ||
303 | { | ||
304 | /* cut line from rest */ | ||
305 | if(length > rawInput.Length) | ||
306 | { | ||
307 | throw new NotANotecardFormatException(lineNumber); | ||
308 | } | ||
309 | string line = rawInput.Substring(0, length); | ||
310 | rawInput = rawInput.Substring(length); | ||
311 | return line; | ||
312 | } | ||
267 | } | 313 | } |
268 | 314 | ||
269 | /// <summary> | 315 | public class NotANotecardFormatException : Exception |
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 | { | 316 | { |
276 | string[] input; | 317 | public int lineNumber; |
277 | int idx = 0; | 318 | public NotANotecardFormatException(int _lineNumber) |
278 | int level = 0; | 319 | : base() |
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 | { | 320 | { |
290 | if (input[idx] == "{") | 321 | lineNumber = _lineNumber; |
322 | } | ||
323 | } | ||
324 | |||
325 | private static void skipSection(NotecardReader reader) | ||
326 | { | ||
327 | if (reader.getLine() != "{") | ||
328 | throw new NotANotecardFormatException(reader.LineNumber); | ||
329 | |||
330 | string line; | ||
331 | while ((line = reader.getLine()) != "}") | ||
332 | { | ||
333 | if(line.IndexOf('{')>=0) | ||
334 | { | ||
335 | throw new NotANotecardFormatException(reader.LineNumber); | ||
336 | } | ||
337 | } | ||
338 | } | ||
339 | |||
340 | private static void skipInventoryItem(NotecardReader reader) | ||
341 | { | ||
342 | if (reader.getLine() != "{") | ||
343 | throw new NotANotecardFormatException(reader.LineNumber); | ||
344 | |||
345 | string line; | ||
346 | while((line = reader.getLine()) != "}") | ||
347 | { | ||
348 | string[] data = line.Split(' '); | ||
349 | if(data.Length == 0) | ||
291 | { | 350 | { |
292 | level++; | ||
293 | idx++; | ||
294 | continue; | 351 | continue; |
295 | } | 352 | } |
353 | if(data[0] == "permissions") | ||
354 | { | ||
355 | skipSection(reader); | ||
356 | } | ||
357 | else if(data[0] == "sale_info") | ||
358 | { | ||
359 | skipSection(reader); | ||
360 | } | ||
361 | else if (line.IndexOf('{') >= 0) | ||
362 | { | ||
363 | throw new NotANotecardFormatException(reader.LineNumber); | ||
364 | } | ||
365 | } | ||
366 | } | ||
367 | |||
368 | private static void skipInventoryItems(NotecardReader reader) | ||
369 | { | ||
370 | if(reader.getLine() != "{") | ||
371 | { | ||
372 | throw new NotANotecardFormatException(reader.LineNumber); | ||
373 | } | ||
296 | 374 | ||
297 | if (input[idx]== "}") | 375 | string line; |
376 | while((line = reader.getLine()) != "}") | ||
377 | { | ||
378 | string[] data = line.Split(' '); | ||
379 | if(data.Length == 0) | ||
298 | { | 380 | { |
299 | level--; | ||
300 | idx++; | ||
301 | continue; | 381 | continue; |
302 | } | 382 | } |
303 | 383 | ||
304 | switch (level) | 384 | if(data[0] == "inv_item") |
305 | { | 385 | { |
306 | case 0: | 386 | skipInventoryItem(reader); |
307 | words = input[idx].Split(' '); // Linden text ver | 387 | } |
308 | // Notecards are created *really* empty. Treat that as "no text" (just like after saving an empty notecard) | 388 | else if (line.IndexOf('{') >= 0) |
309 | if (words.Length < 3) | 389 | { |
310 | return output; | 390 | throw new NotANotecardFormatException(reader.LineNumber); |
311 | 391 | } | |
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 | 392 | ||
324 | //Number of lines in notecard. | 393 | } |
325 | int lines = input.Length - idx; | 394 | } |
326 | int line = 0; | ||
327 | 395 | ||
328 | while (line < lines) | 396 | private static void skipInventory(NotecardReader reader) |
329 | { | 397 | { |
330 | // m_log.DebugFormat("[PARSE NOTECARD]: Adding line {0}", input[idx]); | 398 | if (reader.getLine() != "{") |
331 | output.Add(input[idx]); | 399 | throw new NotANotecardFormatException(reader.LineNumber); |
332 | idx++; | ||
333 | line++; | ||
334 | } | ||
335 | 400 | ||
336 | return output; | 401 | string line; |
337 | } | 402 | while((line = reader.getLine()) != "}") |
338 | break; | 403 | { |
339 | case 2: | 404 | string[] data = line.Split(' '); |
340 | words = input[idx].Split(' '); // count | 405 | if(data[0] == "count") |
341 | if (words[0] == "count") | 406 | { |
407 | int count = Int32.Parse(data[1]); | ||
408 | for(int i = 0; i < count; ++i) | ||
342 | { | 409 | { |
343 | int c = int.Parse(words[1]); | 410 | skipInventoryItems(reader); |
344 | if (c > 0) | ||
345 | return output; | ||
346 | break; | ||
347 | } | 411 | } |
348 | break; | ||
349 | } | 412 | } |
350 | idx++; | 413 | else if (line.IndexOf('{') >= 0) |
414 | { | ||
415 | throw new NotANotecardFormatException(reader.LineNumber); | ||
416 | } | ||
351 | } | 417 | } |
352 | 418 | } | |
353 | return output; | 419 | |
420 | private static string readNotecardText(NotecardReader reader) | ||
421 | { | ||
422 | if (reader.getLine() != "{") | ||
423 | throw new NotANotecardFormatException(reader.LineNumber); | ||
424 | |||
425 | string notecardString = string.Empty; | ||
426 | string line; | ||
427 | while((line = reader.getLine()) != "}") | ||
428 | { | ||
429 | string[] data = line.Split(' '); | ||
430 | if (data.Length == 0) | ||
431 | { | ||
432 | continue; | ||
433 | } | ||
434 | |||
435 | if (data[0] == "LLEmbeddedItems") | ||
436 | { | ||
437 | skipInventory(reader); | ||
438 | } | ||
439 | else if(data[0] == "Text" && data.Length == 3) | ||
440 | { | ||
441 | int length = Int32.Parse(data[2]); | ||
442 | notecardString = reader.getBlock(length); | ||
443 | } | ||
444 | else if (line.IndexOf('{') >= 0) | ||
445 | { | ||
446 | throw new NotANotecardFormatException(reader.LineNumber); | ||
447 | } | ||
448 | |||
449 | } | ||
450 | return notecardString; | ||
451 | } | ||
452 | |||
453 | private static string readNotecard(byte[] rawInput) | ||
454 | { | ||
455 | string rawIntermedInput = string.Empty; | ||
456 | |||
457 | /* make up a Raw Encoding here */ | ||
458 | foreach(byte c in rawInput) | ||
459 | { | ||
460 | char d = (char)c; | ||
461 | rawIntermedInput += d; | ||
462 | } | ||
463 | |||
464 | NotecardReader reader = new NotecardReader(rawIntermedInput); | ||
465 | string line; | ||
466 | try | ||
467 | { | ||
468 | line = reader.getLine(); | ||
469 | } | ||
470 | catch(Exception) | ||
471 | { | ||
472 | return System.Text.Encoding.UTF8.GetString(rawInput); | ||
473 | } | ||
474 | string[] versioninfo = line.Split(' '); | ||
475 | if(versioninfo.Length < 3) | ||
476 | { | ||
477 | return System.Text.Encoding.UTF8.GetString(rawInput); | ||
478 | } | ||
479 | else if(versioninfo[0] != "Linden" || versioninfo[1] != "text") | ||
480 | { | ||
481 | return System.Text.Encoding.UTF8.GetString(rawInput); | ||
482 | } | ||
483 | else | ||
484 | { | ||
485 | /* now we actually decode the Encoding, before we needed it in raw */ | ||
486 | string o = readNotecardText(reader); | ||
487 | byte[] a = new byte[o.Length]; | ||
488 | for(int i = 0; i < o.Length; ++i) | ||
489 | { | ||
490 | a[i] = (byte)o[i]; | ||
491 | } | ||
492 | return System.Text.Encoding.UTF8.GetString(a); | ||
493 | } | ||
494 | } | ||
495 | |||
496 | /// <summary> | ||
497 | /// Parse a notecard in Linden format to a string of ordinary text. | ||
498 | /// </summary> | ||
499 | /// <param name="rawInput"></param> | ||
500 | /// <returns></returns> | ||
501 | public static string ParseNotecardToString(byte[] rawInput) | ||
502 | { | ||
503 | return readNotecard(rawInput); | ||
504 | } | ||
505 | |||
506 | /// <summary> | ||
507 | /// Parse a notecard in Linden format to a list of ordinary lines. | ||
508 | /// </summary> | ||
509 | /// <param name="rawInput"></param> | ||
510 | /// <returns></returns> | ||
511 | public static string[] ParseNotecardToArray(byte[] rawInput) | ||
512 | { | ||
513 | return readNotecard(rawInput).Replace("\r", "").Split('\n'); | ||
354 | } | 514 | } |
355 | } | 515 | } |
356 | } | 516 | } |
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs index b69676b..edf51a2 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs | |||
@@ -595,11 +595,15 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
595 | 595 | ||
596 | try | 596 | try |
597 | { | 597 | { |
598 | string jsondata = SLUtil.ParseNotecardToString(Encoding.UTF8.GetString(a.Data)); | 598 | string jsondata = SLUtil.ParseNotecardToString(a.Data); |
599 | int result = m_store.SetValue(storeID, path, jsondata,true) ? 1 : 0; | 599 | int result = m_store.SetValue(storeID, path, jsondata,true) ? 1 : 0; |
600 | m_comms.DispatchReply(scriptID, result, "", reqID.ToString()); | 600 | m_comms.DispatchReply(scriptID, result, "", reqID.ToString()); |
601 | return; | 601 | return; |
602 | } | 602 | } |
603 | catch(SLUtil.NotANotecardFormatException e) | ||
604 | { | ||
605 | m_log.WarnFormat("[JsonStoreScripts]: Notecard parsing failed; assetId {0} at line number {1}", assetID.ToString(), e.lineNumber); | ||
606 | } | ||
603 | catch (Exception e) | 607 | catch (Exception e) |
604 | { | 608 | { |
605 | m_log.WarnFormat("[JsonStoreScripts]: Json parsing failed; {0}", e.Message); | 609 | m_log.WarnFormat("[JsonStoreScripts]: Json parsing failed; {0}", e.Message); |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index bb8ec9c..6a30da2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -11632,9 +11632,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11632 | return; | 11632 | return; |
11633 | } | 11633 | } |
11634 | 11634 | ||
11635 | string data = Encoding.UTF8.GetString(a.Data); | 11635 | NotecardCache.Cache(id, a.Data); |
11636 | //m_log.Debug(data); | ||
11637 | NotecardCache.Cache(id, data); | ||
11638 | AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(id).ToString()); | 11636 | AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(id).ToString()); |
11639 | }); | 11637 | }); |
11640 | 11638 | ||
@@ -11688,7 +11686,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11688 | 11686 | ||
11689 | string data = Encoding.UTF8.GetString(a.Data); | 11687 | string data = Encoding.UTF8.GetString(a.Data); |
11690 | //m_log.Debug(data); | 11688 | //m_log.Debug(data); |
11691 | NotecardCache.Cache(id, data); | 11689 | NotecardCache.Cache(id, a.Data); |
11692 | AsyncCommands.DataserverPlugin.DataserverReply( | 11690 | AsyncCommands.DataserverPlugin.DataserverReply( |
11693 | reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); | 11691 | reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); |
11694 | }); | 11692 | }); |
@@ -12461,10 +12459,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
12461 | public DateTime lastRef; | 12459 | public DateTime lastRef; |
12462 | } | 12460 | } |
12463 | 12461 | ||
12464 | protected static Dictionary<UUID, Notecard> m_Notecards = | 12462 | private static Dictionary<UUID, Notecard> m_Notecards = |
12465 | new Dictionary<UUID, Notecard>(); | 12463 | new Dictionary<UUID, Notecard>(); |
12466 | 12464 | ||
12467 | public static void Cache(UUID assetID, string text) | 12465 | public static void Cache(UUID assetID, byte[] text) |
12468 | { | 12466 | { |
12469 | CheckCache(); | 12467 | CheckCache(); |
12470 | 12468 | ||
@@ -12475,7 +12473,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
12475 | 12473 | ||
12476 | Notecard nc = new Notecard(); | 12474 | Notecard nc = new Notecard(); |
12477 | nc.lastRef = DateTime.Now; | 12475 | nc.lastRef = DateTime.Now; |
12478 | nc.text = SLUtil.ParseNotecardToList(text).ToArray(); | 12476 | try |
12477 | { | ||
12478 | nc.text = SLUtil.ParseNotecardToArray(text); | ||
12479 | } | ||
12480 | catch(SLUtil.NotANotecardFormatException) | ||
12481 | { | ||
12482 | nc.text = new string[0]; | ||
12483 | } | ||
12479 | m_Notecards[assetID] = nc; | 12484 | m_Notecards[assetID] = nc; |
12480 | } | 12485 | } |
12481 | } | 12486 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 10ddf14..3afebe2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | |||
@@ -1926,8 +1926,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1926 | if (a == null) | 1926 | if (a == null) |
1927 | return UUID.Zero; | 1927 | return UUID.Zero; |
1928 | 1928 | ||
1929 | string data = Encoding.UTF8.GetString(a.Data); | 1929 | NotecardCache.Cache(assetID, a.Data); |
1930 | NotecardCache.Cache(assetID, data); | ||
1931 | }; | 1930 | }; |
1932 | 1931 | ||
1933 | return assetID; | 1932 | return assetID; |