0

I have a Java applet for an intranet site which needs to access the file system on the client's PC (specifically a LAN share). This applet has a function similar to:

JSObject win;

public void init() {
    win=(JSObject) JSObject.getWindow(this);
    win.call("appletMsg", new Object[] {"<b>Applet Loaded</b>", "win"});
}

public void saveFile(String filepath, String filename) {
    File theDir = new File(filepath);
    try {
        if (theDir.exists()) { // This throws exception
            win.call("appletMsg", new Object[] {"Directory Exists", "win"});
        }
        else {
            win.call("appletMsg", new Object[] {"Creating Directory...", "msg"});
            if (theDir.mkdir()) {
                win.call("appletMsg", new Object[] {"Directory Created", "win"});
            }
            else win.call("appletMsg", new Object[] {"Directory Creation Failed!", "fail"});
        }
    }
    catch (Exception e) { // This exception is caught
        win.call("appletMsg", new Object[] {"Error Reading Directory!", "fail"});
        win.call("appletMsg", new Object[] {filepath, "fail"});
    }
    // More code for working with files, error happens above this
}

Javascript behind the applet

// call applet method
function save() {
    document.myApplet.saveFile('\\\\LOCATION\\DIR\\DIR\\', 'test.txt');
}

// output responses from applet to div
function appletMsg(response, type) {
    document.getElementById('output').innerHTML+='<br><span class='+type+'>'+response+'</span>';
}

Troubleshooting/Thoughts:

  • the applet worked before I made the JS call the Java method (arguments were in param lists, applet was fully reloaded when needed, file operations were in init() method, reverting to this works but is terrible practice)
  • the applet is signed with a self-cert
  • I put a JFileChooser in the init() method to make sure paths were right, moved it to the saveFile() method and the dialog does not show. It doesn't cause a JS error to show like it did with the .exists() call in Java, it does throw a FilePermission exception in a try/catch
  • since this works in init() and not in saveFile() I can only assume this is to prevent JavaScript itself from accessing the file system??
MaKR
  • 1,882
  • 2
  • 17
  • 29
  • Browsers will not allow you to access the file system if you are using an untrusted (ie. self-signed) cert. – Aurand Sep 11 '13 at 23:54
  • They do, just only in the init() method. There are 2 possible workarounds, doPrivilieged as Yann39 points out, or define a thread inside of init() that executes a callback. – MaKR Sep 12 '13 at 19:53

1 Answers1

2

To be able to call your applet functions from JavaScript, you have to use an access controller. See documentation.

So try :

public void saveFile(String filepath, String filename) {
    AccessController.doPrivileged(new PrivilegedAction() {
        public Object run() {
            File theDir = new File(filepath);
            try {
                if (theDir.exists()) { // This throws exception
                    win.call("appletMsg", new Object[] { "Directory Exists", "win" });
                } else {
                    win.call("appletMsg", new Object[] { "Creating Directory...", "msg" });
                    if (theDir.mkdir()) {
                        win.call("appletMsg", new Object[] { "Directory Created", "win" });
                    } else
                        win.call("appletMsg", new Object[] { "Directory Creation Failed!", "fail" });
                }
            } catch (Exception e) { // This exception is caught
                win.call("appletMsg", new Object[] { "Error Reading Directory!", "fail" });
                win.call("appletMsg", new Object[] { filepath, "fail" });
            }
            // More code for working with files, error happens above this
        }
    });
}

It works even using a self-signed certificate, you will simply get the security warning.

Always remember to make the privileged code section as small as possible.

Yann39
  • 14,285
  • 11
  • 56
  • 84
  • Thanks, got it working a different way though. init() starts a thread that listens for a boolean, on boolean change it runs a callback function, and since the thread was defined in init() it has the privileges to run. Fortunately this app is on an intranet site, because it's heavy on breaking permissions. Aside from file operations it's using a library to access TWAIN drivers through JNI. My whole function would have basically been doPrivileged. – MaKR Sep 12 '13 at 19:51
  • Glad you make it work. It appears than using a thread that listens for a boolean has the same effects than using `DoPrivileged`, you can refer to [this post](http://stackoverflow.com/questions/3632283/does-accesscontroller-doprivileged-give-javascript-threads-the-permissions-of-th). – Yann39 Sep 13 '13 at 07:01