views:

263

answers:

3

I'm writing a utility that takes in a .resx file and creates a javascript object containing properties for all the name/value pairs in the .resx file. This is all well and good, until one of the values in the .resx is

This dealer accepts electronic orders.

/r/nClick to order {0} from this dealer.

I'm adding the name/value pairs to the js object like this:

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

When kvp.Value = "This dealer accepts electronic orders./r/nClick to order {0} from this dealer."

This causes StreamWriter.Write() to actually place a newline in between 'orders.' and 'Click', which naturally screws up my javascript output.

I've tried different things with @ and without using string.Format, but I've had no luck. Any suggestions?

Edit: This application is run during build to get some javascript files deployed later, so at no point is it accessible to / run by anyone but the app developers. So while I obviously need a way to escape characters here, XSS as such is not really a concern.

+1  A: 

You need to escape the strings, using Microsoft's Anti-XSS Library.

SLaks
+1  A: 

Just escape the backslashes.

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

You may need to do this when you are reading from the resx file.

DonaldRay
Tried this, and it's not working for some reason. .Replace doesn't seem to want to replace \.
Joel
Okay, here's the deal. I ended up going with this solution, but the syntax had to be kvp.Value = kvp.Value.Replace("\r", @"\\r").I assume this is because "\r" and "\n" are unique characters in the string - C# doesn't recognize the single "\" as anything, it's just aprt of "\n" or "\r" character.So, more work, but it seems to get me where I want to go. I'm open to more discussion / explanation on this, or links, as I feel it highlights some important string principles (I just don't know what they are!)
Joel
No, this makes a lot of sense. '\r' is a single character in the string. When you replace this carriage return with @"\\r" you are placing in two backslashes and an r (because the @ symbol suppresses escape characters). When the streamwriter goes to write the string, it sees "\\r". "\\" is interpreted as '\', and the r is printed as normal.
DonaldRay
+3  A: 

Your problem has already happened by the time you get to this code. String.Format will not "expand" literal \n and \r in the substituted strings ({0} etc) into newline and CR, so it must have happened at some earlier point, possibly while reading the .resx file.

You have two possible solutions. One, as you discovered in the comments to DonaldRay's answer, is to explicitly reverse this replacement, and replace literal newlines with the two characters \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"

You will need to do the same for every character that could appear in your strings. \n and \r are the most common, and then \t (tab); that's probably enough for most dev tools.

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

Alternatively, you could look upstream at the .resx file reading code, and try to find and remove the part that's explicitly expanding these character sequences. This would be a better general solution, if it's possible.

Andy Mortimer
I made a cursory pass at this before doing it the way I am now. I'm using XmlDocument.LoadXml() to read the .resx file, and then using doing a ForEach(Node in doc.SelectNodes(xpath string)), Node.ChildNodes[1].InnerText.It seems like, by the time I touch the Node.ChildNodes[1].InnerText, the special characters have already been expanded. Assuming it's not worth the effort to switch from the XmlDocument implementation, any ideas on this?
Joel