diff --git a/libresonic-main/pom.xml b/libresonic-main/pom.xml index 40ae8b15..ac1fe759 100644 --- a/libresonic-main/pom.xml +++ b/libresonic-main/pom.xml @@ -77,14 +77,15 @@ - javax.servlet - jstl - 1.2 + org.apache.taglibs + taglibs-standard-impl + 1.2.5 taglibs string 1.1.0 + runtime @@ -223,6 +224,20 @@ 2.5.1 + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + + javax.servlet + jstl + 1.2 + runtime + + javax.mail javax.mail-api @@ -284,7 +299,6 @@ spring-web - runtime @@ -372,6 +386,7 @@ spring-boot-maven-plugin org.libresonic.player.boot.Application + WAR diff --git a/libresonic-main/src/main/java/org/libresonic/player/boot/Application.java b/libresonic-main/src/main/java/org/libresonic/player/boot/Application.java index 86f40157..6e05cc4a 100644 --- a/libresonic-main/src/main/java/org/libresonic/player/boot/Application.java +++ b/libresonic-main/src/main/java/org/libresonic/player/boot/Application.java @@ -1,10 +1,18 @@ package org.libresonic.player.boot; +import javax.servlet.Filter; +import javax.servlet.ServletContextListener; +import net.sf.ehcache.constructs.web.ShutdownListener; import org.directwebremoting.servlet.DwrServlet; +import org.libresonic.player.filter.BootstrapVerificationFilter; +import org.libresonic.player.filter.ParameterDecodingFilter; +import org.libresonic.player.filter.RESTFilter; +import org.libresonic.player.filter.RequestEncodingFilter; +import org.libresonic.player.filter.ResponseHeaderFilter; import org.libresonic.player.spring.AdditionalPropertySourceConfigurer; -import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; @@ -31,19 +39,124 @@ public class Application extends SpringBootServletInitializer { return servlet; } + @Bean + public ServletRegistrationBean cxfServletBean() { + return new ServletRegistrationBean(new org.apache.cxf.transport.servlet.CXFServlet(), "/ws/*"); + } + + @Bean + public ServletContextListener ehCacheShutdownListener() { + return new ShutdownListener(); + } + + @Bean + public FilterRegistrationBean bootstrapVerificationFilterRegistration() { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(bootstrapVerificationFiler()); + registration.addUrlPatterns("/*"); + registration.setName("BootstrapVerificationFilter"); + registration.setOrder(1); + return registration; + } + + @Bean + public Filter bootstrapVerificationFiler() { + return new BootstrapVerificationFilter(); + } + + @Bean + public FilterRegistrationBean parameterDecodingFilterRegistration() { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(parameterDecodingFilter()); + registration.addUrlPatterns("/*"); + registration.setName("ParameterDecodingFilter"); + registration.setOrder(2); + return registration; + } + + @Bean + public Filter parameterDecodingFilter() { + return new ParameterDecodingFilter(); + } + + @Bean + public FilterRegistrationBean restFilterRegistration() { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(restFilter()); + registration.addUrlPatterns("/rest/*"); + registration.setName("RESTFilter"); + registration.setOrder(3); + return registration; + } + + @Bean + public Filter restFilter() { + return new RESTFilter(); + } + + @Bean + public FilterRegistrationBean requestEncodingFilterRegistration() { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(requestEncodingFilter()); + registration.addUrlPatterns("/*"); + registration.addInitParameter("encoding", "UTF-8"); + registration.setName("RequestEncodingFilter"); + registration.setOrder(4); + return registration; + } + + @Bean + public Filter requestEncodingFilter() { + return new RequestEncodingFilter(); + } + + @Bean + public FilterRegistrationBean cacheFilterRegistration() { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(cacheFilter()); + registration.addUrlPatterns("/icons/*", "/style/*"); + registration.addInitParameter("Cache-Control", "max-age=36000"); + registration.setName("CacheFilter"); + registration.setOrder(5); + return registration; + } + + @Bean + public Filter cacheFilter() { + return new ResponseHeaderFilter(); + } + + @Bean + public FilterRegistrationBean noCacheFilterRegistration() { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(noCacheFilter()); + registration.addUrlPatterns("/statusChart.view", "/userChart.view", "/playQueue.view", "/podcastChannels.view", "/podcastChannel.view", "/help.view", "/top.view", "/home.view"); + registration.addInitParameter("Cache-Control", "no-cache, post-check=0, pre-check=0"); + registration.addInitParameter("Pragma", "no-cache"); + registration.addInitParameter("Expires", "Thu, 01 Dec 1994 16:00:00 GMT"); + registration.setName("NoCacheFilter"); + registration.setOrder(6); + return registration; + } + + @Bean + public Filter noCacheFilter() { + return new ResponseHeaderFilter(); + } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { // Customize the application or call application.sources(...) to add sources // Since our example is itself a @Configuration class (via @SpringBootApplication) // we actually don't need to override this method. - return application; + return application.sources(Application.class); } public static void main(String[] args) { - SpringApplication springApplication = new SpringApplication(Application.class); - springApplication.addInitializers(new AdditionalPropertySourceConfigurer()); - springApplication.run(args); + new Application().configure(new SpringApplicationBuilder(Application.class)) + .web(true) + .initializers(new AdditionalPropertySourceConfigurer()) + .run(args); } } \ No newline at end of file diff --git a/libresonic-main/src/main/java/org/libresonic/player/spring/DbmsVersionPrecondition.java b/libresonic-main/src/main/java/org/libresonic/player/spring/DbmsVersionPrecondition.java index 0b16fc04..89161061 100644 --- a/libresonic-main/src/main/java/org/libresonic/player/spring/DbmsVersionPrecondition.java +++ b/libresonic-main/src/main/java/org/libresonic/player/spring/DbmsVersionPrecondition.java @@ -1,64 +1,31 @@ package org.libresonic.player.spring; -import liquibase.changelog.ChangeSet; -import liquibase.changelog.DatabaseChangeLog; import liquibase.database.Database; -import liquibase.exception.PreconditionErrorException; -import liquibase.exception.PreconditionFailedException; -import liquibase.exception.ValidationErrors; -import liquibase.exception.Warnings; -import liquibase.precondition.Precondition; -import liquibase.serializer.AbstractLiquibaseSerializable; +import liquibase.exception.CustomPreconditionErrorException; +import liquibase.exception.CustomPreconditionFailedException; +import liquibase.exception.DatabaseException; +import liquibase.precondition.CustomPrecondition; -public class DbmsVersionPrecondition extends AbstractLiquibaseSerializable implements Precondition { +public class DbmsVersionPrecondition implements CustomPrecondition { private Integer major; private Integer minor; @Override - public String getName() { - return "dbmsVersion"; - } - - @Override - public Warnings warn(Database database) { - return new Warnings(); - } - - @Override - public ValidationErrors validate(Database database) { - return new ValidationErrors(); - } - - @Override - public void check( - Database database, DatabaseChangeLog changeLog, ChangeSet changeSet - ) throws PreconditionFailedException, PreconditionErrorException { + public void check(Database database) throws CustomPreconditionFailedException, CustomPreconditionErrorException { try { int dbMajor = database.getDatabaseMajorVersion(); int dbMinor = database.getDatabaseMinorVersion(); if(major != null && !major.equals(dbMajor)) { - throw new PreconditionFailedException("DBMS Major Version Precondition failed: expected " + major + ", got " + dbMajor, changeLog, this); + throw new CustomPreconditionFailedException("DBMS Major Version Precondition failed: expected " + major + ", got " + dbMajor); } if(minor != null && !minor.equals(dbMinor)) { - throw new PreconditionFailedException("DBMS Minor Version Precondition failed: expected " + minor + ", got " + dbMinor, changeLog, this); + throw new CustomPreconditionFailedException("DBMS Minor Version Precondition failed: expected " + minor + ", got " + dbMinor); } - } catch (PreconditionFailedException e) { - throw e; - } catch (Exception e) { - throw new PreconditionErrorException(e, changeLog, this); + } catch (DatabaseException e) { + throw new CustomPreconditionErrorException(e.getMessage()); } } - @Override - public String getSerializedObjectName() { - return getName(); - } - - @Override - public String getSerializedObjectNamespace() { - return GENERIC_CHANGELOG_EXTENSION_NAMESPACE; - } - public Integer getMajor() { return major; } @@ -74,4 +41,5 @@ public class DbmsVersionPrecondition extends AbstractLiquibaseSerializable imple public void setMinor(Integer minor) { this.minor = minor; } + } diff --git a/libresonic-main/src/main/java/org/libresonic/player/spring/SpringLiquibase.java b/libresonic-main/src/main/java/org/libresonic/player/spring/SpringLiquibase.java index 4eda164a..0ff200b4 100644 --- a/libresonic-main/src/main/java/org/libresonic/player/spring/SpringLiquibase.java +++ b/libresonic-main/src/main/java/org/libresonic/player/spring/SpringLiquibase.java @@ -51,7 +51,6 @@ public class SpringLiquibase extends liquibase.integration.spring.SpringLiquibas if (StringUtils.trimToNull(this.defaultSchema) != null) { database.setDefaultSchemaName(this.defaultSchema); } - liquibase.precondition.PreconditionFactory.getInstance().register(DbmsVersionPrecondition.class); return database; } diff --git a/libresonic-main/src/main/resources/application.properties b/libresonic-main/src/main/resources/application.properties new file mode 100644 index 00000000..d8a35e3b --- /dev/null +++ b/libresonic-main/src/main/resources/application.properties @@ -0,0 +1,3 @@ +spring.mvc.view.prefix: /WEB-INF/jsp/ +spring.mvc.view.suffix: .jsp +server.error.includeStacktrace: ALWAYS diff --git a/libresonic-main/src/main/resources/libresonic-servlet.xml b/libresonic-main/src/main/resources/libresonic-servlet.xml index 5ae4d97e..c34faccd 100644 --- a/libresonic-main/src/main/resources/libresonic-servlet.xml +++ b/libresonic-main/src/main/resources/libresonic-servlet.xml @@ -47,4 +47,6 @@ + + diff --git a/libresonic-main/src/main/resources/liquibase/legacy/schema47.xml b/libresonic-main/src/main/resources/liquibase/legacy/schema47.xml index df3eb9f7..ba176727 100644 --- a/libresonic-main/src/main/resources/liquibase/legacy/schema47.xml +++ b/libresonic-main/src/main/resources/liquibase/legacy/schema47.xml @@ -238,7 +238,7 @@ select count(*) from INFORMATION_SCHEMA.SYSTEM_INDEXINFO where - TABLE_NAME = 'album' and INDEX_NAME = 'idx_album_name'; + lower(TABLE_NAME) = 'album' and lower(INDEX_NAME) = 'idx_album_name'; diff --git a/libresonic-main/src/main/resources/liquibase/legacy/schema53.xml b/libresonic-main/src/main/resources/liquibase/legacy/schema53.xml index f8bad2fd..5a053df4 100644 --- a/libresonic-main/src/main/resources/liquibase/legacy/schema53.xml +++ b/libresonic-main/src/main/resources/liquibase/legacy/schema53.xml @@ -39,7 +39,7 @@ select count(*) from INFORMATION_SCHEMA.SYSTEM_INDEXINFO where - TABLE_NAME = 'podcast_episode' and INDEX_NAME = 'idx_podcast_episode_url'; + lower(TABLE_NAME) = 'podcast_episode' and lower(INDEX_NAME) = 'idx_podcast_episode_url'; diff --git a/libresonic-main/src/main/webapp/error.jsp b/libresonic-main/src/main/webapp/WEB-INF/jsp/error.jsp similarity index 73% rename from libresonic-main/src/main/webapp/error.jsp rename to libresonic-main/src/main/webapp/WEB-INF/jsp/error.jsp index e1b4d758..841a7279 100644 --- a/libresonic-main/src/main/webapp/error.jsp +++ b/libresonic-main/src/main/webapp/WEB-INF/jsp/error.jsp @@ -1,5 +1,7 @@ -<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" isErrorPage="true" %> -<%@ page import="java.io.PrintWriter, java.io.StringWriter"%> +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="UTF-8" isErrorPage="true" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + - - contextConfigLocation - - /WEB-INF/applicationContext-service.xml - /WEB-INF/applicationContext-security.xml - /WEB-INF/applicationContext-cache.xml - /WEB-INF/applicationContext-sonos.xml - - - - - contextInitializerClasses - org.libresonic.player.spring.AdditionalPropertySourceConfigurer - - - - org.springframework.web.context.ContextLoaderListener - - - net.sf.ehcache.constructs.web.ShutdownListener - - - - libresonic - org.springframework.web.servlet.DispatcherServlet - 1 - - - - CFX Servlet - cxfservlet - org.apache.cxf.transport.servlet.CXFServlet - 1 - - - - DWR Servlet - dwr-invoker - org.directwebremoting.servlet.DwrServlet - - crossDomainSessionSecurity - false - - - - - libresonic - *.view - - - libresonic - /podcast - - - libresonic - /wap - - - libresonic - /play.m3u - - - libresonic - /stream/* - - - libresonic - /rest/* - - - libresonic - /hls/* - - - libresonic - /share/* - - - dwr-invoker - /dwr/* - - - cxfservlet - /ws/* - - - - index.html - index.jsp - - - - java.lang.Throwable - /error.jsp - - - - BootstrapVerificationFilter - org.libresonic.player.filter.BootstrapVerificationFilter - - - BootstrapVerificationFilter - /* - - - - ParameterDecodingFilter - org.libresonic.player.filter.ParameterDecodingFilter - - - ParameterDecodingFilter - /* - - - - RESTFilter - org.libresonic.player.filter.RESTFilter - - - RESTFilter - /rest/* - - - - RequestEncodingFilter - org.libresonic.player.filter.RequestEncodingFilter - - encoding - UTF-8 - - - - RequestEncodingFilter - /* - - - - Sets HTTP headers to enable browser caching. - CacheFilter - org.libresonic.player.filter.ResponseHeaderFilter - - Cache-Control - max-age=36000 - - - - - Sets HTTP headers to disable browser caching. - NoCacheFilter - org.libresonic.player.filter.ResponseHeaderFilter - - Cache-Control - no-cache, post-check=0, pre-check=0 - - - Pragma - no-cache - - - Expires - Thu, 01 Dec 1994 16:00:00 GMT - - - - - CacheFilter - /icons/* - - - CacheFilter - /style/* - - - - NoCacheFilter - /statusChart.view - - - NoCacheFilter - /userChart.view - - - NoCacheFilter - /playQueue.view - - - NoCacheFilter - /podcastChannels.view - - - NoCacheFilter - /podcastChannel.view - - - NoCacheFilter - /help.view - - - NoCacheFilter - /top.view - - - NoCacheFilter - /home.view - - - - springSecurityFilterChain - org.springframework.web.filter.DelegatingFilterProxy - - - - springSecurityFilterChain - /* - - - \ No newline at end of file diff --git a/pom.xml b/pom.xml index e0b6a88d..ee8c42c9 100644 --- a/pom.xml +++ b/pom.xml @@ -142,6 +142,12 @@ maven-jaxb2-plugin 0.13.1 + + maven-war-plugin + + false + +