aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared
diff options
context:
space:
mode:
authornebadon2011-12-11 23:25:12 -0700
committernebadon2011-12-11 23:25:12 -0700
commit8ae824ff095605c5889828503cec09006ac07cc0 (patch)
treec87dcf50a53184b21e30b287200d903db9f17948 /OpenSim/Region/ScriptEngine/Shared
parentImplement handler for TeleportCancel inbound packet (diff)
downloadopensim-SC-8ae824ff095605c5889828503cec09006ac07cc0.zip
opensim-SC-8ae824ff095605c5889828503cec09006ac07cc0.tar.gz
opensim-SC-8ae824ff095605c5889828503cec09006ac07cc0.tar.bz2
opensim-SC-8ae824ff095605c5889828503cec09006ac07cc0.tar.xz
Mantis 5816: osParseJSON Decoding Problems
osParseJSON uses hand-crafted decoding that has two issues * does not seem to handle top-level JSON lists * does not seem to handle unicode text thanks otakup0pe!
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs256
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs5
3 files changed, 72 insertions, 191 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index f3206ac..503b5d0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -1552,209 +1552,83 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1552 return m_ScriptEngine.World.GetSimulatorVersion(); 1552 return m_ScriptEngine.World.GetSimulatorVersion();
1553 } 1553 }
1554 1554
1555 public Hashtable osParseJSON(string JSON) 1555 private Hashtable osdToHashtable(OSDMap map)
1556 {
1557 Hashtable result = new Hashtable();
1558 foreach (KeyValuePair<string, OSD> item in map) {
1559 result.Add(item.Key, osdToObject(item.Value));
1560 }
1561 return result;
1562 }
1563
1564 private ArrayList osdToArray(OSDArray list)
1565 {
1566 ArrayList result = new ArrayList();
1567 foreach ( OSD item in list ) {
1568 result.Add(osdToObject(item));
1569 }
1570 return result;
1571 }
1572
1573 private Object osdToObject(OSD decoded)
1574 {
1575 if ( decoded is OSDString ) {
1576 return (string) decoded.AsString();
1577 } else if ( decoded is OSDInteger ) {
1578 return (int) decoded.AsInteger();
1579 } else if ( decoded is OSDReal ) {
1580 return (float) decoded.AsReal();
1581 } else if ( decoded is OSDBoolean ) {
1582 return (bool) decoded.AsBoolean();
1583 } else if ( decoded is OSDMap ) {
1584 return osdToHashtable((OSDMap) decoded);
1585 } else if ( decoded is OSDArray ) {
1586 return osdToArray((OSDArray) decoded);
1587 } else {
1588 return null;
1589 }
1590 }
1591
1592 public Object osParseJSONNew(string JSON)
1556 { 1593 {
1557 CheckThreatLevel(ThreatLevel.None, "osParseJSON"); 1594 CheckThreatLevel(ThreatLevel.None, "osParseJSON");
1558 1595
1559 m_host.AddScriptLPS(1); 1596 m_host.AddScriptLPS(1);
1560 1597
1561 // see http://www.json.org/ for more details on JSON
1562
1563 string currentKey = null;
1564 Stack objectStack = new Stack(); // objects in JSON can be nested so we need to keep a track of this
1565 Hashtable jsondata = new Hashtable(); // the hashtable to be returned
1566 int i = 0;
1567 try 1598 try
1568 { 1599 {
1600 OSD decoded = OSDParser.DeserializeJson(JSON);
1601 return osdToObject(decoded);
1602 }
1603 catch(Exception e)
1604 {
1605 OSSLError("osParseJSONNew: Problems decoding JSON string " + JSON + " : " + e.Message) ;
1606 return null;
1607 }
1608 }
1569 1609
1570 // iterate through the serialised stream of tokens and store at the right depth in the hashtable 1610 public Hashtable osParseJSON(string JSON)
1571 // the top level hashtable may contain more nested hashtables within it each containing an objects representation 1611 {
1572 for (i = 0; i < JSON.Length; i++) 1612 CheckThreatLevel(ThreatLevel.None, "osParseJSON");
1573 {
1574
1575 // m_log.Debug(""+JSON[i]);
1576 switch (JSON[i])
1577 {
1578 case '{':
1579 // create hashtable and add it to the stack or array if we are populating one, we can have a lot of nested objects in JSON
1580
1581 Hashtable currentObject = new Hashtable();
1582 if (objectStack.Count == 0) // the stack should only be empty for the first outer object
1583 {
1584
1585 objectStack.Push(jsondata);
1586 }
1587 else if (objectStack.Peek().ToString() == "System.Collections.ArrayList")
1588 {
1589 // add it to the parent array
1590 ((ArrayList)objectStack.Peek()).Add(currentObject);
1591 objectStack.Push(currentObject);
1592 }
1593 else
1594 {
1595 // add it to the parent hashtable
1596 ((Hashtable)objectStack.Peek()).Add(currentKey,currentObject);
1597 objectStack.Push(currentObject);
1598 }
1599
1600 // clear the key
1601 currentKey = null;
1602 break;
1603
1604 case '}':
1605 // pop the hashtable off the stack
1606 objectStack.Pop();
1607 break;
1608
1609 case '"':// string boundary
1610
1611 string tokenValue = "";
1612 i++; // move to next char
1613
1614 // just loop through until the next quote mark storing the string, ignore quotes with pre-ceding \
1615 while (JSON[i] != '"')
1616 {
1617 tokenValue += JSON[i];
1618
1619 // handle escaped double quotes \"
1620 if (JSON[i] == '\\' && JSON[i+1] == '"')
1621 {
1622 tokenValue += JSON[i+1];
1623 i++;
1624 }
1625 i++;
1626
1627 }
1628
1629 // ok we've got a string, if we've got an array on the top of the stack then we store it
1630 if (objectStack.Peek().ToString() == "System.Collections.ArrayList")
1631 {
1632 ((ArrayList)objectStack.Peek()).Add(tokenValue);
1633 }
1634 else if (currentKey == null) // no key stored and its not an array this must be a key so store it
1635 {
1636 currentKey = tokenValue;
1637 }
1638 else
1639 {
1640 // we have a key so lets store this value
1641 ((Hashtable)objectStack.Peek()).Add(currentKey,tokenValue);
1642 // now lets clear the key, we're done with it and moving on
1643 currentKey = null;
1644 }
1645
1646 break;
1647
1648 case ':':// key : value separator
1649 // just ignore
1650 break;
1651
1652 case ' ':// spaces
1653 // just ignore
1654 break;
1655
1656 case '[': // array start
1657 ArrayList currentArray = new ArrayList();
1658
1659 if (objectStack.Peek().ToString() == "System.Collections.ArrayList")
1660 {
1661 ((ArrayList)objectStack.Peek()).Add(currentArray);
1662 }
1663 else
1664 {
1665 ((Hashtable)objectStack.Peek()).Add(currentKey,currentArray);
1666 // clear the key
1667 currentKey = null;
1668 }
1669 objectStack.Push(currentArray);
1670
1671 break;
1672
1673 case ',':// seperator
1674 // just ignore
1675 break;
1676
1677 case ']'://Array end
1678 // pop the array off the stack
1679 objectStack.Pop();
1680 break;
1681
1682 case 't': // we've found a character start not in quotes, it must be a boolean true
1683
1684 if (objectStack.Peek().ToString() == "System.Collections.ArrayList")
1685 {
1686 ((ArrayList)objectStack.Peek()).Add(true);
1687 }
1688 else
1689 {
1690 ((Hashtable)objectStack.Peek()).Add(currentKey,true);
1691 currentKey = null;
1692 }
1693
1694 //advance the counter to the letter 'e'
1695 i = i + 3;
1696 break;
1697
1698 case 'f': // we've found a character start not in quotes, it must be a boolean false
1699
1700 if (objectStack.Peek().ToString() == "System.Collections.ArrayList")
1701 {
1702 ((ArrayList)objectStack.Peek()).Add(false);
1703 }
1704 else
1705 {
1706 ((Hashtable)objectStack.Peek()).Add(currentKey,false);
1707 currentKey = null;
1708 }
1709 //advance the counter to the letter 'e'
1710 i = i + 4;
1711 break;
1712
1713 case '\n':// carriage return
1714 // just ignore
1715 break;
1716
1717 case '\r':// carriage return
1718 // just ignore
1719 break;
1720
1721 default:
1722 // ok here we're catching all numeric types int,double,long we might want to spit these up mr accurately
1723 // but for now we'll just do them as strings
1724
1725 string numberValue = "";
1726
1727 // just loop through until the next known marker quote mark storing the string
1728 while (JSON[i] != '"' && JSON[i] != ',' && JSON[i] != ']' && JSON[i] != '}' && JSON[i] != ' ')
1729 {
1730 numberValue += "" + JSON[i++];
1731 }
1732
1733 i--; // we want to process this caracter that marked the end of this string in the main loop
1734 1613
1735 // ok we've got a string, if we've got an array on the top of the stack then we store it 1614 m_host.AddScriptLPS(1);
1736 if (objectStack.Peek().ToString() == "System.Collections.ArrayList")
1737 {
1738 ((ArrayList)objectStack.Peek()).Add(numberValue);
1739 }
1740 else
1741 {
1742 // we have a key so lets store this value
1743 ((Hashtable)objectStack.Peek()).Add(currentKey,numberValue);
1744 // now lets clear the key, we're done with it and moving on
1745 currentKey = null;
1746 }
1747 1615
1748 break; 1616 Object decoded = osParseJSONNew(JSON);
1749 } 1617
1618 if ( decoded is Hashtable ) {
1619 return (Hashtable) decoded;
1620 } else if ( decoded is ArrayList ) {
1621 ArrayList decoded_list = (ArrayList) decoded;
1622 Hashtable fakearray = new Hashtable();
1623 int i = 0;
1624 for ( i = 0; i < decoded_list.Count ; i++ ) {
1625 fakearray.Add(i, decoded_list[i]);
1750 } 1626 }
1627 return fakearray;
1628 } else {
1629 OSSLError("osParseJSON: unable to parse JSON string " + JSON);
1630 return null;
1751 } 1631 }
1752 catch(Exception)
1753 {
1754 OSSLError("osParseJSON: The JSON string is not valid " + JSON) ;
1755 }
1756
1757 return jsondata;
1758 } 1632 }
1759 1633
1760 /// <summary> 1634 /// <summary>
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 3221833..00ca070 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -25,6 +25,7 @@
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.Collections; 29using System.Collections;
29using OpenSim.Region.ScriptEngine.Interfaces; 30using OpenSim.Region.ScriptEngine.Interfaces;
30 31
@@ -140,6 +141,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
140 141
141 string osGetScriptEngineName(); 142 string osGetScriptEngineName();
142 string osGetSimulatorVersion(); 143 string osGetSimulatorVersion();
144 Object osParseJSONNew(string JSON);
143 Hashtable osParseJSON(string JSON); 145 Hashtable osParseJSON(string JSON);
144 146
145 void osMessageObject(key objectUUID,string message); 147 void osMessageObject(key objectUUID,string message);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index 9e7c8da..0d7d5ea 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -396,6 +396,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
396 { 396 {
397 return m_OSSL_Functions.osParseJSON(JSON); 397 return m_OSSL_Functions.osParseJSON(JSON);
398 } 398 }
399
400 public Object osParseJSONNew(string JSON)
401 {
402 return m_OSSL_Functions.osParseJSONNew(JSON);
403 }
399 404
400 public void osMessageObject(key objectUUID,string message) 405 public void osMessageObject(key objectUUID,string message)
401 { 406 {