6590857: Drag & Drop arbitrary file copy

Reviewed-by: uta
This commit is contained in:
Denis Fokin 2009-04-13 21:42:44 +04:00
parent 29e370d911
commit 8ac601577f

View file

@ -65,10 +65,13 @@ import java.lang.reflect.Modifier;
import java.rmi.MarshalledObject; import java.rmi.MarshalledObject;
import java.security.AccessControlContext;
import java.security.AccessControlException;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.security.PrivilegedActionException; import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -111,6 +114,8 @@ import javax.imageio.stream.ImageOutputStream;
import sun.awt.image.ImageRepresentation; import sun.awt.image.ImageRepresentation;
import sun.awt.image.ToolkitImage; import sun.awt.image.ToolkitImage;
import java.io.FilePermission;
/** /**
* Provides a set of functions to be shared among the DataFlavor class and * Provides a set of functions to be shared among the DataFlavor class and
@ -1177,8 +1182,10 @@ search:
(String.class.equals(flavor.getRepresentationClass()) && (String.class.equals(flavor.getRepresentationClass()) &&
isFlavorCharsetTextType(flavor) && isTextFormat(format))) { isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
String str = removeSuspectedData(flavor, contents, (String)obj);
return translateTransferableString( return translateTransferableString(
(String)obj, str,
format); format);
// Source data is a Reader. Convert to a String and recur. In the // Source data is a Reader. Convert to a String and recur. In the
@ -1286,6 +1293,11 @@ search:
throw new IOException("data translation failed"); throw new IOException("data translation failed");
} }
final List list = (List)obj; final List list = (List)obj;
final ArrayList fileList = new ArrayList();
final ProtectionDomain userProtectionDomain = getUserProtectionDomain(contents);
int nFiles = 0; int nFiles = 0;
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
Object o = list.get(i); Object o = list.get(i);
@ -1293,17 +1305,18 @@ search:
nFiles++; nFiles++;
} }
} }
final String[] files = new String[nFiles];
try { try {
AccessController.doPrivileged(new PrivilegedExceptionAction() { AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws IOException { public Object run() throws IOException {
for (int i = 0, j = 0; i < list.size(); i++) { for (Object fileObject : list)
Object o = list.get(i); {
if (o instanceof File) { File file = castToFile(fileObject);
files[j++] = ((File)o).getCanonicalPath(); if (null == System.getSecurityManager() ||
} else if (o instanceof String) { !(isFileInWebstartedCache(file) ||
files[j++] = (String)o; isForbiddenToRead(file, userProtectionDomain)))
{
fileList.add(file.getCanonicalPath());
} }
} }
return null; return null;
@ -1313,10 +1326,11 @@ search:
throw new IOException(pae.getMessage()); throw new IOException(pae.getMessage());
} }
for (int i = 0; i < files.length; i++) { for (int i = 0; i < fileList.size(); i++)
byte[] bytes = files[i].getBytes(); {
if (i != 0) bos.write(0); byte[] bytes = ((String)fileList.get(i)).getBytes();
bos.write(bytes, 0, bytes.length); if (i != 0) bos.write(0);
bos.write(bytes, 0, bytes.length);
} }
// Source data is an InputStream. For arbitrary flavors, just grab the // Source data is an InputStream. For arbitrary flavors, just grab the
@ -1366,6 +1380,123 @@ search:
return ret; return ret;
} }
private String removeSuspectedData(DataFlavor flavor, final Transferable contents, final String str)
throws IOException
{
if (null == System.getSecurityManager()
|| !flavor.isMimeTypeEqual("text/uri-list"))
{
return str;
}
String ret_val = "";
final ProtectionDomain userProtectionDomain = getUserProtectionDomain(contents);
try {
ret_val = (String) AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() {
StringBuffer allowedFiles = new StringBuffer(str.length());
String [] uriArray = str.split("(\\s)+");
for (String fileName : uriArray)
{
File file = new File(fileName);
if (file.exists() &&
!(isFileInWebstartedCache(file) ||
isForbiddenToRead(file, userProtectionDomain)))
{
if (0 != allowedFiles.length())
{
allowedFiles.append("\\r\\n");
}
allowedFiles.append(fileName);
}
}
return allowedFiles.toString();
}
});
} catch (PrivilegedActionException pae) {
throw new IOException(pae.getMessage(), pae);
}
return ret_val;
}
private static ProtectionDomain getUserProtectionDomain(Transferable contents) {
return contents.getClass().getProtectionDomain();
}
private boolean isForbiddenToRead (File file, ProtectionDomain protectionDomain)
{
if (null == protectionDomain) {
return false;
}
try {
FilePermission filePermission =
new FilePermission(file.getCanonicalPath(), "read, delete");
if (protectionDomain.implies(filePermission)) {
return false;
}
} catch (IOException e) {}
return true;
}
// It is important do not use user's successors
// of File class.
private File castToFile(Object fileObject) throws IOException {
String filePath = null;
if (fileObject instanceof File) {
filePath = ((File)fileObject).getCanonicalPath();
} else if (fileObject instanceof String) {
filePath = (String) fileObject;
}
return new File(filePath);
}
private final static String[] DEPLOYMENT_CACHE_PROPERTIES = {
"deployment.system.cachedir",
"deployment.user.cachedir",
"deployment.javaws.cachedir",
"deployment.javapi.cachedir"
};
private final static ArrayList <File> deploymentCacheDirectoryList =
new ArrayList<File>();
private static boolean isFileInWebstartedCache(File f) {
if (deploymentCacheDirectoryList.isEmpty()) {
for (String cacheDirectoryProperty : DEPLOYMENT_CACHE_PROPERTIES) {
String cacheDirectoryPath = System.getProperty(cacheDirectoryProperty);
if (cacheDirectoryPath != null) {
try {
File cacheDirectory = (new File(cacheDirectoryPath)).getCanonicalFile();
if (cacheDirectory != null) {
deploymentCacheDirectoryList.add(cacheDirectory);
}
} catch (IOException ioe) {}
}
}
}
for (File deploymentCacheDirectory : deploymentCacheDirectoryList) {
for (File dir = f; dir != null; dir = dir.getParentFile()) {
if (dir.equals(deploymentCacheDirectory)) {
return true;
}
}
}
return false;
}
public Object translateBytes(byte[] bytes, DataFlavor flavor, public Object translateBytes(byte[] bytes, DataFlavor flavor,
long format, Transferable localeTransferable) long format, Transferable localeTransferable)
throws IOException throws IOException