diff --git a/htroot/Blacklist_p.java b/htroot/Blacklist_p.java
index c2f3ef461..015906e5f 100644
--- a/htroot/Blacklist_p.java
+++ b/htroot/Blacklist_p.java
@@ -166,9 +166,9 @@ public class Blacklist_p {
return prop;
}
- final File BlackListFile = new File(listManager.listsPath, blacklistToUse);
- if(!BlackListFile.delete()) {
- Log.logWarning("Blacklist", "file "+ BlackListFile +" could not be deleted!");
+ final File blackListFile = new File(listManager.listsPath, blacklistToUse);
+ if(!blackListFile.delete()) {
+ Log.logWarning("Blacklist", "file "+ blackListFile +" could not be deleted!");
}
for (int blTypes=0; blTypes < supportedBlacklistTypes.length; blTypes++) {
diff --git a/htroot/ConfigAppearance_p.html b/htroot/ConfigAppearance_p.html
index c7d5c995d..5aac1235e 100644
--- a/htroot/ConfigAppearance_p.html
+++ b/htroot/ConfigAppearance_p.html
@@ -48,6 +48,8 @@
+
Make sure that you only download data from trustworthy sources. The new language file
+ might overwrite existing data if a file of the same name exists already.
diff --git a/htroot/ConfigAppearance_p.java b/htroot/ConfigAppearance_p.java
index 0678a6f72..0a0680ac3 100644
--- a/htroot/ConfigAppearance_p.java
+++ b/htroot/ConfigAppearance_p.java
@@ -52,7 +52,9 @@ import java.util.Collections;
public class ConfigAppearance_p {
- public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) {
+ private final static String SKIN_FILENAME_FILTER = "^.*\\.css$";
+
+ public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) {
final serverObjects prop = new serverObjects();
final Switchboard sb = (Switchboard) env;
final String skinPath = new File(env.getRootPath(), env.getConfig("skinPath", "DATA/SKINS")).toString();
@@ -61,26 +63,42 @@ public class ConfigAppearance_p {
prop.put("currentskin", "");
prop.put("status", "0"); // nothing
- List skinFiles = listManager.getDirListing(skinPath);
+ List skinFiles = listManager.getDirListing(skinPath, SKIN_FILENAME_FILTER);
if (skinFiles == null) {
return prop;
}
if (post != null) {
- if (post.containsKey("use_button") && post.get("skin") != null) {
- // change skin
- changeSkin(sb, skinPath, post.get("skin"));
+ String selectedSkin = post.get("skin");
+ if (post.containsKey("use_button") && selectedSkin != null) {
+ /* Only change skin if filename is contained in list of filesnames
+ * read from the skin directory. This is very important to prevent
+ * directory traversal attacks!
+ */
+ if (skinFiles.contains(selectedSkin)) {
+ changeSkin(sb, skinPath, selectedSkin);
+ }
+
}
+
if (post.containsKey("delete_button")) {
- // delete skin
- final File skinfile = new File(skinPath, post.get("skin"));
- FileUtils.deletedelete(skinfile);
+
+ /* Only delete file if filename is contained in list of filesname
+ * read from the skin directory. This is very important to prevent
+ * directory traversal attacks!
+ */
+ if (skinFiles.contains(selectedSkin)) {
+ final File skinfile = new File(skinPath, selectedSkin);
+ FileUtils.deletedelete(skinfile);
+ }
}
if (post.containsKey("install_button")) {
// load skin from URL
final String url = post.get("url");
+ final File skinFile = new File(skinPath, url.substring(url.lastIndexOf("/"), url.length()));
+
Iterator it;
try {
final DigestURI u = new DigestURI(url, null);
@@ -93,7 +111,6 @@ public class ConfigAppearance_p {
return prop;
}
try {
- final File skinFile = new File(skinPath, url.substring(url.lastIndexOf("/"), url.length()));
final BufferedWriter bw = new BufferedWriter(new PrintWriter(new FileWriter(skinFile)));
while (it.hasNext()) {
@@ -112,7 +129,7 @@ public class ConfigAppearance_p {
}
// reread skins
- skinFiles = listManager.getDirListing(skinPath);
+ skinFiles = listManager.getDirListing(skinPath, SKIN_FILENAME_FILTER);
Collections.sort(skinFiles);
int count = 0;
for (String skinFile : skinFiles) {
diff --git a/htroot/ConfigLanguage_p.html b/htroot/ConfigLanguage_p.html
index 4f2aa39c7..29192d109 100644
--- a/htroot/ConfigLanguage_p.html
+++ b/htroot/ConfigLanguage_p.html
@@ -51,6 +51,8 @@
+
Make sure that you only download data from trustworthy sources. The new language file
+ might overwrite existing data if a file of the same name exists already.
#(status)#
diff --git a/htroot/ConfigLanguage_p.java b/htroot/ConfigLanguage_p.java
index 5854c59df..e1fe8c331 100644
--- a/htroot/ConfigLanguage_p.java
+++ b/htroot/ConfigLanguage_p.java
@@ -54,8 +54,10 @@ import java.util.Collections;
public class ConfigLanguage_p {
+ private final static String LANG_FILENAME_FILTER = "^.*\\.lng$";
+
public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) {
- //listManager.switchboard = (plasmaSwitchboard) env;
+
final serverObjects prop = new serverObjects();
final String langPath = env.getConfigPath("locale.work", "DATA/LOCALE/locales").getAbsolutePath();
@@ -63,20 +65,35 @@ public class ConfigLanguage_p {
//prop.put("currentlang", ""); //is done by Translationtemplate
prop.put("status", "0");//nothing
- List langFiles = listManager.getDirListing(langPath);
+ List langFiles = listManager.getDirListing(langPath, LANG_FILENAME_FILTER);
if(langFiles == null){
return prop;
}
if (post != null){
+ String selectedLanguage = post.get("language");
+
//change language
- if(post.containsKey("use_button") && post.get("language") != null){
- translator.changeLang(env, langPath, post.get("language"));
+ if(post.containsKey("use_button") && selectedLanguage != null){
+ /* Only change language if filename is contained in list of filesnames
+ * read from the language directory. This is very important to prevent
+ * directory traversal attacks!
+ */
+ if (langFiles.contains(selectedLanguage)) {
+ translator.changeLang(env, langPath, selectedLanguage);
+ }
//delete language file
}else if(post.containsKey("delete")){
- final File langfile= new File(langPath, post.get("language"));
- FileUtils.deletedelete(langfile);
+
+ /* Only delete file if filename is contained in list of filesnames
+ * read from the language directory. This is very important to prevent
+ * directory traversal attacks!
+ */
+ if (langFiles.contains(selectedLanguage)) {
+ final File langfile= new File(langPath, selectedLanguage);
+ FileUtils.deletedelete(langfile);
+ }
//load language file from URL
} else if (post.containsKey("url")){
@@ -111,7 +128,7 @@ public class ConfigLanguage_p {
}
//reread language files
- langFiles = listManager.getDirListing(langPath);
+ langFiles = listManager.getDirListing(langPath, LANG_FILENAME_FILTER);
Collections.sort(langFiles);
final HashMap langNames = translator.langMap(env);
String langKey, langName;
@@ -123,20 +140,18 @@ public class ConfigLanguage_p {
int count = 0;
for(String langFile : langFiles){
- if(langFile.endsWith(".lng")){
- //+1 because of the virtual entry "default" at top
- langKey = langFile.substring(0, langFile.length() -4);
- langName = langNames.get(langKey);
- prop.put("langlist_" + (count + 1) + "_file", langFile);
- prop.put("langlist_" + (count + 1) + "_name", ((langName == null) ? langKey : langName));
- if(env.getConfig("locale.language", "default").equals(langKey)) {
- prop.put("langlist_" + (count + 1) + "_selected", "selected=\"selected\"");
- prop.put("langlist_0_selected", " "); // reset Default
- } else {
- prop.put("langlist_" + (count + 1) + "_selected", " ");
- }
- count++;
+ //+1 because of the virtual entry "default" at top
+ langKey = langFile.substring(0, langFile.length() -4);
+ langName = langNames.get(langKey);
+ prop.put("langlist_" + (count + 1) + "_file", langFile);
+ prop.put("langlist_" + (count + 1) + "_name", ((langName == null) ? langKey : langName));
+ if(env.getConfig("locale.language", "default").equals(langKey)) {
+ prop.put("langlist_" + (count + 1) + "_selected", "selected=\"selected\"");
+ prop.put("langlist_0_selected", " "); // reset Default
+ } else {
+ prop.put("langlist_" + (count + 1) + "_selected", " ");
}
+ count++;
}
prop.put("langlist", (count + 1));