2008-11-12

Writing files from JavaScript

In Internet Explorer, you can use the ActiveXObject "microsoft.xmldom" to load an XML file into a DOM that can be inspected and manipulated from JavaScript. So far so good. But what if you want to write an XML file to the local file system? XmlDom has a save() method and the argument lets you specify a local file path. But in IE6 and later, the attempt will always fail.

The 'net is full of forum posts with frantic pleas for help with titles like "XML DOM save - File Permission denied". In almost all cases, the answers fell into the following categories:

"Tough luck, that's the way it is" / "the cookie crumbles."

True enough, but not helpful.

"You need to have write permission on the folder you're writing to!"

True enough, but I'll bet everyone with half a brain checked that before posting. Even if that was the problem, you'd run up against the previous one.

"I have the same problem. Please email me the answer!"

Me too!

"You can't do that from HTML, you need a HTA

True enough, but if the requester could get a user to download and execute an application he wouldn't have this problem in the first place.

"In ASP on the server you do this..."

That doesn't help with saving files on the client's file system.



It was a long time before I came across a post that mentioned FileSystemObject. It turns out that while xmldom.save() is never allowed to write to the local file system (apparently no amount of tweaking any permissions will change that), FileSystemObject can create, read, write and even delete files, subject to permissions given in IE's Internet Options.

It's no big deal to pull the XML from the DOM as a String and to save it using a TextStream object created by FileSystemObject.CreateTextFile(). Here's a code sample of mine that does it:


function save2()
{
var xmlDoc = new ActiveXObject("microsoft.xmldom");
xmlDoc.load(path + "stuff.xml");
alert("stuff.xml loaded");
fso = new ActiveXObject("Scripting.FileSystemObject");
f2 = fso.CreateTextFile(path + "stuff2.xml", true);
f2.write(xmlDoc.xml);
f2.Close();
alert("stuff2.xml saved");
}


I surmise that more readers of those forums knew the "right" answer but chose not to tell because they suspected malicious intent on part of the requesters. When you can write to the user's file system you can do many evil things.

My take on this is: Any user surfing the Web with IE and permissions set to "trusting" is asking for trouble anyway; and the more professional malware authors already know how to exploit this. Microsoft's choice to never allow XmlDom to save looks silly in view of the fact that there's a perfectly workable back door.

My own use of this feature is legitimate, of course: I'm working with a JavaScript application that wants to store some user settings on the user's machine. More information than will fit into a cookie, and there's no server to persist the information on. Also, it's a closed environment, even to the user, with no Internet connection, so it can safely run with full permissions.

No comments: