mantis 8271: work around missing encoding of estate bans on the pseudo url encode used on POST, without changing the xml also used elsewhere. Possible this can be used in other case

0.9.0.1-postfixes
UbitUmarov 2017-12-30 15:28:26 +00:00
parent f0fd15ccc9
commit 8032898773
2 changed files with 117 additions and 54 deletions

View File

@ -573,13 +573,40 @@ namespace OpenSim.Framework
// EstateBans are special // EstateBans are special
if (map.ContainsKey("EstateBans")) if (map.ContainsKey("EstateBans"))
{ {
var banData = ((Dictionary<string, object>)map["EstateBans"]).Values; if(map["EstateBans"] is string)
EstateBan[] bans = new EstateBan[banData.Count]; {
int b = 0; // JSON encoded bans map
foreach (Dictionary<string, object> ban in banData) Dictionary<string, EstateBan> bdata = new Dictionary<string, EstateBan>();
bans[b++] = new EstateBan(ban); try
PropertyInfo bansProperty = this.GetType().GetProperty("EstateBans", BindingFlags.Public | BindingFlags.Instance); {
bansProperty.SetValue(this, bans, null); // bypass libovm, we dont need even more useless high level maps
// this should only be called once.. but no problem, i hope
// (other uses may need more..)
LitJson.JsonMapper.RegisterImporter<string, UUID>((input) => new UUID(input));
bdata = LitJson.JsonMapper.ToObject<Dictionary<string,EstateBan>>((string)map["EstateBans"]);
}
// catch(Exception e)
catch
{
return;
}
EstateBan[] jbans = new EstateBan[bdata.Count];
bdata.Values.CopyTo(jbans,0);
PropertyInfo jbansProperty = this.GetType().GetProperty("EstateBans", BindingFlags.Public | BindingFlags.Instance);
jbansProperty.SetValue(this, jbans, null);
}
else
{
var banData = ((Dictionary<string, object>)map["EstateBans"]).Values;
EstateBan[] bans = new EstateBan[banData.Count];
int b = 0;
foreach (Dictionary<string, object> ban in banData)
bans[b++] = new EstateBan(ban);
PropertyInfo bansProperty = this.GetType().GetProperty("EstateBans", BindingFlags.Public | BindingFlags.Instance);
bansProperty.SetValue(this, bans, null);
}
} }
} }
} }

View File

