Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebServiceTarget - Fix boolean parameter conversion for Xml and Json (lowercase) & merged the JSON serializer code into DefaultJsonSerializer #2017

Merged
merged 1 commit into from Mar 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
93 changes: 93 additions & 0 deletions src/NLog/Internal/XmlHelper.cs
Expand Up @@ -98,6 +98,99 @@ private static string CreateValidXmlString(string text)
}
#endif

/// <summary>
/// Converts object value to invariant format, and strips any invalid xml-characters
/// </summary>
/// <param name="value">Object value</param>
/// <returns>Object value converted to string</returns>
internal static string XmlConvertToStringSafe(object value)
{
string valueString = XmlConvertToString(value);
return RemoveInvalidXmlChars(valueString);
}

/// <summary>
/// Converts object value to invariant format (understood by JavaScript)
/// </summary>
/// <param name="value">Object value</param>
/// <returns>Object value converted to string</returns>
internal static string XmlConvertToString(object value)
{
TypeCode objTypeCode;
return XmlConvertToString(value, out objTypeCode);
}

/// <summary>
/// Converts object value to invariant format (understood by JavaScript)
/// </summary>
/// <param name="value">Object value</param>
/// <param name="objTypeCode">Object TypeCode</param>
/// <returns>Object value converted to string</returns>
internal static string XmlConvertToString(object value, out TypeCode objTypeCode)
{
if (value == null)
{
objTypeCode = TypeCode.Empty;
return "null";
}

objTypeCode = Convert.GetTypeCode(value);
switch (objTypeCode)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is working with typecode better than type? Any idea of the .NET core support?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think switch-statement is faster than dictionary-lookup. System.Convert.GetTypeCode should also work in NET Core (It is System.Type.GetTypeCode that has been removed).

{
case TypeCode.Boolean:
return XmlConvert.ToString((Boolean)value); // boolean as lowercase
case TypeCode.Byte:
return XmlConvert.ToString((Byte)value);
case TypeCode.SByte:
return XmlConvert.ToString((SByte)value);
case TypeCode.Int16:
return XmlConvert.ToString((Int16)value);
case TypeCode.Int32:
return XmlConvert.ToString((Int32)value);
case TypeCode.Int64:
return XmlConvert.ToString((Int64)value);
case TypeCode.UInt16:
return XmlConvert.ToString((UInt16)value);
case TypeCode.UInt32:
return XmlConvert.ToString((UInt32)value);
case TypeCode.UInt64:
return XmlConvert.ToString((UInt64)value);
case TypeCode.Single:
{
float singleValue = (Single)value;
if (float.IsInfinity(singleValue))
return Convert.ToString(singleValue, System.Globalization.CultureInfo.InvariantCulture); // Infinity instead of INF
else
return XmlConvert.ToString(singleValue); // 8 digits scale
}
case TypeCode.Double:
{
double doubleValue = (Double)value;
if (double.IsInfinity(doubleValue))
return Convert.ToString(doubleValue, System.Globalization.CultureInfo.InvariantCulture); // Infinity instead of INF
else
return XmlConvert.ToString(doubleValue); // 16 digits scale
}
case TypeCode.Decimal:
return XmlConvert.ToString((Decimal)value);
case TypeCode.DateTime:
return XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.Utc);
case TypeCode.Char:
return XmlConvert.ToString((Char)value);
case TypeCode.String:
return (string)value;
default:
try
{
return Convert.ToString(value, System.Globalization.CultureInfo.InvariantCulture);
}
catch
{
return null;
}
}
}

/// <summary>
/// Safe version of WriteAttributeString
/// </summary>
Expand Down
44 changes: 28 additions & 16 deletions src/NLog/LayoutRenderers/Log4JXmlEventLayoutRenderer.cs
Expand Up @@ -259,34 +259,47 @@ protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
xtw.WriteAttributeSafeString("assembly", type.Assembly.FullName);
}

xtw.WriteEndElement();
}
}
}

xtw.WriteStartElement("nlog", "properties", dummyNLogNamespace);
if (logEvent.HasProperties)
{
foreach (var contextProperty in logEvent.Properties)
{
xtw.WriteStartElement("nlog", "data", dummyNLogNamespace);
xtw.WriteAttributeSafeString("name", Convert.ToString(contextProperty.Key, CultureInfo.InvariantCulture));
xtw.WriteAttributeSafeString("value", Convert.ToString(contextProperty.Value, CultureInfo.InvariantCulture));
xtw.WriteEndElement();
}
}
if (this.IncludeNLogData)
{
xtw.WriteStartElement("nlog", "properties", dummyNLogNamespace);
if (logEvent.HasProperties)
{
foreach (var contextProperty in logEvent.Properties)
{
string propertyKey = XmlHelper.XmlConvertToString(contextProperty.Key);
if (string.IsNullOrEmpty(propertyKey))
continue;

string propertyValue = XmlHelper.XmlConvertToString(contextProperty.Value);
if (propertyValue == null)
continue;

xtw.WriteStartElement("nlog", "data", dummyNLogNamespace);
xtw.WriteAttributeSafeString("name", propertyKey);
xtw.WriteAttributeSafeString("value", propertyValue);
xtw.WriteEndElement();
}

}
xtw.WriteEndElement();
}

xtw.WriteStartElement("log4j", "properties", dummyNamespace);
if (this.IncludeMdc)
{
foreach (string key in MappedDiagnosticsContext.GetNames())
{
string propertyValue = XmlHelper.XmlConvertToString(MappedDiagnosticsContext.GetObject(key));
if (propertyValue == null)
continue;

xtw.WriteStartElement("log4j", "data", dummyNamespace);
xtw.WriteAttributeSafeString("name", key);
xtw.WriteAttributeSafeString("value", String.Format(logEvent.FormatProvider, "{0}", MappedDiagnosticsContext.GetObject(key)));
xtw.WriteAttributeSafeString("value", propertyValue);
xtw.WriteEndElement();
}
}
Expand All @@ -309,10 +322,9 @@ protected override void Append(StringBuilder builder, LogEventInfo logEvent)

xtw.WriteStartElement("log4j", "data", dummyNamespace);
xtw.WriteAttributeSafeString("name", "log4jmachinename");

xtw.WriteAttributeSafeString("value", this.machineName);

xtw.WriteEndElement();

xtw.WriteEndElement();

xtw.WriteEndElement();
Expand Down
Expand Up @@ -68,95 +68,7 @@ public JsonEncodeLayoutRendererWrapper()
/// <returns>JSON-encoded string.</returns>
protected override string Transform(string text)
{
return this.JsonEncode ? DoJsonEscape(text) : text;
}

private static string DoJsonEscape(string text)
{
StringBuilder sb = null;
for (int i = 0; i < text.Length; ++i)
{
char ch = text[i];
if (sb == null)
{
// Check if we need to upgrade to StringBuilder
if (!NeedsEscaping(ch))
{
switch (ch)
{
case '"':
case '\\':
case '/':
break;

default:
continue; // StringBuilder not needed, yet
}
}

// StringBuilder needed
sb = new StringBuilder(text.Length + 4);
sb.Append(text, 0, i);
}

switch (text[i])
{
case '"':
sb.Append("\\\"");
break;

case '\\':
sb.Append("\\\\");
break;

case '/':
sb.Append("\\/");
break;

case '\b':
sb.Append("\\b");
break;

case '\r':
sb.Append("\\r");
break;

case '\n':
sb.Append("\\n");
break;

case '\f':
sb.Append("\\f");
break;

case '\t':
sb.Append("\\t");
break;

default:
if (NeedsEscaping(text[i]))
{
sb.Append("\\u");
sb.Append(Convert.ToString((int)text[i], 16).PadLeft(4, '0'));
}
else
{
sb.Append(text[i]);
}

break;
}
}

if (sb != null)
return sb.ToString();
else
return text;
}

private static bool NeedsEscaping(char ch)
{
return ch < 32 || ch > 127;
return this.JsonEncode ? Targets.DefaultJsonSerializer.JsonStringEscape(text) : text;
}
}
}