diff --git a/airsonic-main/src/main/java/org/airsonic/player/ajax/CoverArtService.java b/airsonic-main/src/main/java/org/airsonic/player/ajax/CoverArtService.java index 9d8d3407..498936eb 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/ajax/CoverArtService.java +++ b/airsonic-main/src/main/java/org/airsonic/player/ajax/CoverArtService.java @@ -25,8 +25,8 @@ import org.airsonic.player.service.LastFmService; import org.airsonic.player.service.MediaFileService; import org.airsonic.player.service.SecurityService; import org.airsonic.player.util.FileUtil; -import org.airsonic.player.util.StringUtil; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringEscapeUtils; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; @@ -109,7 +109,7 @@ public class CoverArtService { // Check permissions. File newCoverFile = new File(path, "cover." + suffix); if (!securityService.isWriteAllowed(newCoverFile)) { - throw new Exception("Permission denied: " + StringUtil.toHtml(newCoverFile.getPath())); + throw new Exception("Permission denied: " + StringEscapeUtils.escapeHtml(newCoverFile.getPath())); } // If file exists, create a backup. diff --git a/airsonic-main/src/main/java/org/airsonic/player/ajax/NowPlayingService.java b/airsonic-main/src/main/java/org/airsonic/player/ajax/NowPlayingService.java index 302b1aa4..63e0a28a 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/ajax/NowPlayingService.java +++ b/airsonic-main/src/main/java/org/airsonic/player/ajax/NowPlayingService.java @@ -22,6 +22,7 @@ package org.airsonic.player.ajax; import org.airsonic.player.domain.*; import org.airsonic.player.service.*; import org.airsonic.player.util.StringUtil; +import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; import org.directwebremoting.WebContext; import org.directwebremoting.WebContextFactory; @@ -129,14 +130,14 @@ public class NowPlayingService { avatarUrl = url + "avatar.view?usernameUtf8Hex=" + StringUtil.utf8HexEncode(username); } - String tooltip = StringUtil.toHtml(artist) + " – " + StringUtil.toHtml(title); + String tooltip = StringEscapeUtils.escapeHtml(artist) + " – " + StringEscapeUtils.escapeHtml(title); if (StringUtils.isNotBlank(player.getName())) { username += "@" + player.getName(); } - artist = StringUtil.toHtml(StringUtils.abbreviate(artist, 25)); - title = StringUtil.toHtml(StringUtils.abbreviate(title, 25)); - username = StringUtil.toHtml(StringUtils.abbreviate(username, 25)); + artist = StringEscapeUtils.escapeHtml(StringUtils.abbreviate(artist, 25)); + title = StringEscapeUtils.escapeHtml(StringUtils.abbreviate(title, 25)); + username = StringEscapeUtils.escapeHtml(StringUtils.abbreviate(username, 25)); long minutesAgo = status.getMinutesAgo(); diff --git a/airsonic-main/src/main/java/org/airsonic/player/controller/SetMusicFileInfoController.java b/airsonic-main/src/main/java/org/airsonic/player/controller/SetMusicFileInfoController.java index 92018ecd..8a37d5ee 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/controller/SetMusicFileInfoController.java +++ b/airsonic-main/src/main/java/org/airsonic/player/controller/SetMusicFileInfoController.java @@ -21,7 +21,7 @@ package org.airsonic.player.controller; import org.airsonic.player.domain.MediaFile; import org.airsonic.player.service.MediaFileService; -import org.airsonic.player.util.StringUtil; +import org.apache.commons.lang.StringEscapeUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.ServletRequestUtils; @@ -52,7 +52,7 @@ public class SetMusicFileInfoController { MediaFile mediaFile = mediaFileService.getMediaFile(id); if ("comment".equals(action)) { - mediaFile.setComment(StringUtil.toHtml(request.getParameter("comment"))); + mediaFile.setComment(StringEscapeUtils.escapeHtml(request.getParameter("comment"))); mediaFileService.updateMediaFile(mediaFile); } diff --git a/airsonic-main/src/main/java/org/airsonic/player/controller/UploadController.java b/airsonic-main/src/main/java/org/airsonic/player/controller/UploadController.java index 5256fb7d..6f6936ab 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/controller/UploadController.java +++ b/airsonic-main/src/main/java/org/airsonic/player/controller/UploadController.java @@ -28,10 +28,10 @@ import org.airsonic.player.service.StatusService; import org.airsonic.player.upload.MonitoredDiskFileItemFactory; import org.airsonic.player.upload.UploadListener; import org.airsonic.player.util.FileUtil; -import org.airsonic.player.util.StringUtil; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.apache.commons.lang.StringEscapeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -127,7 +127,7 @@ public class UploadController { File targetFile = new File(dir, new File(fileName).getName()); if (!securityService.isUploadAllowed(targetFile)) { - throw new Exception("Permission denied: " + StringUtil.toHtml(targetFile.getPath())); + throw new Exception("Permission denied: " + StringEscapeUtils.escapeHtml(targetFile.getPath())); } if (!dir.exists()) { @@ -174,13 +174,13 @@ public class UploadController { ZipEntry entry = (ZipEntry) entries.nextElement(); File entryFile = new File(file.getParentFile(), entry.getName()); if (!entryFile.toPath().normalize().startsWith(file.getParentFile().toPath())) { - throw new Exception("Bad zip filename: " + StringUtil.toHtml(entryFile.getPath())); + throw new Exception("Bad zip filename: " + StringEscapeUtils.escapeHtml(entryFile.getPath())); } if (!entry.isDirectory()) { if (!securityService.isUploadAllowed(entryFile)) { - throw new Exception("Permission denied: " + StringUtil.toHtml(entryFile.getPath())); + throw new Exception("Permission denied: " + StringEscapeUtils.escapeHtml(entryFile.getPath())); } entryFile.getParentFile().mkdirs(); diff --git a/airsonic-main/src/main/java/org/airsonic/player/util/StringUtil.java b/airsonic-main/src/main/java/org/airsonic/player/util/StringUtil.java index b4d4b401..2b459379 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/util/StringUtil.java +++ b/airsonic-main/src/main/java/org/airsonic/player/util/StringUtil.java @@ -20,6 +20,7 @@ package org.airsonic.player.util; import org.apache.commons.codec.binary.Hex; +import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; import java.io.*; @@ -43,14 +44,6 @@ public final class StringUtil { public static final String ENCODING_UTF8 = "UTF-8"; - private static final String[][] HTML_SUBSTITUTIONS = { - {"&", "&"}, - {"<", "<"}, - {">", ">"}, - {"'", "'"}, - {"\"", """}, - }; - private static final String[][] MIME_TYPES = { {"mp3", "audio/mpeg"}, {"ogg", "audio/ogg"}, @@ -97,40 +90,6 @@ public final class StringUtil { private StringUtil() { } - /** - * Returns the specified string converted to a format suitable for - * HTML. All single-quote, double-quote, greater-than, less-than and - * ampersand characters are replaces with their corresponding HTML - * Character Entity code. - * - * @param s the string to convert - * @return the converted string - */ - public static String toHtml(String s) { - if (s == null) { - return null; - } - for (String[] substitution : HTML_SUBSTITUTIONS) { - if (s.contains(substitution[0])) { - s = s.replaceAll(substitution[0], substitution[1]); - } - } - return s; - } - - - /** - * Removes the suffix (the substring after the last dot) of the given string. The dot is - * also removed. - * - * @param s The string in question, e.g., "foo.mp3". - * @return The string without the suffix, e.g., "foo". - */ - public static String removeSuffix(String s) { - int index = s.lastIndexOf('.'); - return index == -1 ? s : s.substring(0, index); - } - /** * Returns the proper MIME type for the given suffix. * diff --git a/airsonic-main/src/test/java/org/airsonic/player/util/StringUtilTestCase.java b/airsonic-main/src/test/java/org/airsonic/player/util/StringUtilTestCase.java index c45cd14b..b187acb8 100644 --- a/airsonic-main/src/test/java/org/airsonic/player/util/StringUtilTestCase.java +++ b/airsonic-main/src/test/java/org/airsonic/player/util/StringUtilTestCase.java @@ -20,6 +20,7 @@ package org.airsonic.player.util; import junit.framework.TestCase; +import org.apache.commons.lang.StringEscapeUtils; import java.util.Arrays; import java.util.Locale; @@ -32,20 +33,11 @@ import java.util.Locale; public class StringUtilTestCase extends TestCase { public void testToHtml() { - assertEquals(null, StringUtil.toHtml(null)); - assertEquals("", StringUtil.toHtml("")); - assertEquals(" ", StringUtil.toHtml(" ")); - assertEquals("q & a", StringUtil.toHtml("q & a")); - assertEquals("q & a <> b", StringUtil.toHtml("q & a <> b")); - } - - public void testRemoveSuffix() { - assertEquals("Error in removeSuffix().", "foo", StringUtil.removeSuffix("foo.mp3")); - assertEquals("Error in removeSuffix().", "", StringUtil.removeSuffix(".mp3")); - assertEquals("Error in removeSuffix().", "foo.bar", StringUtil.removeSuffix("foo.bar.mp3")); - assertEquals("Error in removeSuffix().", "foo.", StringUtil.removeSuffix("foo..mp3")); - assertEquals("Error in removeSuffix().", "foo", StringUtil.removeSuffix("foo")); - assertEquals("Error in removeSuffix().", "", StringUtil.removeSuffix("")); + assertEquals(null, StringEscapeUtils.escapeHtml(null)); + assertEquals("", StringEscapeUtils.escapeHtml("")); + assertEquals(" ", StringEscapeUtils.escapeHtml(" ")); + assertEquals("q & a", StringEscapeUtils.escapeHtml("q & a")); + assertEquals("q & a <> b", StringEscapeUtils.escapeHtml("q & a <> b")); } public void testGetMimeType() {