aboutsummaryrefslogtreecommitdiff
path: root/subsonic-main/src/main/java/net/sourceforge/subsonic/filter
diff options
context:
space:
mode:
Diffstat (limited to 'subsonic-main/src/main/java/net/sourceforge/subsonic/filter')
-rw-r--r--subsonic-main/src/main/java/net/sourceforge/subsonic/filter/BootstrapVerificationFilter.java107
-rw-r--r--subsonic-main/src/main/java/net/sourceforge/subsonic/filter/ParameterDecodingFilter.java147
-rw-r--r--subsonic-main/src/main/java/net/sourceforge/subsonic/filter/RequestEncodingFilter.java54
-rw-r--r--subsonic-main/src/main/java/net/sourceforge/subsonic/filter/ResponseHeaderFilter.java57
4 files changed, 365 insertions, 0 deletions
diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/BootstrapVerificationFilter.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/BootstrapVerificationFilter.java
new file mode 100644
index 00000000..c93d0603
--- /dev/null
+++ b/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/BootstrapVerificationFilter.java
@@ -0,0 +1,107 @@
+/*
+ This file is part of Subsonic.
+
+ Subsonic 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 3 of the License, or
+ (at your option) any later version.
+
+ Subsonic 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.
+
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+
+ Copyright 2009 (C) Sindre Mehus
+ */
+package net.sourceforge.subsonic.filter;
+
+import net.sourceforge.subsonic.service.SettingsService;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * This filter is executed very early in the filter chain. It verifies that
+ * the Subsonic home directory (c:\subsonic or /var/subsonic) exists and
+ * is writable. If not, a proper error message is given to the user.
+ * <p/>
+ * (The Subsonic home directory is usually created automatically, but a common
+ * problem on Linux is that the Tomcat user does not have the necessary
+ * privileges).
+ *
+ * @author Sindre Mehus
+ */
+public class BootstrapVerificationFilter implements Filter {
+
+ private boolean subsonicHomeVerified = false;
+
+
+ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
+ throws IOException, ServletException {
+
+ // Already verified?
+ if (subsonicHomeVerified) {
+ chain.doFilter(req, res);
+ return;
+ }
+
+ File home = SettingsService.getSubsonicHome();
+ if (!directoryExists(home)) {
+ error(res, "<p>The directory <b>" + home + "</b> does not exist. Please create it and make it writable, " +
+ "then restart the servlet container.</p>" +
+ "<p>(You can override the directory location by specifying -Dsubsonic.home=... when " +
+ "starting the servlet container.)</p>");
+
+ } else if (!directoryWritable(home)) {
+ error(res, "<p>The directory <b>" + home + "</b> is not writable. Please change file permissions, " +
+ "then restart the servlet container.</p>" +
+ "<p>(You can override the directory location by specifying -Dsubsonic.home=... when " +
+ "starting the servlet container.)</p>");
+
+ } else {
+ subsonicHomeVerified = true;
+ chain.doFilter(req, res);
+ }
+ }
+
+ private boolean directoryExists(File dir) {
+ return dir.exists() && dir.isDirectory();
+ }
+
+ private boolean directoryWritable(File dir) {
+ try {
+ File tempFile = File.createTempFile("test", null, dir);
+ tempFile.delete();
+ return true;
+ } catch (IOException x) {
+ return false;
+ }
+ }
+
+ private void error(ServletResponse res, String error) throws IOException {
+ ServletOutputStream out = res.getOutputStream();
+ out.println("<html>" +
+ "<head><title>Subsonic Error</title></head>" +
+ "<body>" +
+ "<h2>Subsonic Error</h2>" +
+ error +
+ "</body>" +
+ "</html>");
+ }
+
+ public void init(FilterConfig filterConfig) {
+ }
+
+ public void destroy() {
+ }
+}
diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/ParameterDecodingFilter.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/ParameterDecodingFilter.java
new file mode 100644
index 00000000..52a98ad0
--- /dev/null
+++ b/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/ParameterDecodingFilter.java
@@ -0,0 +1,147 @@
+/*
+ This file is part of Subsonic.
+
+ Subsonic 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 3 of the License, or
+ (at your option) any later version.
+
+ Subsonic 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.
+
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+
+ Copyright 2009 (C) Sindre Mehus
+ */
+package net.sourceforge.subsonic.filter;
+
+import net.sourceforge.subsonic.Logger;
+import net.sourceforge.subsonic.util.StringUtil;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+/**
+ * Servlet filter which decodes HTTP request parameters. If a parameter name ends with
+ * "Utf8Hex" ({@link #PARAM_SUFFIX}) , the corresponding parameter value is assumed to be the
+ * hexadecimal representation of the UTF-8 bytes of the value.
+ * <p/>
+ * Used to support request parameter values of any character encoding.
+ *
+ * @author Sindre Mehus
+ */
+public class ParameterDecodingFilter implements Filter {
+
+ public static final String PARAM_SUFFIX = "Utf8Hex";
+ private static final Logger LOG = Logger.getLogger(ParameterDecodingFilter.class);
+
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+
+ // Wrap request in decoder.
+ ServletRequest decodedRequest = new DecodingServletRequestWrapper((HttpServletRequest) request);
+
+ // Pass the request/response on
+ chain.doFilter(decodedRequest, response);
+ }
+
+ public void init(FilterConfig filterConfig) {
+ }
+
+ public void destroy() {
+ }
+
+ private static class DecodingServletRequestWrapper extends HttpServletRequestWrapper {
+
+ public DecodingServletRequestWrapper(HttpServletRequest servletRequest) {
+ super(servletRequest);
+ }
+
+ @Override
+ public String getParameter(String name) {
+ String[] values = getParameterValues(name);
+ if (values == null || values.length == 0) {
+ return null;
+ }
+ return values[0];
+ }
+
+ @Override
+ public Map getParameterMap() {
+ Map map = super.getParameterMap();
+ Map<String, String[]> result = new HashMap<String, String[]>();
+
+ for (Object o : map.entrySet()) {
+ Map.Entry entry = (Map.Entry) o;
+ String name = (String) entry.getKey();
+ String[] values = (String[]) entry.getValue();
+
+ if (name.endsWith(PARAM_SUFFIX)) {
+ result.put(name.replace(PARAM_SUFFIX, ""), decode(values));
+ } else {
+ result.put(name, values);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public Enumeration getParameterNames() {
+ Enumeration e = super.getParameterNames();
+ Vector<String> v = new Vector<String>();
+ while (e.hasMoreElements()) {
+ String name = (String) e.nextElement();
+ if (name.endsWith(PARAM_SUFFIX)) {
+ name = name.replace(PARAM_SUFFIX, "");
+ }
+ v.add(name);
+ }
+
+ return v.elements();
+ }
+
+ @Override
+ public String[] getParameterValues(String name) {
+ String[] values = super.getParameterValues(name);
+ if (values != null) {
+ return values;
+ }
+
+ values = super.getParameterValues(name + PARAM_SUFFIX);
+ if (values != null) {
+ return decode(values);
+ }
+
+ return null;
+ }
+
+ private String[] decode(String[] values) {
+ if (values == null) {
+ return null;
+ }
+
+ String[] result = new String[values.length];
+ for (int i = 0; i < values.length; i++) {
+ try {
+ result[i] = StringUtil.utf8HexDecode(values[i]);
+ } catch (Exception x) {
+ LOG.error("Failed to decode parameter value '" + values[i] + "'");
+ result[i] = values[i];
+ }
+ }
+
+ return result;
+ }
+
+ }
+
+}
diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/RequestEncodingFilter.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/RequestEncodingFilter.java
new file mode 100644
index 00000000..3b37e8d4
--- /dev/null
+++ b/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/RequestEncodingFilter.java
@@ -0,0 +1,54 @@
+/*
+ This file is part of Subsonic.
+
+ Subsonic 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 3 of the License, or
+ (at your option) any later version.
+
+ Subsonic 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.
+
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+
+ Copyright 2009 (C) Sindre Mehus
+ */
+package net.sourceforge.subsonic.filter;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+import java.io.*;
+
+/**
+ * Configurable filter for setting the character encoding to use for the HTTP request.
+ * Typically used to set UTF-8 encoding when reading request parameters with non-Latin
+ * content.
+ *
+ * @author Sindre Mehus
+ * @version $Revision: 1.1 $ $Date: 2006/03/01 16:58:08 $
+ */
+public class RequestEncodingFilter implements Filter {
+
+ private String encoding;
+
+ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
+ throws IOException, ServletException {
+ HttpServletRequest request = (HttpServletRequest) req;
+ request.setCharacterEncoding(encoding);
+
+ // Pass the request/response on
+ chain.doFilter(req, res);
+ }
+
+ public void init(FilterConfig filterConfig) {
+ encoding = filterConfig.getInitParameter("encoding");
+ }
+
+ public void destroy() {
+ encoding = null;
+ }
+
+}
diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/ResponseHeaderFilter.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/ResponseHeaderFilter.java
new file mode 100644
index 00000000..33f60f83
--- /dev/null
+++ b/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/ResponseHeaderFilter.java
@@ -0,0 +1,57 @@
+/*
+ This file is part of Subsonic.
+
+ Subsonic 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 3 of the License, or
+ (at your option) any later version.
+
+ Subsonic 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.
+
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+
+ Copyright 2009 (C) Sindre Mehus
+ */
+package net.sourceforge.subsonic.filter;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+import java.io.*;
+import java.util.*;
+
+/**
+ * Configurable filter for setting HTTP response headers. Can be used, for instance, to
+ * set cache control directives for certain resources.
+ *
+ * @author Sindre Mehus
+ * @version $Revision: 1.1 $ $Date: 2005/08/14 13:14:47 $
+ */
+public class ResponseHeaderFilter implements Filter {
+ private FilterConfig filterConfig;
+
+ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
+ throws IOException, ServletException {
+ HttpServletResponse response = (HttpServletResponse) res;
+
+ // Sets the provided HTTP response parameters
+ for (Enumeration e = filterConfig.getInitParameterNames(); e.hasMoreElements();) {
+ String headerName = (String) e.nextElement();
+ response.addHeader(headerName, filterConfig.getInitParameter(headerName));
+ }
+
+ // pass the request/response on
+ chain.doFilter(req, response);
+ }
+
+ public void init(FilterConfig filterConfig) {
+ this.filterConfig = filterConfig;
+ }
+
+ public void destroy() {
+ this.filterConfig = null;
+ }
+} \ No newline at end of file