JDK-4395902 : Font.createFont() causes SecurityException in JApplet
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 1.3.0,1.4.0
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic,windows_nt
  • CPU: generic,x86
  • Submitted: 2000-12-07
  • Updated: 2001-06-08
  • Resolved: 2001-06-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4.0 beta2Fixed
Related Reports
Duplicate :  
Relates :  
Description

Name: boT120536			Date: 12/07/2000


java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

Font.createFont(int fontFormat, InputStream fontStream) causes a security
exception when called from within an applet.

Stack trace indicates that the implemention of createFont attempts to write the
retrieved font file to the local drive (SecurityException).  Seems that the font
needs to be cached in memory only.

//============================================
Example Code:

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.applet.*;
import javax.swing.JApplet;
import java.net.URL;
import java.io.*;

public class AppletWindow extends JApplet
{
    public void start()
    {
        try
        {
            URL fontURL = new URL("http://www.XXXXXX.com/Burmese.ttf");
            InputStream fontStream = fontURL.openStream();
            Font tempFont = Font.createFont(Font.TRUETYPE_FONT, fontStream);
            fontStream.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    public void stop(){}
    public void init(){}
    public void destroy(){}
}

//============================================
Plug-in Exception:

Java(TM) Plug-in: Version 1.3.0-C
Using JRE version 1.3.0 Java HotSpot(TM) Client VM
Proxy Configuration: no proxy

JAR cache disabled.
java.lang.SecurityException: Unable to create temporary file
	at java.io.File.checkAndCreate(File.java:1156)
	at java.io.File.createTempFile(File.java:1244)
	at java.awt.Font.createFont(Font.java:398)
	at AppletWindow.start(AppletWindow.java:19)
	at sun.applet.AppletPanel.run(AppletPanel.java:358)
	at java.lang.Thread.run(Thread.java:484)
(Review ID: 112326) 
======================================================================

Name: yyT116575			Date: 01/05/2001


C:\JBuilder4\jdk1.3\bin>.\java -version
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)


The following web page:

http://java.sun.com/j2se/1.3/docs/guide/2d/new_features.html#DF

Describes how to load dynamic fonts from a URL

Dynamic font loading
The new method Font.createFont(int, InputStream) provides the ability to add
fonts to the JavaTM 2 Virtual Machine* (JVM) at runtime. This font is not
persistent upon termination of the JVM and is only available to the creator of
the Font. At this time, only TrueTypeTM fonts can be created at runtime.
The following code sample illustrates how to dynamically load the TrueType font
Arial from a file:


	File file = new File("Arial.ttf");
	FileInputStream fis = new FileInputStream(file);
	Font font = Font.createFont(Font.TRUETYPE_FONT, fis);
	
Similarly, to load the font from a URL:
	URL url = new URL("Arial.ttf");
	InputStream is = url.openStream();
	Font font = Font.createFont(Font.TRUETYPE_FONT, is);
	
When I use the sample for loading a font from a URL I get the following error:

java.lang.SecurityException: Unable to create temporary file
	at java.io.File.checkAndCreate(Unknown Source)
	at java.io.File.createTempFile(Unknown Source)
	at java.awt.Font.createFont(Unknown Source)
	at JinYoTimPiano.JinYoTimPiano.init(JinYoTimPiano.java:75)
	at sun.applet.AppletPanel.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)

Is it trying to create a temporary file on my system?
(Review ID: 114612)
======================================================================

Name: yyT116575			Date: 01/16/2001


java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

Put the applet and html file shown bellow and any True Type font to the web
server directory, run the applet using html file shown bellow (it uses
JavaPlugin 1.3), push the button "Download TTF file..." and enter URL to the
True Type font file in your webserver. After you push OK button, exception
message "java.lang.SecurityException: Unable to create temporary file" is shown
in text area.

Applet:

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;

public class TTFRendererApplet extends JApplet implements ActionListener {
    private final String DEMO_TEXT = "The quick brown fox jumps over the lazy
dog. 1234567890";
    private final Font DEFAULT_FONT = new TextArea().getFont();
    
    private boolean bold = false;
    private boolean italic = false;
    
    private AbstractButton openButton;
    private AbstractButton boldButton;
    private AbstractButton italicButton;
    private AbstractButton sizeButton;
    private JTextField inputField;
    
