mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
Candidate release of source code.
This commit is contained in:
parent
db81e6b3b0
commit
79d8f164f8
12449 changed files with 2800756 additions and 16 deletions
|
@ -0,0 +1,269 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package generic.jar;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
public class ClassModuleTree {
|
||||
private FileNode root = new FileNode(null, "");
|
||||
|
||||
public ClassModuleTree() {
|
||||
|
||||
}
|
||||
|
||||
public ClassModuleTree(ResourceFile treeFile) throws IOException {
|
||||
|
||||
try (BufferedReader reader =
|
||||
new BufferedReader(new InputStreamReader(treeFile.getInputStream()))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
String[] split = line.split(" ");
|
||||
String path = split[0];
|
||||
String module = split[1].equals("null") ? null : split[1];
|
||||
addNode(path, module);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addNode(String path, String moduleName) {
|
||||
String[] split = path.split("/");
|
||||
FileNode file = root;
|
||||
for (String string : split) {
|
||||
file = file.createNode(string);
|
||||
}
|
||||
file.setModule(moduleName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj.getClass() != this.getClass()) {
|
||||
return false;
|
||||
}
|
||||
ClassModuleTree other = (ClassModuleTree) obj;
|
||||
return root.equals(other.root);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return root.hashCode();
|
||||
}
|
||||
|
||||
public void trim() {
|
||||
root.trim();
|
||||
}
|
||||
|
||||
public void printRecursively() {
|
||||
printRecursively(root);
|
||||
}
|
||||
|
||||
public void saveFile(File outputFile) throws IOException {
|
||||
try (FileWriter writer = new FileWriter(outputFile)) {
|
||||
List<FileNode> children = root.getChildren();
|
||||
for (FileNode child : children) {
|
||||
writeRecursively(writer, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeRecursively(FileWriter writer, FileNode node) throws IOException {
|
||||
writer.write(node.getPath());
|
||||
writer.write(" ");
|
||||
writer.write(node.module == null ? "null" : node.module);
|
||||
writer.write("\n");
|
||||
List<FileNode> children = node.getChildren();
|
||||
for (FileNode child : children) {
|
||||
writeRecursively(writer, child);
|
||||
}
|
||||
}
|
||||
|
||||
private void printRecursively(FileNode node) {
|
||||
System.out.println(node.getPath() + " : " + node.module);
|
||||
List<FileNode> children = node.getChildren();
|
||||
for (FileNode child : children) {
|
||||
printRecursively(child);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getNodeCount() {
|
||||
return root.getCount();
|
||||
}
|
||||
|
||||
static class FileNode implements Comparable<FileNode> {
|
||||
private FileNode parent;
|
||||
private Map<String, FileNode> children;
|
||||
private String module;
|
||||
private String name;
|
||||
|
||||
public FileNode(FileNode parent, String name) {
|
||||
this.parent = parent;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
int count = 1;
|
||||
if (children != null) {
|
||||
List<FileNode> childList = getChildren();
|
||||
for (FileNode child : childList) {
|
||||
count += child.getCount();
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public String trim() {
|
||||
if (module != null) {
|
||||
return module;
|
||||
}
|
||||
if (children == null) {
|
||||
return null;
|
||||
}
|
||||
Set<String> set = new HashSet<String>();
|
||||
for (FileNode node : children.values()) {
|
||||
set.add(node.trim());
|
||||
}
|
||||
if (set.size() == 1) {
|
||||
module = set.iterator().next();
|
||||
if (module != null) {
|
||||
children = null; // trim the children
|
||||
}
|
||||
}
|
||||
return module;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((children == null) ? 0 : children.hashCode());
|
||||
result = prime * result + ((module == null) ? 0 : module.hashCode());
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
FileNode other = (FileNode) obj;
|
||||
if (children == null) {
|
||||
if (other.children != null)
|
||||
return false;
|
||||
}
|
||||
else if (!children.equals(other.children))
|
||||
return false;
|
||||
if (module == null) {
|
||||
if (other.module != null)
|
||||
return false;
|
||||
}
|
||||
else if (!module.equals(other.module))
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
}
|
||||
else if (!name.equals(other.name))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setModule(String moduleName) {
|
||||
this.module = moduleName;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
if (parent == null) {
|
||||
return "";
|
||||
}
|
||||
String parentPath = parent.getPath();
|
||||
if (parentPath.length() == 0) {
|
||||
return name;
|
||||
}
|
||||
return parentPath + "/" + name;
|
||||
}
|
||||
|
||||
public FileNode createNode(String nodeName) {
|
||||
if (children == null) {
|
||||
children = new HashMap<String, ClassModuleTree.FileNode>();
|
||||
}
|
||||
FileNode child = children.get(nodeName);
|
||||
if (child == null) {
|
||||
child = new FileNode(this, nodeName);
|
||||
children.put(nodeName, child);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
public List<FileNode> getChildren() {
|
||||
if (children == null) {
|
||||
return new ArrayList<FileNode>();
|
||||
}
|
||||
return new ArrayList<FileNode>(children.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(FileNode o) {
|
||||
return name.compareTo(o.name);
|
||||
}
|
||||
|
||||
public FileNode getChild(String childName) {
|
||||
if (children == null) {
|
||||
return null;
|
||||
}
|
||||
return children.get(childName);
|
||||
}
|
||||
}
|
||||
|
||||
public String getModuleName(String className) {
|
||||
String[] split = className.split("/");
|
||||
FileNode node = root;
|
||||
for (String name : split) {
|
||||
node = node.getChild(name);
|
||||
if (node == null) {
|
||||
return null;
|
||||
}
|
||||
if (node.module != null) {
|
||||
return node.module;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
ClassModuleTree tree = new ClassModuleTree();
|
||||
tree.addNode("a/b/c", "module1");
|
||||
tree.addNode("a/b/d", "module1");
|
||||
tree.addNode("a/b/e", "module1");
|
||||
|
||||
tree.addNode("a/x/a", "module2");
|
||||
tree.addNode("a/x/b", "module3");
|
||||
|
||||
tree.printRecursively();
|
||||
System.out.println("------");
|
||||
tree.trim();
|
||||
tree.printRecursively();
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package generic.jar;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
//
|
||||
public class FileResource implements Resource {
|
||||
private File file;
|
||||
|
||||
public FileResource(File file) {
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource getResource(String childPath) {
|
||||
return new FileResource(new File(file, childPath));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAbsolutePath() {
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceFile[] listFiles() {
|
||||
File[] listFiles = file.listFiles();
|
||||
|
||||
if (listFiles == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ResourceFile[] resourceFiles = new ResourceFile[listFiles.length];
|
||||
for (int i = 0; i < listFiles.length; i++) {
|
||||
resourceFiles[i] = new ResourceFile(new FileResource(listFiles[i]));
|
||||
}
|
||||
return resourceFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceFile[] listFiles(ResourceFileFilter filter) {
|
||||
File[] listFiles = file.listFiles();
|
||||
if (listFiles == null) {
|
||||
return null;
|
||||
}
|
||||
List<ResourceFile> fileList = new ArrayList<>();
|
||||
for (File listFile : listFiles) {
|
||||
ResourceFile resourceFile = new ResourceFile(new FileResource(listFile));
|
||||
if (filter.accept(resourceFile)) {
|
||||
fileList.add(resourceFile);
|
||||
}
|
||||
}
|
||||
return fileList.toArray(new ResourceFile[fileList.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return file.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory() {
|
||||
return file.isDirectory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL toURL() throws MalformedURLException {
|
||||
return file.toURI().toURL();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws FileNotFoundException {
|
||||
return new FileInputStream(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStream() throws FileNotFoundException {
|
||||
return new FileOutputStream(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileResource getParent() {
|
||||
File parent = file.getParentFile();
|
||||
if (parent == null) {
|
||||
parent = file.getAbsoluteFile().getParentFile();
|
||||
if (parent == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return new FileResource(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long lastModified() {
|
||||
return file.lastModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return file.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
return file.equals(((FileResource) obj).file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete() {
|
||||
return file.delete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getResourceAsFile(ResourceFile resourceFile) {
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long length() {
|
||||
return file.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCanonicalPath() throws IOException {
|
||||
return file.getCanonicalPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFile() {
|
||||
return file.isFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource getCanonicalResource() {
|
||||
try {
|
||||
return new FileResource(file.getCanonicalFile());
|
||||
}
|
||||
catch (IOException e) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite() {
|
||||
return file.canWrite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mkdir() {
|
||||
return file.mkdir();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getFileSystemRoot() {
|
||||
File testFile = file;
|
||||
File parentFile = testFile.getParentFile();
|
||||
while (parentFile != null) {
|
||||
testFile = parentFile;
|
||||
parentFile = testFile.getParentFile();
|
||||
}
|
||||
return testFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI toURI() {
|
||||
return file.toURI();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package generic.jar;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
||||
public class GClassLoader extends URLClassLoader {
|
||||
|
||||
public GClassLoader(List<File> moduleDirs) {
|
||||
super(findUrls(moduleDirs), ClassLoader.getSystemClassLoader());
|
||||
}
|
||||
|
||||
private static URL[] findUrls(List<File> moduleDirs) {
|
||||
List<URL> urls = new ArrayList<URL>();
|
||||
|
||||
for (File moduleDir : moduleDirs) {
|
||||
File binDir = new File(moduleDir, "bin/");
|
||||
if (binDir.exists()) {
|
||||
addFileURL(urls, binDir);
|
||||
}
|
||||
addModuleJars(urls, new File(moduleDir, "lib"));
|
||||
}
|
||||
|
||||
return urls.toArray(new URL[urls.size()]);
|
||||
}
|
||||
|
||||
private static void addFileURL(List<URL> urls, File binDir) {
|
||||
try {
|
||||
urls.add(binDir.toURI().toURL());
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
throw new AssertException("Can't happen since we checked that it exists.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void addModuleJars(List<URL> urls, File libDir) {
|
||||
if (!libDir.isDirectory()) {
|
||||
return;
|
||||
}
|
||||
File[] listFiles = libDir.listFiles();
|
||||
if (listFiles != null) {
|
||||
for (File jarFile : listFiles) {
|
||||
if (isJarFile(jarFile)) {
|
||||
addFileURL(urls, jarFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isJarFile(File jarFile) {
|
||||
return jarFile.exists() && jarFile.getName().endsWith(".jar");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package generic.jar;
|
||||
|
||||
import java.util.jar.JarEntry;
|
||||
|
||||
public interface JarEntryFilter {
|
||||
|
||||
boolean accepts(JarEntry jarEntry);
|
||||
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package generic.jar;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public class JarEntryNode {
|
||||
private final JarEntryNode parent;
|
||||
private final String name;
|
||||
private Map<String, JarEntryNode> childMap;
|
||||
|
||||
JarEntryNode(JarEntryNode parent, String name) {
|
||||
this.name = name;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public JarEntryNode getNode(String childName) {
|
||||
if (childMap == null) {
|
||||
return null;
|
||||
}
|
||||
if (childName.equals(".")) {
|
||||
return this;
|
||||
}
|
||||
if (childName.equals("..")) {
|
||||
return parent;
|
||||
}
|
||||
return childMap.get(childName);
|
||||
}
|
||||
|
||||
JarEntryNode createNode(String childName) {
|
||||
JarEntryNode file = getNode(childName);
|
||||
if (file == null) {
|
||||
file = new JarEntryNode(this, childName);
|
||||
if (childMap == null) {
|
||||
childMap = new HashMap<String, JarEntryNode>();
|
||||
}
|
||||
childMap.put(childName, file);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
String getPath() {
|
||||
if (parent == null) {
|
||||
return "";
|
||||
}
|
||||
String parentPath = parent.getPath();
|
||||
return parentPath.length() == 0 ? name : parentPath + "/" + name;
|
||||
}
|
||||
|
||||
public List<JarEntryNode> getChildren() {
|
||||
if (childMap == null) {
|
||||
return null;
|
||||
}
|
||||
return new ArrayList<JarEntryNode>(childMap.values());
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isDirectory() {
|
||||
return childMap != null;
|
||||
}
|
||||
|
||||
public boolean isFile() {
|
||||
return childMap == null;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException {
|
||||
JarFile jarFile = getJarFile();
|
||||
JarEntry jarEntry = jarFile.getJarEntry(getPath());
|
||||
return jarFile.getInputStream(jarEntry);
|
||||
}
|
||||
|
||||
protected JarFile getJarFile() {
|
||||
return parent.getJarFile();
|
||||
}
|
||||
|
||||
public JarEntryNode getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public long lastModified() {
|
||||
JarFile jarFile = getJarFile();
|
||||
JarEntry jarEntry = jarFile.getJarEntry(getPath());
|
||||
return jarEntry.getTime();
|
||||
}
|
||||
|
||||
public JarEntryNode getNode(String[] path) {
|
||||
JarEntryNode temp = this;
|
||||
for (String childName : path) {
|
||||
temp = temp.getNode(childName);
|
||||
if (temp == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
public long length() {
|
||||
JarFile jarFile = getJarFile();
|
||||
JarEntry jarEntry = jarFile.getJarEntry(getPath());
|
||||
return jarEntry.getSize();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package generic.jar;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public class JarEntryRootNode extends JarEntryNode {
|
||||
private JarFile jarFile;
|
||||
private File file;
|
||||
|
||||
public JarEntryRootNode(File file, JarEntryFilter filter) throws IOException {
|
||||
super(null, "");
|
||||
jarFile = new JarFile(file);
|
||||
this.file = file;
|
||||
if (filter == null) {
|
||||
filter = new DefaultFilter();
|
||||
}
|
||||
createIndex(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JarFile getJarFile() {
|
||||
return jarFile;
|
||||
}
|
||||
|
||||
protected File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public URL toURL() throws MalformedURLException {
|
||||
return file.toURI().toURL();
|
||||
}
|
||||
|
||||
private void createIndex(JarEntryFilter filter) {
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry jarEntry = entries.nextElement();
|
||||
if (jarEntry.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
if (filter.accepts(jarEntry)) {
|
||||
addFile(jarEntry.getName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void addFile(String path) {
|
||||
String[] split = path.split("/");
|
||||
JarEntryNode node = this;
|
||||
for (String string : split) {
|
||||
node = getOrCreateNode(node, string);
|
||||
}
|
||||
}
|
||||
|
||||
private JarEntryNode getOrCreateNode(JarEntryNode node, String name) {
|
||||
return node.createNode(name); // if already exists, create will return exiting node
|
||||
}
|
||||
|
||||
private static class DefaultFilter implements JarEntryFilter {
|
||||
|
||||
@Override
|
||||
public boolean accepts(JarEntry jarEntry) {
|
||||
String name = jarEntry.getName();
|
||||
if (name.endsWith(".class")) {
|
||||
return false;
|
||||
}
|
||||
if (name.endsWith(".png")) {
|
||||
return false;
|
||||
}
|
||||
if (name.endsWith(".gif")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,300 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package generic.jar;
|
||||
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import utilities.util.FileUtilities;
|
||||
import utility.application.ApplicationSettings;
|
||||
|
||||
public class JarResource implements Resource {
|
||||
private final JarEntryRootNode root;
|
||||
private final JarEntryNode node;
|
||||
private final String name;
|
||||
private final String path;
|
||||
|
||||
public JarResource(File jarFile, JarEntryFilter filter) throws IOException {
|
||||
root = new JarEntryRootNode(jarFile, filter);
|
||||
node = root;
|
||||
name = root.getName();
|
||||
path = root.getPath();
|
||||
}
|
||||
|
||||
public JarResource(JarResource parent, String path) {
|
||||
this.root = parent.root;
|
||||
String myName;
|
||||
JarEntryNode myNode;
|
||||
String myPath;
|
||||
path = path.replace('\\', '/');
|
||||
if (path.startsWith("/")) {
|
||||
path = path.substring(1);
|
||||
}
|
||||
if (path.length() == 0) {
|
||||
myName = parent.getName();
|
||||
myNode = parent.node;
|
||||
myPath = parent.path;
|
||||
}
|
||||
else {
|
||||
String[] split = path.split("/");
|
||||
myName = split[split.length - 1];
|
||||
myNode = parent.node == null ? null : parent.node.getNode(split);
|
||||
myPath = myNode != null ? myNode.getPath() : parent.path + "/" + path;
|
||||
}
|
||||
this.name = myName;
|
||||
this.node = myNode;
|
||||
this.path = myPath;
|
||||
}
|
||||
|
||||
JarResource(JarEntryRootNode root, JarEntryNode node) {
|
||||
this.root = root;
|
||||
this.node = node;
|
||||
this.name = node.getName();
|
||||
this.path = node.getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAbsolutePath() {
|
||||
String jarPath;
|
||||
try {
|
||||
jarPath = root.toURL().toExternalForm();
|
||||
}
|
||||
catch (IOException e) {
|
||||
jarPath = "file:" + root.getFile().getAbsolutePath();
|
||||
}
|
||||
return "jar:" + jarPath + "!/" + path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL toURL() throws MalformedURLException {
|
||||
return new URL(getAbsolutePath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI toURI() {
|
||||
try {
|
||||
return new URI(getAbsolutePath());
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
throw new AssertException("Unexpected exception getting URI: " + this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceFile[] listFiles() {
|
||||
if (!isDirectory()) {
|
||||
return null;
|
||||
}
|
||||
List<JarEntryNode> children = node.getChildren();
|
||||
ResourceFile[] files = new ResourceFile[children.size()];
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
files[i] = new ResourceFile(new JarResource(root, children.get(i)));
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceFile[] listFiles(ResourceFileFilter filter) {
|
||||
if (!isDirectory()) {
|
||||
return null;
|
||||
}
|
||||
List<ResourceFile> fileList = new ArrayList<ResourceFile>();
|
||||
List<JarEntryNode> children = node.getChildren();
|
||||
for (JarEntryNode jarEntryNode : children) {
|
||||
ResourceFile file = new ResourceFile(new JarResource(root, jarEntryNode));
|
||||
if (filter.accept(file)) {
|
||||
fileList.add(file);
|
||||
}
|
||||
}
|
||||
return fileList.toArray(new ResourceFile[fileList.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory() {
|
||||
return node == null ? false : node.isDirectory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFile() {
|
||||
return node == null ? false : node.isFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
if (node == null || isDirectory()) {
|
||||
throw new FileNotFoundException(path + " does not exist or is a directory");
|
||||
}
|
||||
return node.getInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource getParent() {
|
||||
if (node != null) {
|
||||
if (node == root) {
|
||||
return null;
|
||||
}
|
||||
return new JarResource(root, node.getParent());
|
||||
}
|
||||
JarResource rootResource = new JarResource(root, root);
|
||||
String parentPath = getParentPath();
|
||||
if (parentPath == null) {
|
||||
return rootResource;
|
||||
}
|
||||
return new JarResource(rootResource, parentPath);
|
||||
}
|
||||
|
||||
private String getParentPath() {
|
||||
String[] split = path.split("/");
|
||||
if (split.length == 1) {
|
||||
return null;
|
||||
}
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(split[0]);
|
||||
for (int i = 1; i < split.length; i++) {
|
||||
buf.append("/");
|
||||
buf.append(split[i]);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long lastModified() {
|
||||
if (node != null) {
|
||||
return node.lastModified();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return node != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStream() throws FileNotFoundException {
|
||||
throw new FileNotFoundException("Cannot write to a file inside of a jar file!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource getResource(String childPath) {
|
||||
if (childPath == null || childPath.length() == 0) {
|
||||
return this;
|
||||
}
|
||||
return new JarResource(this, childPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getFile() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getResourceAsFile(ResourceFile resourceFile) {
|
||||
File userCopyDir = getFileCacheDirectory();
|
||||
if (!userCopyDir.exists()) {
|
||||
FileUtilities.mkdirs(userCopyDir);
|
||||
}
|
||||
|
||||
File fileCopy = new File(userCopyDir, name);
|
||||
if (!fileCopy.exists()) {
|
||||
try {
|
||||
FileUtilities.copyFile(resourceFile, fileCopy, false, null);
|
||||
fileCopy.setExecutable(true);
|
||||
}
|
||||
catch (IOException e) {
|
||||
Msg.error(this, "Resource file copy failed: " + resourceFile, e);
|
||||
}
|
||||
}
|
||||
return fileCopy;
|
||||
}
|
||||
|
||||
private File getFileCacheDirectory() {
|
||||
|
||||
File settingsDir = ApplicationSettings.getUserApplicationSettingsDirectory();
|
||||
return new File(settingsDir, "jar.resource.copied.files");
|
||||
}
|
||||
|
||||
@Override
|
||||
public long length() {
|
||||
return node.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCanonicalPath() throws IOException {
|
||||
return getAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource getCanonicalResource() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mkdir() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
JarResource other = (JarResource) obj;
|
||||
return root == other.root && name.equals(other.name) && path.equals(other.path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return path.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getFileSystemRoot() {
|
||||
return root.getFile();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package generic.jar;
|
||||
|
||||
import java.io.*;
|
||||
//
|
||||
import java.net.*;
|
||||
|
||||
public interface Resource {
|
||||
|
||||
Resource getResource(String name);
|
||||
|
||||
String getAbsolutePath();
|
||||
|
||||
ResourceFile[] listFiles();
|
||||
|
||||
ResourceFile[] listFiles(ResourceFileFilter filter);
|
||||
|
||||
String getName();
|
||||
|
||||
boolean isDirectory();
|
||||
|
||||
Resource getParent();
|
||||
|
||||
URL toURL() throws MalformedURLException;
|
||||
|
||||
long lastModified();
|
||||
|
||||
InputStream getInputStream() throws FileNotFoundException, IOException;
|
||||
|
||||
boolean delete();
|
||||
|
||||
boolean exists();
|
||||
|
||||
OutputStream getOutputStream() throws FileNotFoundException;
|
||||
|
||||
File getFile();
|
||||
|
||||
long length();
|
||||
|
||||
String getCanonicalPath() throws IOException;
|
||||
|
||||
boolean isFile();
|
||||
|
||||
Resource getCanonicalResource();
|
||||
|
||||
boolean canWrite();
|
||||
|
||||
boolean mkdir();
|
||||
|
||||
File getFileSystemRoot();
|
||||
|
||||
URI toURI();
|
||||
|
||||
File getResourceAsFile(ResourceFile resourceFile);
|
||||
|
||||
}
|
|
@ -0,0 +1,332 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package generic.jar;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Class for representing file object regardless of whether they are actual files in the file system or
|
||||
* or files stored inside of a jar file. This class provides most all the same capabilities as the
|
||||
* File class.
|
||||
*
|
||||
*/
|
||||
|
||||
public class ResourceFile implements Comparable<ResourceFile> {
|
||||
private static final String JAR_FILE_PREFIX = "jar:file:";
|
||||
private Resource resource;
|
||||
private static Map<String, JarResource> jarRootsMap = new HashMap<String, JarResource>();
|
||||
|
||||
/**
|
||||
* Construct a ResourceFile that represents a normal file in the file system.
|
||||
* @param file the file in the file system.
|
||||
*/
|
||||
public ResourceFile(File file) {
|
||||
resource = new FileResource(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new ResourceFile from a parent file and a relative child path.
|
||||
* @param resourceFile the parent file
|
||||
* @param path the child path.
|
||||
*/
|
||||
public ResourceFile(ResourceFile resourceFile, String path) {
|
||||
if (resourceFile == null) {
|
||||
throw new IllegalArgumentException("Parent ResourceFile cannot be null.");
|
||||
}
|
||||
|
||||
resource = resourceFile.resource.getResource(path);
|
||||
}
|
||||
|
||||
ResourceFile(Resource resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a Resource file from string path that can be either a file path or a jar url.
|
||||
* @param absolutePath the path to the file.
|
||||
*/
|
||||
public ResourceFile(String absolutePath) {
|
||||
this(absolutePath, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a Resource file from string path that can be either a file path or a jar url.
|
||||
*
|
||||
* @param absolutePath the path to the file.
|
||||
* @param filter The filter used to exclude files from being loaded
|
||||
*/
|
||||
public ResourceFile(String absolutePath, JarEntryFilter filter) {
|
||||
if (absolutePath.startsWith(JAR_FILE_PREFIX)) {
|
||||
int indexOf = absolutePath.indexOf("!/");
|
||||
if (indexOf < 0) {
|
||||
throw new IllegalArgumentException("Invalid jar specification: " + absolutePath);
|
||||
}
|
||||
String filePath = absolutePath.substring(JAR_FILE_PREFIX.length(), indexOf);
|
||||
String relativePath = absolutePath.substring(indexOf + 2);
|
||||
Resource root = jarRootsMap.get(filePath);
|
||||
try {
|
||||
if (root == null) {
|
||||
root = openJarResourceFile(new File(filePath), filter).resource;
|
||||
}
|
||||
resource = root.getResource(relativePath);
|
||||
return;
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalArgumentException("Failed to open jar: " + filePath, e);
|
||||
}
|
||||
}
|
||||
resource = new FileResource(new File(absolutePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Root ResourceFile for a given jar file.
|
||||
* @param jarFile the jar file to open.
|
||||
* @param filter JarEntryFilter that will filter out unwanted jar entries.
|
||||
* @return A Resource file that represents the root of the jarfile file system.
|
||||
* @throws IOException if the jar file can't be read.
|
||||
*/
|
||||
public static ResourceFile openJarResourceFile(File jarFile, JarEntryFilter filter)
|
||||
throws IOException {
|
||||
|
||||
JarResource root = new JarResource(jarFile, filter);
|
||||
ResourceFile rootResourceFile = new ResourceFile(root);
|
||||
jarRootsMap.put(jarFile.getCanonicalPath(), root);
|
||||
return rootResourceFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute file path for this file.
|
||||
* @return the absolute file path for this file.
|
||||
*/
|
||||
public String getAbsolutePath() {
|
||||
return resource.getAbsolutePath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the canonical file path for this file.
|
||||
* @return the absolute file path for this file.
|
||||
*/
|
||||
public String getCanonicalPath() throws IOException {
|
||||
return resource.getCanonicalPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a array of ResourceFiles if this ResourceFile is a directory. Otherwise return null.
|
||||
* @return the child ResourceFiles if this is a directory, null otherwise.
|
||||
*/
|
||||
public ResourceFile[] listFiles() {
|
||||
return resource.listFiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a array of ResourceFiles if this ResourceFile is a directory. Otherwise return null.
|
||||
* @param filter a filter to restrict the array of files returned.
|
||||
* @return the child ResourceFiles if this is a directory, null otherwise.
|
||||
*/
|
||||
public ResourceFile[] listFiles(ResourceFileFilter filter) {
|
||||
return resource.listFiles(filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the simple name of the file.
|
||||
* @return the simple name of the file.
|
||||
*/
|
||||
public String getName() {
|
||||
return resource.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this Resource file exists and is a directory.
|
||||
* @return true if this Resource file exists and is a directory.
|
||||
*/
|
||||
public boolean isDirectory() {
|
||||
return resource.isDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent of this ResourceFile or null if it is a root.
|
||||
* @return the parent of this ResourceFile or null if it is a root.
|
||||
*/
|
||||
public ResourceFile getParentFile() {
|
||||
Resource parent = resource.getParent();
|
||||
return parent == null ? null : new ResourceFile(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a URL that represents this file object.
|
||||
* @return a URL that represents this file object.
|
||||
* @throws MalformedURLException if a URL can't be formed for this file.
|
||||
*/
|
||||
public URL toURL() throws MalformedURLException {
|
||||
return resource.toURL();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time that this file was last modified.
|
||||
* @return the time that this file was last modified.
|
||||
*/
|
||||
public long lastModified() {
|
||||
return resource.lastModified();
|
||||
}
|
||||
|
||||
/**
|
||||
* If this file exists and is not a directory, it will return an InputStream for the file's
|
||||
* contents.
|
||||
* @return an InputStream for the file's contents.
|
||||
* @throws FileNotFoundException if the file does not exist.
|
||||
* @throws IOException
|
||||
*/
|
||||
public InputStream getInputStream() throws FileNotFoundException, IOException {
|
||||
return resource.getInputStream();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to delete the file. Not supported (returns false) for files within a jar file.
|
||||
* @return true if the file was deleted, false otherwise.
|
||||
*/
|
||||
public boolean delete() {
|
||||
return resource.delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the file exists.
|
||||
* @return true if the file exists.
|
||||
*/
|
||||
public boolean exists() {
|
||||
return resource.exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an OutputStream if the file can be opened for writing.
|
||||
* @return an OutputStream if the file can be opened for writing.
|
||||
* @throws FileNotFoundException if the file can't be created or opened for writing.
|
||||
*/
|
||||
public OutputStream getOutputStream() throws FileNotFoundException {
|
||||
return resource.getOutputStream();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a File object. If this ResourceFile represents a standard filesystem, then no
|
||||
* copy is necessary to return a file. If this ResourceFile represents a compressed
|
||||
* filesystem, then a copy from that filesystem to the real filesystem is needed to create
|
||||
* a File object. <tt>copyIfNeeded</tt> allows you to dictate whether a copy should take
|
||||
* place, if needed.
|
||||
* <p>
|
||||
* If you just want the contents of a file, then call {@link #getInputStream()}.
|
||||
*
|
||||
* @param copyIfNeeded true to copy the file when embedded in a compressed filesystem; false
|
||||
* to return null in that case.
|
||||
* @return a File object or null if not a file and copyIfNeeded was false
|
||||
*/
|
||||
public File getFile(boolean copyIfNeeded) {
|
||||
if (copyIfNeeded) {
|
||||
return resource.getResourceAsFile(this);
|
||||
}
|
||||
return resource.getFile(); // will be null if the resource is a compressed filesystem
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of this file.
|
||||
* @return the size of the file.
|
||||
*/
|
||||
public long length() {
|
||||
return resource.length();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this file exists and is not a directory.
|
||||
* @return true if this file exists and is not a directory.
|
||||
*/
|
||||
public boolean isFile() {
|
||||
return resource.isFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the canonicalFile for this file.
|
||||
* @return the canonicalFile for this file.
|
||||
*/
|
||||
public ResourceFile getCanonicalFile() {
|
||||
Resource newResource = resource.getCanonicalResource();
|
||||
if (resource == newResource) {
|
||||
return this;
|
||||
}
|
||||
return new ResourceFile(newResource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this file can be written to.
|
||||
* @return true if this file can be written to.
|
||||
*/
|
||||
public boolean canWrite() {
|
||||
return resource.canWrite();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a directory for the path represented by this file.
|
||||
* @return true if a new directory was created.
|
||||
*/
|
||||
public boolean mkdir() {
|
||||
return resource.mkdir();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
return resource.equals(((ResourceFile) obj).resource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return resource.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ResourceFile o) {
|
||||
return getAbsolutePath().compareTo(o.getAbsolutePath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getAbsolutePath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root file for this file.
|
||||
* @return the root file for this file.
|
||||
*/
|
||||
public File getFileSystemRoot() {
|
||||
return resource.getFileSystemRoot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a URI for this file object.
|
||||
* @return a URI for this file object.
|
||||
*/
|
||||
public URI toURI() {
|
||||
return resource.toURI();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package generic.jar;
|
||||
|
||||
public interface ResourceFileFilter {
|
||||
public boolean accept(ResourceFile file);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue