Fixed issue with loading messages in different language. As a standalone jar you can write properties back to messages.properties, this approach worked when you run with exploded classpath (target/classes etc). However failed when running inside Docker container.
This commit is contained in:
parent
d25700434e
commit
ae82df3fb4
@ -32,6 +32,7 @@ package org.owasp.webgoat;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.owasp.webgoat.i18n.Messages;
|
||||
import org.owasp.webgoat.i18n.PluginMessages;
|
||||
import org.owasp.webgoat.session.Course;
|
||||
import org.owasp.webgoat.session.LabelDebugger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -117,8 +118,13 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Messages messageSource() {
|
||||
Messages messages = new Messages(localeResolver());
|
||||
public PluginMessages pluginMessages(Messages messages) {
|
||||
return new PluginMessages(messages);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Messages messageSource(LocaleResolver localeResolver) {
|
||||
Messages messages = new Messages(localeResolver);
|
||||
messages.setBasename("classpath:/i18n/messages");
|
||||
return messages;
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.catalina.Context;
|
||||
import org.owasp.webgoat.i18n.PluginMessages;
|
||||
import org.owasp.webgoat.plugins.PluginClassLoader;
|
||||
import org.owasp.webgoat.plugins.PluginEndpointPublisher;
|
||||
import org.owasp.webgoat.plugins.PluginsExtractor;
|
||||
@ -91,8 +92,8 @@ public class WebGoat extends SpringBootServletInitializer {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PluginsExtractor pluginsLoader(@Qualifier("pluginTargetDirectory") File pluginTargetDirectory, PluginClassLoader classLoader) {
|
||||
return new PluginsExtractor(pluginTargetDirectory, classLoader);
|
||||
public PluginsExtractor pluginsLoader(@Qualifier("pluginTargetDirectory") File pluginTargetDirectory, PluginClassLoader classLoader, PluginMessages messages) {
|
||||
return new PluginsExtractor(pluginTargetDirectory, classLoader, messages);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -25,7 +25,7 @@
|
||||
package org.owasp.webgoat.assignments;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.owasp.webgoat.i18n.Messages;
|
||||
import org.owasp.webgoat.i18n.PluginMessages;
|
||||
import org.owasp.webgoat.session.UserSessionData;
|
||||
import org.owasp.webgoat.session.UserTracker;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
@ -50,7 +50,7 @@ public abstract class AssignmentEndpoint extends Endpoint {
|
||||
private UserSessionData userSessionData;
|
||||
@Getter
|
||||
@Autowired
|
||||
private Messages messages;
|
||||
private PluginMessages messages;
|
||||
|
||||
//// TODO: 11/13/2016 events better fit?
|
||||
protected AttackResult trackProgress(AttackResult attackResult) {
|
||||
|
@ -27,7 +27,7 @@ package org.owasp.webgoat.assignments;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.owasp.webgoat.i18n.Messages;
|
||||
import org.owasp.webgoat.i18n.PluginMessages;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class AttackResult {
|
||||
@ -35,13 +35,13 @@ public class AttackResult {
|
||||
public static class AttackResultBuilder {
|
||||
|
||||
private boolean lessonCompleted;
|
||||
private Messages messages;
|
||||
private PluginMessages messages;
|
||||
private Object[] feedbackArgs;
|
||||
private String feedbackResourceBundleKey;
|
||||
private String output;
|
||||
private Object[] outputArgs;
|
||||
|
||||
public AttackResultBuilder(Messages messages) {
|
||||
public AttackResultBuilder(PluginMessages messages) {
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ public class AttackResult {
|
||||
private String output;
|
||||
|
||||
|
||||
public static AttackResultBuilder builder(Messages messages) {
|
||||
public static AttackResultBuilder builder(PluginMessages messages) {
|
||||
return new AttackResultBuilder(messages);
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@ public class Messages extends ReloadableResourceBundleMessageSource {
|
||||
|
||||
/**
|
||||
* Gets all messages for presented Locale.
|
||||
*
|
||||
* @return all messages
|
||||
*/
|
||||
public Properties getMessages() {
|
||||
@ -64,4 +65,6 @@ public class Messages extends ReloadableResourceBundleMessageSource {
|
||||
return localeResolver.resolveLocale(((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
||||
* please see http://www.owasp.org/
|
||||
* <p>
|
||||
* Copyright (c) 2002 - 2017 Bruce Mayhew
|
||||
* <p>
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License along with this program; if
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
* <p>
|
||||
* Getting Source ==============
|
||||
* <p>
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
||||
* projects.
|
||||
* <p>
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.i18n;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Message resource bundle for plugins. The files is created after startup during the init of the plugins so we
|
||||
* need to load this file through a ResourceLoader instead of location on the classpath.
|
||||
*
|
||||
* @author nbaars
|
||||
* @date 2/4/17
|
||||
*/
|
||||
public class PluginMessages extends ReloadableResourceBundleMessageSource {
|
||||
|
||||
private Messages messages;
|
||||
|
||||
public PluginMessages(Messages messages) {
|
||||
this.messages = messages;
|
||||
this.setParentMessageSource(messages);
|
||||
}
|
||||
|
||||
public Properties getMessages() {
|
||||
return getMergedProperties(messages.resolveLocale()).getProperties();
|
||||
}
|
||||
|
||||
public String getMessage(String code, Object... args) {
|
||||
return getMessage(code, args, messages.resolveLocale());
|
||||
}
|
||||
|
||||
public String getMessage(String code, String defaultValue, Object... args) {
|
||||
return super.getMessage(code, args, defaultValue, messages.resolveLocale());
|
||||
}
|
||||
|
||||
public void addPluginMessageBundles(final File i18nPluginDirectory) {
|
||||
this.setBasename("WebGoatLabels");
|
||||
this.setResourceLoader(new ResourceLoader() {
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public Resource getResource(String location) {
|
||||
return new UrlResource(new File(i18nPluginDirectory, location).toURI());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getClassLoader() {
|
||||
return Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -24,49 +24,49 @@
|
||||
*/
|
||||
package org.owasp.webgoat.plugins;
|
||||
|
||||
import com.google.common.primitives.Bytes;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import static com.google.common.io.Files.createParentDirs;
|
||||
|
||||
/**
|
||||
* Merges the main message.properties with the plugins WebGoatLabels
|
||||
*/
|
||||
public class MessagePropertiesMerger {
|
||||
public class MessagePropertyMerger {
|
||||
|
||||
private final File targetDirectory;
|
||||
|
||||
public MessagePropertiesMerger(File targetDirectory) {
|
||||
public MessagePropertyMerger(File targetDirectory) {
|
||||
this.targetDirectory = targetDirectory;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public void mergeAllLanguage() {
|
||||
try(Stream<Path> paths = Files.walk(new File(targetDirectory, "plugin/i18n/").toPath())) {
|
||||
paths.filter(Files::isRegularFile).forEach(filePath -> merge(filePath));
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public void merge(Path propertyFile) {
|
||||
public void merge(ZipFile zipFile, ZipEntry zipEntry) {
|
||||
Properties messageProperties = new Properties();
|
||||
String messagePropertyFileName = propertyFile.getFileName().toString().replace("WebGoatLabels", "messages");
|
||||
messageProperties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("i18n/" + messagePropertyFileName));
|
||||
preparePropertyFile(propertyFile);
|
||||
messageProperties.load(new FileInputStream(propertyFile.toFile()));
|
||||
messageProperties.store(new FileOutputStream(new File(Thread.currentThread().getContextClassLoader().getResource("i18n/" + messagePropertyFileName).toURI())), "WebGoat message properties");
|
||||
try (InputStream zis = zipFile.getInputStream(zipEntry)) {
|
||||
messageProperties.load(zis);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private void preparePropertyFile(Path propertyFile) {
|
||||
byte[] lines = Files.readAllBytes(propertyFile);
|
||||
lines = Bytes.concat(lines, System.lineSeparator().getBytes());
|
||||
Files.write(propertyFile, lines);
|
||||
Properties messagesFromHome = new Properties();
|
||||
File pluginMessageFiles = new File(targetDirectory, zipEntry.getName());
|
||||
if (pluginMessageFiles.exists()) {
|
||||
try (FileInputStream fis = new FileInputStream(pluginMessageFiles)) {
|
||||
messagesFromHome.load(fis);
|
||||
}
|
||||
}
|
||||
|
||||
messageProperties.putAll(messagesFromHome);
|
||||
|
||||
createParentDirs(pluginMessageFiles);
|
||||
try (FileOutputStream fos = new FileOutputStream(pluginMessageFiles)) {
|
||||
messageProperties.store(fos, "Plugin message properties");
|
||||
}
|
||||
}
|
||||
}
|
@ -71,6 +71,9 @@ public class PluginExtractor {
|
||||
throws IOException {
|
||||
if (zipEntry.getName().endsWith(".properties")) {
|
||||
final File targetFile = new File(targetDirectory, zipEntry.getName());
|
||||
if ("WebGoatLabels.properties".equals(targetFile.getName())) {
|
||||
new MessagePropertyMerger(targetDirectory).merge(zipFile, zipEntry);
|
||||
}
|
||||
copyFile(zipFile, zipEntry, targetFile, true);
|
||||
return true;
|
||||
}
|
||||
@ -99,6 +102,7 @@ public class PluginExtractor {
|
||||
return targetFile;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Getter for the field <code>classes</code>.</p>
|
||||
*
|
||||
|
@ -3,6 +3,7 @@ package org.owasp.webgoat.plugins;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.owasp.webgoat.i18n.PluginMessages;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
|
||||
import java.io.*;
|
||||
@ -28,10 +29,12 @@ public class PluginsExtractor {
|
||||
private static final int BUFFER_SIZE = 32 * 1024;
|
||||
private final File pluginTargetDirectory;
|
||||
private final PluginClassLoader classLoader;
|
||||
private final PluginMessages messages;
|
||||
|
||||
public PluginsExtractor(File pluginTargetDirectory, PluginClassLoader pluginClassLoader) {
|
||||
public PluginsExtractor(File pluginTargetDirectory, PluginClassLoader pluginClassLoader, PluginMessages messages) {
|
||||
this.classLoader = pluginClassLoader;
|
||||
this.pluginTargetDirectory = pluginTargetDirectory;
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,7 +140,7 @@ public class PluginsExtractor {
|
||||
plugin.getOriginationJar());
|
||||
}
|
||||
}
|
||||
new MessagePropertiesMerger(pluginTargetDirectory).mergeAllLanguage();
|
||||
messages.addPluginMessageBundles(new File(pluginTargetDirectory, "plugin/i18n"));
|
||||
return plugins;
|
||||
} finally {
|
||||
executorService.shutdown();
|
||||
|
@ -31,6 +31,7 @@ package org.owasp.webgoat.service;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webgoat.i18n.Messages;
|
||||
import org.owasp.webgoat.i18n.PluginMessages;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@ -60,6 +61,7 @@ public class LabelService {
|
||||
public static final String URL_LABELS_MVC = "/service/labels.mvc";
|
||||
private LocaleResolver localeResolver;
|
||||
private Messages messages;
|
||||
private PluginMessages pluginMessages;
|
||||
|
||||
/**
|
||||
* We use Springs session locale resolver which also gives us the option to change the local later on. For
|
||||
@ -82,6 +84,9 @@ public class LabelService {
|
||||
((SessionLocaleResolver)localeResolver).setDefaultLocale(locale);
|
||||
log.debug("Language provided: {} leads to Locale: {}", lang, locale);
|
||||
}
|
||||
return new ResponseEntity<>(messages.getMessages(), HttpStatus.OK);
|
||||
Properties allProperties = new Properties();
|
||||
allProperties.putAll(messages.getMessages());
|
||||
allProperties.putAll(pluginMessages.getMessages());
|
||||
return new ResponseEntity<>(allProperties, HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +94,7 @@
|
||||
<!--<i class="fa fa-users"></i>-->
|
||||
<!--</button>-->
|
||||
</div>
|
||||
<button type="button" id="about-button" class="btn btn-default right_nav_button" title="#{about}"
|
||||
<button type="button" id="about-button" class="btn btn-default right_nav_button" th:title="#{about}"
|
||||
data-toggle="modal" data-target="#about-modal">
|
||||
<i class="fa fa-info"></i>
|
||||
</button>
|
||||
|
@ -27,6 +27,7 @@ package org.owasp.webgoat.assignments;
|
||||
|
||||
import org.mockito.Mock;
|
||||
import org.owasp.webgoat.i18n.Messages;
|
||||
import org.owasp.webgoat.i18n.PluginMessages;
|
||||
import org.owasp.webgoat.session.UserSessionData;
|
||||
import org.owasp.webgoat.session.UserTracker;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
@ -60,13 +61,14 @@ public class AssignmentEndpointTest {
|
||||
return Locale.ENGLISH;
|
||||
}
|
||||
};
|
||||
protected PluginMessages pluginMessages = new PluginMessages(messages);
|
||||
|
||||
public void init(AssignmentEndpoint a) {
|
||||
messages.setBasenames("classpath:/i18n/messages", "classpath:/plugin/i18n/WebGoatLabels");
|
||||
ReflectionTestUtils.setField(a, "userTracker", userTracker);
|
||||
ReflectionTestUtils.setField(a, "userSessionData", userSessionData);
|
||||
ReflectionTestUtils.setField(a, "webSession", webSession);
|
||||
ReflectionTestUtils.setField(a, "messages", messages);
|
||||
ReflectionTestUtils.setField(a, "messages", pluginMessages);
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user