    private JTextArea textArea;
    
    public TTFRendererApplet() {
        
        textArea = new JTextArea();
        textArea.setText(DEMO_TEXT);
        
        JScrollPane scrollPane = new JScrollPane(textArea);
        
        openButton = new JButton("Download TTF file...");
        openButton.addActionListener(this);

        boldButton = new JCheckBox("Bold");
        boldButton.addActionListener(this);

        italicButton = new JCheckBox("Italic");
        italicButton.addActionListener(this);
        
        inputField = new JTextField(6);
        
        sizeButton = new JButton("Change Size");
        sizeButton.addActionListener(this);

        JPanel buttonPanel = new JPanel();
        buttonPanel.add(openButton);
        buttonPanel.add(boldButton);
        buttonPanel.add(italicButton);
        buttonPanel.add(inputField);
        buttonPanel.add(sizeButton);

        Container contentPane = getContentPane();
        contentPane.add(scrollPane, BorderLayout.CENTER);
        contentPane.add(buttonPanel, BorderLayout.SOUTH);
    }
    
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == openButton) {
            textArea.setText("Loading font...");
            
            String urlStr = JOptionPane.showInputDialog(this, "Enter URL to TTF file:");
            URL url;
            try {
                url = new URL(urlStr);
            } catch (MalformedURLException ex) {
                textArea.setFont(DEFAULT_FONT);
                textArea.setText(ex.toString());
                return;
            }
                
            Font font = null;
            
            try {
                // This is where exception is thrown:

                font = Font.createFont(Font.TRUETYPE_FONT, url.openStream());
            } catch (FontFormatException ex) {
                textArea.setFont(DEFAULT_FONT);
                textArea.setText(ex.toString());
                return;
            } catch (IOException ex) {
                textArea.setFont(DEFAULT_FONT);
                textArea.setText(ex.toString());
                return;
            } catch (Exception ex) {
                textArea.setFont(DEFAULT_FONT);
                textArea.setText(ex.toString());
                return;
            }
            
            font = font.deriveFont(12.0f);
            
            textArea.setFont(font);
            
            textArea.setText(DEMO_TEXT);
        } else if (e.getSource() == boldButton || e.getSource() == italicButton) {
            if (e.getSource() == boldButton) {
                bold = !bold;
            } else if (e.getSource() == italicButton) {
                italic = !italic;
            }
        
            Font font = textArea.getFont();
            int style = Font.PLAIN;
            
            if (bold) {
                style |= Font.BOLD;
            }
            if (italic) {
                style |= Font.ITALIC;
            }
            
            font = font.deriveFont(style);
            textArea.setFont(font);
        } else if (e.getSource() == sizeButton) {
            String sizeStr = inputField.getText();
            float size = 12.0f;
            try {
                size = Float.valueOf(sizeStr).floatValue();
            } catch (NumberFormatException ex) {
                textArea.setFont(DEFAULT_FONT);
                textArea.setText(ex.toString());
                return;
            }
            
            Font font = textArea.getFont();
            font = font.deriveFont(size);
            textArea.setFont(font);
        }
    }

}


HTML file:

<html>
<head>
</head>
<body>

<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
    width="400" height="400"
    codebase="http://java.sun.com/products/plugin/1.3/jinstall-13-
win32.cab#Version=1,3,0,0">
    <PARAM NAME="code" VALUE="TTFRendererApplet.class">
        No Java 2 SDK, Standard Edition v 1.3 support for APPLET!!
</OBJECT>

</body>
</html>
(Review ID: 106637)
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: merlin-beta2 FIXED IN: merlin-beta2 INTEGRATED IN: merlin-beta2
14-06-2004

WORK AROUND Name: boT120536 Date: 12/07/2000 Have your browser grant the applet local disk writing access. ======================================================================
11-06-2004

EVALUATION A temp file is created on the disk since the font can be very large. We should state in the javadoc that this might happen. jeannette.hung@Eng 2000-12-07 It was pointed out that we should also do a doPrivileged() to create this temp file. jeannette.hung@Eng 2000-12-07 Fix: Added doPrivileged in all access to the temporary file. jennifer.godinez@Eng 2001-05-31 ===============================
07-12-2000