Local file writing by signed applets is blocked on Safari, due to a November 2013 Safari security change.
Steps to reproduce:
Expected behavior:
The expected behavior is what is seen on Windows and on Firefox on the Macintosh.
Actual behavior:
Regression:
This appeared at the same time as an inability to read local files, as demonstrated at "Local file reading by signed applets blocked by Safari" and the inability of a signed Java applet in Safari to launch new browser windows using Runtime.getRuntime().exec.
Workarounds:
Firefox is not affected, but the issue in Safari can be fixed as follows: Safari > Preferences > Security > Manage Website Settings… > Java > (your site) > Run in Unsafe Mode > Trust
import java.awt.*;
import java.applet.*;
import java.io.*;
import java.net.*;
import java.awt.event.*;
public class localFileWrite extends Applet implements ActionListener {
Button button;
boolean macOS;
boolean windowsOS;
String userHome;
URL rootOnClientURL;
String reportString;
public void init()
{
setBackground(new Color(255, 240, 200));
button = new Button("Write file"); // file creation doesn't work from init, so a button and actionPerformed are used
button.addActionListener(this);
add(button);
macOS = (System.getProperty("os.name").startsWith("Mac"));
windowsOS = (System.getProperty("os.name").startsWith("Win"));
userHome = System.getProperty("user.home");
try
{
if (macOS) rootOnClientURL = new URL("file", "", "//" + System.getProperty("user.home") + "/");
else if (windowsOS) rootOnClientURL = new URL("file:/" + userHome.replace('\\', '/') + "/AppData/LocalLow/");
}
catch (Exception e)
{
System.out.println("Couldn't form URL");
rootOnClientURL = null;
}
}
public void actionPerformed(ActionEvent ae)
{
if (ae.getSource() == button)
{
try
{
String fileString = new URL(rootOnClientURL + "localFile.txt").getFile();
fileString = getLocalFileForm(fileString);
FileOutputStream fos = new FileOutputStream(fileString);
BufferedOutputStream bos = new BufferedOutputStream(fos, 32768);
DataOutputStream dos = new DataOutputStream(bos);
dos.writeUTF("Test file contents");
dos.close();
bos.close();
fos.close();
reportString = "Writing a local file worked.";
}
catch (Exception e)
{
reportString = "Writing a local file didn't work. The Exception is: " + e.getMessage();
}
repaint();
}
}
final String getLocalFileForm(String string)
{
if (!macOS) while (string.startsWith("/")) string = string.substring(1);
string = string.replace ('/', File.separatorChar);
StringBuffer out = new StringBuffer(string.length());
for (int i=0; i<string.length(); i++)
{
char c = string.charAt(i);
if (c == '+') out.append(' '); // + is a space
else if (c == '%') // e.g. %20 is a space
{
int c1 = Character.digit(string.charAt(++i), 16);
int c2 = Character.digit(string.charAt(++i), 16);
out.append((char) (c1*16 + c2));
}
else out.append(c);
}
return (out.toString());
}
public void paint(Graphics g)
{
g.drawString("rootOnClientURL = " + rootOnClientURL, 10, 40);
g.drawString(reportString, 10, 70);
}
} // END OF Class localFileWrite
If you have any insights or comments about this page please contact Mickey Segal. A listing of many Java resources is at this link.