Unverified Commit c0b2230b authored by skylot's avatar skylot Committed by GitHub

Merge pull request #299 from skylot/public_xml_impl

Generates and saves public.xml in apktool style
parents dda49f15 53fa8205
package jadx.core.utils.files;
import java.io.File;
import java.io.IOException;
import java.util.zip.ZipEntry;
import org.slf4j.Logger;
......@@ -14,14 +15,25 @@ public class ZipSecurity {
private ZipSecurity() {}
private static boolean isInSubDirectory(File base, File file) {
if (file == null) {
private static boolean isInSubDirectoryInternal(File baseDir, File canonFile) {
if (canonFile == null) {
return false;
}
if (file.equals(base)) {
if (canonFile.equals(baseDir)) {
return true;
}
return isInSubDirectory(base, file.getParentFile());
return isInSubDirectoryInternal(baseDir, canonFile.getParentFile());
}
public static boolean isInSubDirectory(File baseDir, File file) {
try {
file = file.getCanonicalFile();
baseDir = baseDir.getCanonicalFile();
}
catch(IOException e) {
return false;
}
return isInSubDirectoryInternal(baseDir, file);
}
// checks that entry name contains no any traversals
......@@ -30,7 +42,7 @@ public class ZipSecurity {
try {
File currentPath = new File(".").getCanonicalFile();
File canonical = new File(currentPath, entryName).getCanonicalFile();
if (isInSubDirectory(currentPath, canonical)) {
if (isInSubDirectoryInternal(currentPath, canonical)) {
return true;
}
LOG.error("Path traversal attack detected, invalid name: {}", entryName);
......
......@@ -65,7 +65,7 @@ public class ResTableParser extends CommonBinaryParser {
ResXmlGen resGen = new ResXmlGen(resStorage, vp);
ResContainer res = ResContainer.multiFile("res");
res.setContent(makeDump());
res.setContent(makeXmlDump());
res.getSubFiles().addAll(resGen.makeResourcesXml());
return res;
}
......@@ -82,6 +82,23 @@ public class ResTableParser extends CommonBinaryParser {
writer.finish();
return writer;
}
public CodeWriter makeXmlDump() {
CodeWriter writer = new CodeWriter();
writer.startLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
writer.startLine("<resources>");
writer.incIndent();
for (ResourceEntry ri : resStorage.getResources()) {
String format = String.format("<public type=\"%s\" name=\"%s\" id=\"%s\" />",
ri.getTypeName(), ri.getKeyName(), ri.getId());
writer.startLine(format);
}
writer.decIndent();
writer.startLine("</resources>");
writer.finish();
return writer;
}
public ResourceStorage getResStorage() {
return resStorage;
......
......@@ -13,6 +13,7 @@ import org.slf4j.LoggerFactory;
import jadx.api.ResourceFile;
import jadx.api.ResourceType;
import jadx.core.codegen.CodeWriter;
import jadx.core.utils.files.ZipSecurity;
import static jadx.core.utils.files.FileUtils.prepareFile;
......@@ -46,6 +47,7 @@ public class ResourcesSaver implements Runnable {
if (subFiles.isEmpty()) {
save(rc, outDir);
} else {
saveToFile(rc, new File(outDir, "res/values/public.xml"));
for (ResContainer subFile : subFiles) {
saveResources(subFile);
}
......@@ -59,12 +61,29 @@ public class ResourcesSaver implements Runnable {
String ext = FilenameUtils.getExtension(outFile.getName());
try {
outFile = prepareFile(outFile);
if(!ZipSecurity.isInSubDirectory(outDir, outFile)) {
LOG.error("Path traversal attack detected, invalid resource name: {}",
outFile.getPath());
return;
}
ImageIO.write(image, ext, outFile);
} catch (IOException e) {
LOG.error("Failed to save image: {}", rc.getName(), e);
}
return;
}
if(!ZipSecurity.isInSubDirectory(outDir, outFile)) {
LOG.error("Path traversal attack detected, invalid resource name: {}",
rc.getFileName());
return;
}
saveToFile(rc, outFile);
}
private void saveToFile(ResContainer rc, File outFile) {
CodeWriter cw = rc.getContent();
if (cw != null) {
cw.save(outFile);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment