2010-04-26 92 views
1

我正在编写一个实用程序,它接收.resx文件并创建一个JavaScript对象,其中包含.resx文件中所有名称/值对的属性。这一切都很好,直到.resx中的一个值为如何使用StreamWriter逐字写入转义字符(无需转义)?

此经销商接受电子订单。

/r/n点击订购该经销商的{0}。

我添加的名称/值对的JS对象是这样的:

streamWriter.Write(string.Format("\n{0} : \"{1}\"", kvp.Key, kvp.Value)); 

当kvp.Value =“该经销商接受电子orders./r/nClick从这个{0}订购经销商“。

这会导致StreamWriter.Write()实际在“订单”之间放置换行符。和'点击',这自然搞砸了我的JavaScript输出。

我已经尝试了不同的事情@和没有使用string.Format,但我没有运气。有什么建议么?

编辑:此应用程序在构建期间运行以获得稍后部署的一些javascript文件,因此除了应用程序开发人员之外,任何人都无法访问/运行此应用程序。所以,虽然我明显需要一种逃避角色的方式,但XSS本身并不是一个真正值得关注的问题。

回答

3

当你看到这段代码时,你的问题已经发生了。 String.Format不会将替换字符串({0}等)中的文字\n\r“扩展”为换行符和CR,因此它必定发生在某个更早的时间点,可能在读取.resx文件时发生。

您有两种可能的解决方案。一,当你在评论DonaldRay的答案发现,是明确地扭转这种替换,并用两个字符\n替换文字换行:

kvp.Value.Replace("\r",  // <-- replaced by the C# compiler with a literal CR character 
        "\\r"); // <-- "\\" replaced by the C# compiler with a single "\", 
          // leaving the two-char string "\r" 

您需要为可能出现在每一个字符做同样的你的琴弦。 \ n和\ r是最常见的,然后\ t(tab);这对大多数开发工具来说可能就足够了。

string formatted = kvp.Value.Replace("\r", "\\r") 
          .Replace("\n", "\\n") 
          .Replace("\t", "\\t"); 

或者,你可以看看上游的.resx文件读取代码,并设法找到并删除了明确扩大这些字符序列的部分。如果可能的话,这将是更好的通用解决方案。

+0

我按照现在的方式做了一个粗略的传递。我使用XmlDocument.LoadXml()读取.resx文件,然后使用一个ForEach(Node.SelectNodes(xpath string)),Node.ChildNodes [1] .InnerText。 看来,当我触摸Node.ChildNodes [1] .InnerText时,特殊字符已经被扩展。 假设从XmlDocument实现切换不值得花费精力,对此有何看法? – Joel 2010-04-26 20:36:15

1

只是逃避反斜杠。

kvp.Value = kvp.Value.Replace(@"\", @"\\");

您可能需要这样当您从RESX文件中读取。

+0

试过这个,它不工作的原因。 .Replace似乎并不想取代\。 – Joel 2010-04-26 19:48:34

+0

好的,这是交易。我结束了这个解决方案,但语法必须是kvp.Value = kvp.Value.Replace(“\ r”,@“\\ r”)。 我认为这是因为“\ r”和“\ n”是字符串中的唯一字符--C#不会将单个“\”识别为任何内容,它只是“\ n”或“\ r”字符的aprt 。 所以,更多的工作,但它似乎让我想去的地方。我可以对此进行更多的讨论/解释或链接,因为我觉得它突出了一些重要的字符串原则(我只是不知道它们是什么!) – Joel 2010-04-26 20:06:47

+0

不,这很有意义。 '\ r'是字符串中的单个字符。当你用@“\\ r”替换这个回车符时,你将放置两个反斜杠和一个r(因为@符号禁止转义字符)。当Streamwriter去写字符串时,它会看到“\\ r”。 “\\”被解释为'\',并且r正常打印。 – DonaldRay 2010-04-28 20:05:22