@ -39,7 +39,7 @@ using OpenMetaverse;
using Mono.Addins; using Mono.Addins;
using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Framework.Servers; using OpenSim.Framework.Servers;
using OpenMetaverse.StructuredData; // LitJson is hidden on this
[assembly:AddinRoot("Robust", OpenSim.VersionInfo.VersionNumber)] [assembly:AddinRoot("Robust", OpenSim.VersionInfo.VersionNumber)]
namespace OpenSim.Server.Base namespace OpenSim.Server.Base
@ -327,49 +327,62 @@ namespace OpenSim.Server.Base
public static Dictionary<string, object> ParseQueryString(string query) public static Dictionary<string, object> ParseQueryString(string query)
{ {
Dictionary<string, object> result = new Dictionary<string, object>();
string[] terms = query.Split(new char[] {'&'}); string[] terms = query.Split(new char[] {'&'});
if (terms.Length == 0) int nterms = terms.Length;
return result; if (nterms == 0)
return new Dictionary<string, object>();
foreach (string t in terms) Dictionary<string, object> result = new Dictionary<string, object>(nterms);
string name;
for(int i = 0; i < nterms; ++i)
{ {
string[] elems = t.Split(new char[] {'='}); string[] elems = terms[i].Split(new char[] {'='});
if (elems.Length == 0) if (elems.Length == 0)
continue; continue;
string name = System.Web.HttpUtility.UrlDecode(elems[0]); if(String.IsNullOrWhiteSpace(elems[0]))
string value = String.Empty; continue;
if (elems.Length > 1) name = System.Web.HttpUtility.UrlDecode(elems[0]);
value = System.Web.HttpUtility.UrlDecode(elems[1]);
if (name.EndsWith("[]")) if (name.EndsWith("[]"))
{ {
string cleanName = name.Substring(0, name.Length - 2); name = name.Substring(0, name.Length - 2);
if (result.ContainsKey(cleanName)) if(String.IsNullOrWhiteSpace(name))
continue;
if (result.ContainsKey(name))
{ {
if (!(result[cleanName] is List<string>)) if (!(result[name] is List<string>))
continue; continue;
List<string> l = (List<string>)result[cleanName]; List<string> l = (List<string>)result[name];
if (elems.Length > 1 && !String.IsNullOrWhiteSpace(elems[1]))
l.Add(value); l.Add(System.Web.HttpUtility.UrlDecode(elems[1]));
else
l.Add(String.Empty);
} }
else else
{ {
List<string> newList = new List<string>(); List<string> newList = new List<string>();
if (elems.Length > 1 && !String.IsNullOrWhiteSpace(elems[1]))
newList.Add(value); newList.Add(System.Web.HttpUtility.UrlDecode(elems[1]));
else
result[cleanName] = newList; newList.Add(String.Empty);
result[name] = newList;
} }
} }
else else
{ {
if (!result.ContainsKey(name)) if (!result.ContainsKey(name))
result[name] = value; {
if (elems.Length > 1 && !String.IsNullOrWhiteSpace(elems[1]))
result[name] = System.Web.HttpUtility.UrlDecode(elems[1]);
else
result[name] = String.Empty;
}
} }
} }
@ -378,47 +391,70 @@ namespace OpenSim.Server.Base
public static string BuildQueryString(Dictionary<string, object> data) public static string BuildQueryString(Dictionary<string, object> data)
{ {
string qstring = String.Empty; // this is not conform to html url encoding
// can only be used on Body of POST or PUT
StringBuilder sb = new StringBuilder(4096);
string part; string pvalue;
foreach (KeyValuePair<string, object> kvp in data) foreach (KeyValuePair<string, object> kvp in data)
{ {
if (kvp.Value is List<string>) if (kvp.Value is List<string>)
{ {
List<string> l = (List<String>)kvp.Value; List<string> l = (List<String>)kvp.Value;
int llen = l.Count;
foreach (string s in l) string nkey = System.Web.HttpUtility.UrlEncode(kvp.Key);
for(int i = 0; i < llen; ++i)
{ {
part = System.Web.HttpUtility.UrlEncode(kvp.Key) + if (sb.Length != 0)
"[]=" + System.Web.HttpUtility.UrlEncode(s); sb.Append("&");
sb.Append(nkey);
if (qstring != String.Empty) sb.Append("[]=");
qstring += "&"; sb.Append(System.Web.HttpUtility.UrlEncode(l[i]));
qstring += part;
} }
} }
else if(kvp.Value is Dictionary<string, object>)
{
// encode complex structures as JSON
// needed for estate bans with the encoding used on xml
// encode can be here because object does contain the structure information
// but decode needs to be on estateSettings (or other user)
string js;
try
{
// bypass libovm, we dont need even more useless high level maps
// this should only be called once.. but no problem, i hope
// (other uses may need more..)
LitJson.JsonMapper.RegisterExporter<UUID>((uuid, writer) => writer.Write(uuid.ToString()) );
js = LitJson.JsonMapper.ToJson(kvp.Value);
}
// catch(Exception e)
catch
{
continue;
}
if (sb.Length != 0)
sb.Append("&");
sb.Append(System.Web.HttpUtility.UrlEncode(kvp.Key));
sb.Append("=");
sb.Append(System.Web.HttpUtility.UrlEncode(js));
}
else else
{ {
if (kvp.Value.ToString() != String.Empty) if (sb.Length != 0)
{ sb.Append("&");
part = System.Web.HttpUtility.UrlEncode(kvp.Key) + sb.Append(System.Web.HttpUtility.UrlEncode(kvp.Key));
"=" + System.Web.HttpUtility.UrlEncode(kvp.Value.ToString());
}
else
{
part = System.Web.HttpUtility.UrlEncode(kvp.Key);
}
if (qstring != String.Empty) pvalue = kvp.Value.ToString();
qstring += "&"; if (!String.IsNullOrEmpty(pvalue))
{
qstring += part; sb.Append("=");
sb.Append(System.Web.HttpUtility.UrlEncode(pvalue));
}
} }
} }
return qstring; return sb.ToString();
} }
public static string BuildXmlResponse(Dictionary<string, object> data) public static string BuildXmlResponse(Dictionary<string, object> data)