Merge remote-tracking branch 'origin/pr/1326'
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,10 +27,10 @@ import org.airsonic.player.service.SettingsService;
|
||||
import org.airsonic.player.service.StatusService;
|
||||
import org.airsonic.player.upload.MonitoredDiskFileItemFactory;
|
||||
import org.airsonic.player.upload.UploadListener;
|
||||
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;
|
||||
@@ -126,7 +126,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()) {
|
||||
@@ -173,13 +173,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();
|
||||
|
||||
@@ -877,7 +877,7 @@ public class SettingsService {
|
||||
String[] lines = StringUtil.readLines(in);
|
||||
|
||||
for (String line : lines) {
|
||||
locales.add(parseLocale(line));
|
||||
locales.add(StringUtil.parseLocale(line));
|
||||
}
|
||||
|
||||
} catch (IOException x) {
|
||||
@@ -888,21 +888,6 @@ public class SettingsService {
|
||||
return locales.toArray(new Locale[locales.size()]);
|
||||
}
|
||||
|
||||
private Locale parseLocale(String line) {
|
||||
String[] s = line.split("_");
|
||||
String language = s[0];
|
||||
String country = "";
|
||||
String variant = "";
|
||||
|
||||
if (s.length > 1) {
|
||||
country = s[1];
|
||||
}
|
||||
if (s.length > 2) {
|
||||
variant = s[2];
|
||||
}
|
||||
return new Locale(language, country, variant);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the "brand" name. Normally, this is just "Airsonic".
|
||||
*
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
package org.airsonic.player.util;
|
||||
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
@@ -28,11 +29,11 @@ import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Miscellaneous string utility methods.
|
||||
@@ -42,15 +43,8 @@ import java.util.regex.Pattern;
|
||||
public final class StringUtil {
|
||||
|
||||
public static final String ENCODING_UTF8 = "UTF-8";
|
||||
private static final DateFormat ISO_8601_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
|
||||
private static final String[][] HTML_SUBSTITUTIONS = {
|
||||
{"&", "&"},
|
||||
{"<", "<"},
|
||||
{">", ">"},
|
||||
{"'", "'"},
|
||||
{"\"", """},
|
||||
};
|
||||
private static final Pattern SPLIT_PATTERN = Pattern.compile("\"([^\"]*)\"|(\\S+)");
|
||||
|
||||
private static final String[][] MIME_TYPES = {
|
||||
{"mp3", "audio/mpeg"},
|
||||
@@ -98,58 +92,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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Formats the given date to a ISO-8601 date/time format, and UTC timezone.
|
||||
* <p/>
|
||||
* The returned date uses the following format: 2007-12-17T14:57:17
|
||||
*
|
||||
* @param date The date to format
|
||||
* @return The corresponding ISO-8601 formatted string.
|
||||
*/
|
||||
public static String toISO8601(Date date) {
|
||||
if (date == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
synchronized (ISO_8601_DATE_FORMAT) {
|
||||
return ISO_8601_DATE_FORMAT.format(date);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@@ -269,16 +211,14 @@ public final class StringUtil {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
Pattern pattern = Pattern.compile("\".*?\"|\\S+");
|
||||
Matcher matcher = pattern.matcher(input);
|
||||
|
||||
List<String> result = new ArrayList<String>();
|
||||
while (matcher.find()) {
|
||||
String element = matcher.group();
|
||||
if (element.startsWith("\"") && element.endsWith("\"") && element.length() > 1) {
|
||||
element = element.substring(1, element.length() - 1);
|
||||
List<String> result = new ArrayList<>();
|
||||
Matcher m = SPLIT_PATTERN.matcher(input);
|
||||
while (m.find()) {
|
||||
if (m.group(1) != null) {
|
||||
result.add(m.group(1)); // quoted string
|
||||
} else {
|
||||
result.add(m.group(2)); // unquoted string
|
||||
}
|
||||
result.add(element);
|
||||
}
|
||||
|
||||
return result.toArray(new String[result.size()]);
|
||||
@@ -320,21 +260,9 @@ public final class StringUtil {
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
String[] strings = StringUtils.split(s);
|
||||
int[] ints = new int[strings.length];
|
||||
for (int i = 0; i < strings.length; i++) {
|
||||
ints[i] = Integer.parseInt(strings[i]);
|
||||
}
|
||||
return ints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a is equal to b, taking null into account.
|
||||
*
|
||||
* @return Whether a and b are equal, or both null.
|
||||
*/
|
||||
public static boolean isEqual(Object a, Object b) {
|
||||
return Objects.equals(a, b);
|
||||
return Stream.of(StringUtils.split(s))
|
||||
.mapToInt(Integer::parseInt)
|
||||
.toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -348,18 +276,11 @@ public final class StringUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] elements = s.split("_");
|
||||
|
||||
if (elements.length == 0) {
|
||||
return new Locale(s, "", "");
|
||||
List<String> elements = new ArrayList<>(Arrays.asList(s.split("_", 3)));
|
||||
while (elements.size() < 3) {
|
||||
elements.add("");
|
||||
}
|
||||
if (elements.length == 1) {
|
||||
return new Locale(elements[0], "", "");
|
||||
}
|
||||
if (elements.length == 2) {
|
||||
return new Locale(elements[0], elements[1], "");
|
||||
}
|
||||
return new Locale(elements[0], elements[1], elements[2]);
|
||||
return new Locale(elements.get(0), elements.get(1), elements.get(2));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -404,34 +325,15 @@ public final class StringUtil {
|
||||
*
|
||||
* @param s The string to decode.
|
||||
* @return The decoded string.
|
||||
* @throws Exception If an error occurs.
|
||||
* @throws DecoderException If an error occurs.
|
||||
*/
|
||||
public static String utf8HexDecode(String s) throws Exception {
|
||||
public static String utf8HexDecode(String s) throws DecoderException {
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
return new String(Hex.decodeHex(s.toCharArray()), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the MD5 digest and returns the value as a 32 character hex string.
|
||||
*
|
||||
* @param s Data to digest.
|
||||
* @return MD5 digest as a hex string.
|
||||
*/
|
||||
public static String md5Hex(String s) {
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||
return new String(Hex.encodeHex(md5.digest(s.getBytes(StandardCharsets.UTF_8))));
|
||||
} catch (Exception x) {
|
||||
throw new RuntimeException(x.getMessage(), x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file part of an URL. For instance:
|
||||
* <p/>
|
||||
|
||||
@@ -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() {
|
||||
@@ -184,12 +176,6 @@ public class StringUtilTestCase extends TestCase {
|
||||
assertEquals("Error in utf8hex.", s, StringUtil.utf8HexDecode(StringUtil.utf8HexEncode(s)));
|
||||
}
|
||||
|
||||
public void testMd5Hex() {
|
||||
assertNull("Error in md5Hex().", StringUtil.md5Hex(null));
|
||||
assertEquals("Error in md5Hex().", "d41d8cd98f00b204e9800998ecf8427e", StringUtil.md5Hex(""));
|
||||
assertEquals("Error in md5Hex().", "308ed0af23d48f6d2fd4717e77a23e0c", StringUtil.md5Hex("sindre@activeobjects.no"));
|
||||
}
|
||||
|
||||
public void testGetUrlFile() {
|
||||
assertEquals("Error in getUrlFile().", "foo.mp3", StringUtil.getUrlFile("http://www.asdf.com/foo.mp3"));
|
||||
assertEquals("Error in getUrlFile().", "foo.mp3", StringUtil.getUrlFile("http://www.asdf.com/bar/foo.mp3"));
|
||||
|
||||
Reference in New Issue
Block a user