package org.eclipse.osgi.storage.bundlefile;
import java.io.File;
import java.io.IOException;
import java.util.*;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.util.NLS;
public class DirBundleFile extends BundleFile {
private static final String POINTER_SAME_DIRECTORY_1 = "/.";
private static final String POINTER_SAME_DIRECTORY_2 = "//";
private static final String POINTER_UPPER_DIRECTORY = "..";
private final boolean enableStrictBundleEntryPath;
public DirBundleFile(File basefile, boolean enableStrictBundleEntryPath) throws IOException {
super(getBaseFile(basefile, enableStrictBundleEntryPath));
if (!BundleFile.secureAction.exists(basefile) || !BundleFile.secureAction.isDirectory(basefile)) {
throw new IOException(NLS.bind(Msg.ADAPTOR_DIRECTORY_EXCEPTION, basefile));
}
this.enableStrictBundleEntryPath = enableStrictBundleEntryPath;
}
private static File getBaseFile(File basefile, boolean enableStrictBundleEntryPath) throws IOException {
return enableStrictBundleEntryPath ? secureAction.getCanonicalFile(basefile) : basefile;
}
@Override
public File getFile(String path, boolean nativeCode) {
final boolean checkInBundle = path != null && path.indexOf(POINTER_UPPER_DIRECTORY) >= 0;
File file = new File(this.basefile, path);
if (!BundleFile.secureAction.exists(file)) {
return null;
}
if (!enableStrictBundleEntryPath) {
if (checkInBundle) {
try {
if (!BundleFile.secureAction.getCanonicalPath(file).startsWith(BundleFile.secureAction.getCanonicalPath(basefile)))
return null;
} catch (IOException e) {
return null;
}
}
return file;
}
boolean normalize = false;
boolean isBundleRoot = false;
if (path != null) {
isBundleRoot = path.equals("/");
if (!isBundleRoot) {
normalize = checkInBundle || path.indexOf(POINTER_SAME_DIRECTORY_1) >= 0 || path.indexOf(POINTER_SAME_DIRECTORY_2) >= 0;
}
}
File canonicalFile;
try {
canonicalFile = BundleFile.secureAction.getCanonicalFile(file);
if (!isBundleRoot) {
File absoluteFile = BundleFile.secureAction.getAbsoluteFile(file);
String canonicalPath;
String absolutePath;
if (normalize) {
canonicalPath = canonicalFile.toURI().getPath();
absolutePath = absoluteFile.toURI().normalize().getPath();
} else {
canonicalPath = canonicalFile.getPath();
absolutePath = absoluteFile.getPath();
}
if (!canonicalPath.equals(absolutePath)) {
return null;
}
}
if (checkInBundle) {
if (!canonicalFile.getPath().startsWith(basefile.getPath()))
return null;
}
} catch (IOException e) {
return null;
}
return file;
}
@Override
public BundleEntry getEntry(String path) {
File filePath = getFile(path, false);
if (filePath == null)
return null;
return new FileBundleEntry(filePath, path);
}
@Override
public boolean containsDir(String dir) {
File dirPath = getFile(dir, false);
return dirPath != null && BundleFile.secureAction.isDirectory(dirPath);
}
@Override
public Enumeration<String> getEntryPaths(String path, boolean recurse) {
if (path.length() > 0 && path.charAt(0) == '/')
path = path.substring(1);
File pathFile = getFile(path, false);
if (pathFile == null || !BundleFile.secureAction.isDirectory(pathFile))
return null;
String[] fileList = BundleFile.secureAction.list(pathFile);
if (fileList == null || fileList.length == 0)
return null;
String dirPath = path.length() == 0 || path.charAt(path.length() - 1) == '/' ? path : path + '/';
LinkedHashSet<String> entries = new LinkedHashSet<>();
for (String s : fileList) {
java.io.File childFile = new java.io.File(pathFile, s);
StringBuilder sb = new StringBuilder(dirPath).append(s);
if (BundleFile.secureAction.isDirectory(childFile)) {
sb.append("/");
if (recurse) {
Enumeration<String> e = getEntryPaths(sb.toString(), true);
if (e != null)
entries.addAll(Collections.list(e));
}
}
entries.add(sb.toString());
}
return Collections.enumeration(entries);
}
@Override
public void close() {
}
@Override
public void open() {
}
}