Hi

I attach a testcase for the bug.
It's a simple application that open a window and writes de data droppped
from a file-manager.
With nautilus it works ok, but if you drop files from pcmanfm it throws
a exception at the console.

I also attach a patch to openjdk, to ignore lines with only "null"
character, and a isolated test of the fail point.


the function called to parse the "drop data":

List<File>  fileList = (List<File>)
tr.getTransferData(DataFlavor.javaFileListFlavor);


Then, after some work, it goes to sun.awt.X11.XDataTransferer  line ~287

        while ((line = reader.readLine()) != null) {
                try {
                    uri = new URI(line); //  <-- fails here 
                } catch (URISyntaxException uriSyntaxException) {
                    throw new IOException(uriSyntaxException);  
                }
                uriList.add(uri);
            }

and fails because it tries to make a URI from '\0', 


I've send the patch upstream, but their bug tracking system it's not
public by default. I'll update this bug when I've notice.
import java.awt.BorderLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.TooManyListenersException;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;



public class FileDropTestCase extends JFrame implements DropTargetListener {
	private static final long serialVersionUID = 1L;
	private JTextArea text = null;

	public static void main(String[] args) throws TooManyListenersException {
		JFrame frame = new FileDropTestCase();
		frame.setVisible(true);
	}

	public FileDropTestCase() throws TooManyListenersException {
		super(FileDropTestCase.class.getName());
		text = new JTextArea();
		this.getContentPane().add(new JScrollPane(text), BorderLayout.CENTER);

		this.setBounds(100, 100, 300, 400);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setUpDnd();
		this.setVisible(true);

	}

	private void setUpDnd() throws TooManyListenersException {
		final java.awt.dnd.DropTarget dt = new java.awt.dnd.DropTarget();
		dt.addDropTargetListener(this);
		new java.awt.dnd.DropTarget(text, this);
	}

	@Override
	public void dragEnter(DropTargetDragEvent dtde) {}

	@Override
	public void dragOver(DropTargetDragEvent dtde) {}

	@Override
	public void dropActionChanged(DropTargetDragEvent dtde) {}

	@Override
	public void dragExit(DropTargetEvent dte) {}

	@Override
	public void drop(DropTargetDropEvent evt) {
		java.awt.datatransfer.Transferable tr = evt.getTransferable();
		if (tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {

			evt.acceptDrop(java.awt.dnd.DnDConstants.ACTION_COPY);

			try {
				// This call fails dropping files from pcmanfm.
				// it works fine with nautilus, and windows explorer.
				// other environment not tested
				List<File>  fileList = (List<File>) tr.getTransferData(DataFlavor.javaFileListFlavor);
				
				for (File file : fileList) {
					text.append(file.getCanonicalPath() + "\n");
				}
			} catch (UnsupportedFlavorException e1) {
				e1.printStackTrace();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			// Mark that drop is completed.
			evt.getDropTargetContext().dropComplete(true);
		}

	}

}
import java.io.*;
import java.net.*;
import java.util.ArrayList;


public class Test {


	public static void main(String[] args) throws IOException {
		
		/*
		 *  Real data from a debug session:
		 *  
		 *  file:///tmp/demo1.txt\nfile:///tmp/demo2.txt\n\0
		 */
		
		byte[] bytes = {
				102, 105, 108, 101, 58, 47, 47, 47, 116, 109, 112, 47, 100, 101, 109, 111, 49, 46, 116, 120, 116, 13, 
				10, 
				102, 105, 108, 101, 58, 47, 47, 47, 116, 109, 112, 47, 100, 101, 109, 111, 50, 46, 116, 120, 116, 13, 10,
				0
		};
		URI[] list = simpleTestCaseFixed(
				new ByteArrayInputStream(bytes),
				bytes,
				"UTF-8"
		);
		
		for (URI uri : list) {
			System.out.println(uri);
		}

	}
	
	/*
	 * This function correspond with a fragment of sun.awt.X11.XDataTransferer.dragQueryURIs (~256)
	 * It's modified to ignore lines containing only a string with null terminator char.
	 * 
	 */
	private static URI[] simpleTestCaseFixed(InputStream stream, byte[] bytes, String charset) throws IOException {
		BufferedReader reader = null;

			reader = new BufferedReader(new InputStreamReader(stream, charset));
			String line;
			ArrayList<URI> uriList = new ArrayList<URI>();
			while ((line = reader.readLine()) != null) {
				
				try {
					// Only take on care of not "empty" lines
					if (!"\0".equals(line)){
						uriList.add(new URI(line));
					}
				} catch (URISyntaxException uriSyntaxException) {
					throw new IOException(uriSyntaxException);
				}
				
			}
			return uriList.toArray(new URI[uriList.size()]);
	}
	
	
	/*
	 * This function is a verbatim copy of fragment of sun.awt.X11.XDataTransferer.dragQueryURIs (~256)
	 */
	private static URI[] simpleTestCase(InputStream stream, byte[] bytes, String charset) throws IOException {
		BufferedReader reader = null;

			reader = new BufferedReader(new InputStreamReader(stream, charset));
			String line;
			ArrayList<URI> uriList = new ArrayList<URI>();
			URI uri;
			while ((line = reader.readLine()) != null) {
				try {
					uri = new URI(line);// <- fails here if line == "\0"
				} catch (URISyntaxException uriSyntaxException) {
					throw new IOException(uriSyntaxException);
				}
				uriList.add(uri);
			}
			return uriList.toArray(new URI[uriList.size()]);
	}
}
diff -uNr openjdk-orig/jdk/src/solaris/classes/sun/awt/X11/XDataTransferer.java openjdk/jdk/src/solaris/classes/sun/awt/X11/XDataTransferer.java
--- openjdk-orig/jdk/src/solaris/classes/sun/awt/X11/XDataTransferer.java	2012-10-16 22:36:45.000000000 +0200
+++ openjdk/jdk/src/solaris/classes/sun/awt/X11/XDataTransferer.java	2012-12-15 12:14:59.281673529 +0100
@@ -283,14 +283,14 @@
             reader = new BufferedReader(new InputStreamReader(stream, charset));
             String line;
             ArrayList<URI> uriList = new ArrayList<URI>();
-            URI uri;
             while ((line = reader.readLine()) != null) {
                 try {
-                    uri = new URI(line);
+                    if (!"\0".equals(line)) {
+                        uriList.add(new URI(line));
+                    }
                 } catch (URISyntaxException uriSyntaxException) {
                     throw new IOException(uriSyntaxException);
                 }
-                uriList.add(uri);
             }
             return uriList.toArray(new URI[uriList.size()]);
         } finally {

Reply via email to