diff --git a/src/main/java/org/owasp/webgoat/plugins/Plugin.java b/src/main/java/org/owasp/webgoat/plugins/Plugin.java index 39c9e9774..86f16c05f 100644 --- a/src/main/java/org/owasp/webgoat/plugins/Plugin.java +++ b/src/main/java/org/owasp/webgoat/plugins/Plugin.java @@ -5,11 +5,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.file.Files; +import java.io.File; import java.nio.file.Path; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -18,6 +17,8 @@ public class Plugin { private static final Logger logger = LoggerFactory.getLogger(Plugin.class); private final Class lesson; private final Path pluginDirectory; + private final Map solutionLanguageFiles; + private final Map lessonPlansLanguageFiles; public static class PluginLoadingFailure extends RuntimeException { @@ -31,6 +32,8 @@ public class Plugin { private Path pluginDirectory; private Class lesson; private final List loadedClasses = new ArrayList(); + private final Map solutionLanguageFiles = new HashMap<>(); + private final Map lessonPlansLanguageFiles = new HashMap<>(); public Builder loadClasses(Map classes) { for (Map.Entry clazz : classes.entrySet() ) { @@ -43,7 +46,8 @@ public class Plugin { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); PluginClassLoader pluginClassLoader = new PluginClassLoader(contextClassLoader, classFile); try { - String realClassName = name.replace("/lesson_plans/", "").replaceAll("/", ".").replaceAll(".class", ""); + //TODO the plugin part is extra because the packaging is not correct in WEB-173 + String realClassName = name.replace("/lesson_plans/", "").replace("/plugin", "").replaceAll("/", ".").replaceAll(".class", ""); Class clazz = pluginClassLoader.loadClass(realClassName); if (AbstractLesson.class.isAssignableFrom(clazz)) { this.lesson = clazz; @@ -57,7 +61,6 @@ public class Plugin { public Builder setBaseDirectory(Path pluginDirectory) { this.pluginDirectory = pluginDirectory; - //Find necessary files flag if something went wrong plugin should complain return this; } @@ -66,32 +69,40 @@ public class Plugin { throw new PluginLoadingFailure(String.format("Lesson class not found, following classes were detected in the plugin: %s", StringUtils.collectionToCommaDelimitedString(loadedClasses))); } - return new Plugin(this.lesson, pluginDirectory); + return new Plugin(this.lesson, pluginDirectory, lessonPlansLanguageFiles, solutionLanguageFiles); } + public void loadFiles(List files) { + for (Path file : files) { + if (file.getFileName().endsWith(".html") && file.getParent().getParent().getFileName() + .endsWith("lessonSolutions")) { + solutionLanguageFiles.put(file.getParent().getFileName().toString(), file.toFile()); + } + if (file.getFileName().endsWith(".html") && file.getParent().getParent().getFileName() + .endsWith("lessonPlans")) { + lessonPlansLanguageFiles.put(file.getParent().getFileName().toString(), file.toFile()); + } + } + } } - public Plugin(Class lesson, Path pluginDirectory) { + public Plugin(Class lesson, Path pluginDirectory, Map lessonPlansLanguageFiles, + Map solutionLanguageFiles) { this.lesson = lesson; this.pluginDirectory = pluginDirectory; - } - - public String getLessonPlanHtml() { - Path lesson_plans = this.pluginDirectory.resolve("lesson_plans"); - try { - Files.readAllLines(lesson_plans.resolve(this.lesson.getSimpleName() + ".html"), Charset.defaultCharset()); - } catch (IOException e) { - logger.error("No html found in directory {}", lesson_plans.toString()); - } - return ""; + this.lessonPlansLanguageFiles = lessonPlansLanguageFiles; + this.solutionLanguageFiles = solutionLanguageFiles; } public Class getLesson() { return lesson; } - public String getLessonSolutionHtml() { - return null; - //return lessonSolutionHtml; + public Map getLessonSolutions() { + return this.solutionLanguageFiles; + } + + public Map getLessonPlans() { + return this.lessonPlansLanguageFiles; } } diff --git a/src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java b/src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java index 2cf8fdb9a..3aa861994 100644 --- a/src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java +++ b/src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java @@ -14,14 +14,15 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; /** - * Extract the wpf file and collect the classes to load and remember the base directory in which we extracted - * the files (lesson plans etc) + * Extract the wpf file and collect the classes to load and files(lesson plans etc) */ public class PluginExtractor { @@ -29,16 +30,21 @@ public class PluginExtractor { private final Path pluginArchive; private final Logger logger = LoggerFactory.getLogger(getClass()); private final Map classes = new HashMap(); + private final List files = new ArrayList<>(); private Path baseDirectory; public PluginExtractor(Path pluginArchive) { this.pluginArchive = pluginArchive; + try { + baseDirectory = createDirsIfNotExists(Paths.get(System.getProperty("java.io.tmpdir"), DIRECTORY)); + } catch (IOException io) { + logger.error(String.format("Unable to create base directory: {}", pluginArchive.getFileName()), io); + } } public void extract() { try (FileSystem zip = createZipFileSystem()) { final Path root = zip.getPath("/"); - baseDirectory = Paths.get(System.getProperty("java.io.tmpdir"), DIRECTORY); Files.walkFileTree(root, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { @@ -47,7 +53,7 @@ public class PluginExtractor { Files.copy(file, bos); classes.put(file.toString(), bos.toByteArray()); } - Files.copy(file, Paths.get(baseDirectory.toString(), file.toString()), REPLACE_EXISTING); + files.add(Files.copy(file, createDirsIfNotExists(Paths.get(baseDirectory.toString(), file.toString())), REPLACE_EXISTING)); return FileVisitResult.CONTINUE; } }); @@ -60,6 +66,10 @@ public class PluginExtractor { return this.classes; } + public List getFiles() { + return this.files; + } + public Path getBaseDirectory() { return this.baseDirectory; } @@ -69,15 +79,10 @@ public class PluginExtractor { return FileSystems.newFileSystem(uri, new HashMap()); } - private void closeZipFileSystem(FileSystem zip) { - if (zip != null) { - try { - zip.close(); - } catch (IOException e) { - //ignore - } + public Path createDirsIfNotExists(Path p) throws IOException { + if ( Files.notExists(p)) { + Files.createDirectories(p); } + return p; } - - } diff --git a/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java b/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java index c6d6b846b..dc0bb8315 100644 --- a/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java +++ b/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java @@ -33,6 +33,7 @@ public class PluginsLoader implements Runnable { extractor.extract(); Plugin.Builder builder = new Plugin.Builder(); builder.loadClasses(extractor.getClasses()); + builder.loadFiles(extractor.getFiles()); builder.setBaseDirectory(extractor.getBaseDirectory()); plugins.add(builder.build()); } catch (Plugin.PluginLoadingFailure e) { diff --git a/src/main/java/org/owasp/webgoat/session/Course.java b/src/main/java/org/owasp/webgoat/session/Course.java index 2f8813351..e75c9fdd1 100644 --- a/src/main/java/org/owasp/webgoat/session/Course.java +++ b/src/main/java/org/owasp/webgoat/session/Course.java @@ -17,6 +17,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -326,7 +327,9 @@ public class Course { if (lesson.getHidden() == false) { lessons.add(lesson); } - lesson.setLessonSolutionFileName(plugin.getLessonPlanHtml()); + for(Map.Entry lessonPlan : plugin.getLessonPlans().entrySet()) { + lesson.setLessonPlanFileName(lessonPlan.getKey(), lessonPlan.getValue().toString()); + } } catch (Exception e) { logger.error("Error in loadLessons: ", e); } diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties index 8ed0e8ef3..7dee72c2e 100644 --- a/src/main/resources/log4j.properties +++ b/src/main/resources/log4j.properties @@ -1,4 +1,4 @@ -log4j.rootLogger=DEBUG, MAIN_LOG +log4j.rootLogger=DEBUG, MAIN_LOG,CONSOLE #log4j.rootLogger=DEBUG, MAIN_LOG, ERROR_LOG # MAIN - everything gets logged here @@ -10,6 +10,12 @@ log4j.appender.MAIN_LOG.MaxFileSize=10MB log4j.appender.MAIN_LOG.MaxBackupIndex=5 log4j.appender.MAIN_LOG.append=true +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.Target=System.out +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.conversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p - %m%n + + # a little less spring output log4j.category.org.springframework = INFO