Как я могу отфильтровать этот незаконный символ JavaScript? Это генерируется во время выполнения
Я пытаюсь сгенерировать пользовательскую подсказку, используя элементы управления Microsoft Chart. Элементы управления Microsoft Chart поддерживают возможность использования ключевых слов, которые помогают автоматизировать данные, которые вы хотите отобразить.
Например,
string toolTip = string.Format("<div> {0}: {1} {3} ({2}) </div>", seriesName, "#VALY", "#VALX", "<br>");
series.MapAreaAttributes = "onfocus=\"if(this.blur)this.blur();\" onmouseover=\"DisplayTooltip('" + JavaScriptStringLiteral(toolTip) + "');\" onmouseout=\"DisplayTooltip('');\"";
В приведенном выше коде "#VALY" и "#VALX" являются ключевыми словами. Во время выполнения эти ключевые слова заменяются фактическими значениями. В моем сценарии #VALY - это двойное число, а #VALX - это дата и время.
Заметим:
Теперь это прекрасно работает, если я использую свойство всплывающей подсказки ряда данных. К сожалению, FireFox и Opera (легко) не поддерживают многострочные подсказки. Я пытаюсь запретить эту функцию из них с помощью пользовательских подсказок.
Таким образом, у меня есть код onmouseover и onmouseout - это javascript, который отвечает за подсказку.
Проблема в том, что при оценке #VALX он содержит недопустимые символы javascript. Это вызывает сообщение об ошибке "Uncaught SyntaxError: Неожиданный токен ILLEGAL"
Обратите внимание, что я обернул всплывающую подсказку методом JavaScriptStringLiteral. Вот полезная функция:
private static readonly Regex scriptTagRegex = new Regex("script", RegexOptions.IgnoreCase | RegexOptions.Multiline);
/// <summary>
/// Processes the provided string, creating a quoted JavaScript string literal.
/// </summary>
/// <param name="str">The string to process</param>
/// <returns>A string containing a quoted JavaScript string literal</returns>
public static string JavaScriptStringLiteral(string str)
{
var sb = new StringBuilder();
sb.Append("\"");
foreach (char c in str)
{
switch (c)
{
case '\"':
sb.Append("\\\"");
break;
case '\\':
sb.Append("\\\\");
break;
case '\b':
sb.Append("\\b");
break;
case '\f':
sb.Append("\\f");
break;
case '\n':
sb.Append("\\n");
break;
case '\r':
sb.Append("\\r");
break;
case '\t':
sb.Append("\\t");
break;
default:
int i = (int)c;
if (i < 32 || i > 127)
{
sb.AppendFormat("\\u{0:X04}", i);
}
else
{
sb.Append(c);
}
break;
}
}
sb.Append("\"");
// If a Javascript tag contains "</script>", then it terminates a
// script block. Start by replacing each 's'/'S' with an escape
// sequence so it doesn't trigger this.
return scriptTagRegex.Replace(
sb.ToString(),
m => (m.Value[0] == 's' ? "\\u0073" : "\\u0053") + m.Value.Substring(1));
}
Если бы #VALX не оценивался во время выполнения, я полагаю, что этот служебный метод решит мою проблему. Но, как таковая, служебная функция заменяет "#VALX" как строковый литерал. Затем, после фильтрации недопустимых символов, #VALX оценивается и помещает недопустимые символы в мой javascript.
Есть ли способ предотвратить эту проблему? Что-то эквивалентное символу "@" для путей в C#?
РЕДАКТИРОВАТЬ: Я выяснил, решение, и он тупой.
foreach (HistoricalDataValue value in data)
{
series.Points.AddXY(string.Format("{0:d}{1}{0:T}", value.TimeStamp, "\\n"), value.AttributeValue);
}
Обратите внимание, что это говорит "\\n". Раньше говорили Environment.NewLine, но это не работает. Кроме того, если вы используете Environment.NewLine -OR- "\n", вы не сможете редактировать "#VALX" позже из-за оценки во время выполнения. Таким образом, вы должны использовать экранированный символ новой строки при добавлении значения X, так что когда #VALX его получает, оно уже правильно отформатировано.
Спасибо
2 ответа
Когда вы звоните JavaScriptStringLiteral
Ваш код уже открыл строку в одинарных кавычках, а эта функция возвращает строку, уже заключенную в двойные кавычки.
Вы должны раздеть первый и последний символ от того, что JavaScriptStringLiteral
возвращается.
Почему бы не использовать Microsoft.Security.Application.JavaScriptEncode(string input)
функция в библиотеке AntiXss