Merge branch 'develop' into biconou_develop_PR_metrics

master
Rémi Cocula 8 years ago
commit 09eabd3f29
  1. 6
      .travis.yml
  2. 67
      documentation/PROXY.md
  3. 0
      documentation/TRANSCODE.TXT
  4. 62
      libresonic-assembly/pom.xml
  5. 56
      libresonic-assembly/src/main/assembly/src.xml
  6. 43
      libresonic-assembly/src/main/assembly/standalone.xml
  7. 27
      libresonic-assembly/src/main/assembly/war.xml
  8. 98
      libresonic-booter/pom.xml
  9. 65
      libresonic-booter/src/main/java/org/libresonic/player/booter/Main.java
  10. 201
      libresonic-booter/src/main/java/org/libresonic/player/booter/agent/LibresonicAgent.java
  11. 113
      libresonic-booter/src/main/java/org/libresonic/player/booter/agent/LibresonicFrame.java
  12. 28
      libresonic-booter/src/main/java/org/libresonic/player/booter/agent/LibresonicListener.java
  13. 375
      libresonic-booter/src/main/java/org/libresonic/player/booter/agent/SettingsPanel.java
  14. 116
      libresonic-booter/src/main/java/org/libresonic/player/booter/agent/StatusPanel.java
  15. 125
      libresonic-booter/src/main/java/org/libresonic/player/booter/agent/TrayController.java
  16. 44
      libresonic-booter/src/main/java/org/libresonic/player/booter/deployer/DeploymentStatus.java
  17. 338
      libresonic-booter/src/main/java/org/libresonic/player/booter/deployer/LibresonicDeployer.java
  18. 17
      libresonic-booter/src/main/java/org/libresonic/player/booter/deployer/LibresonicDeployerService.java
  19. 89
      libresonic-booter/src/main/java/org/libresonic/player/booter/mac/LibresonicController.java
  20. 82
      libresonic-booter/src/main/java/org/libresonic/player/booter/mac/LibresonicFrame.java
  21. 115
      libresonic-booter/src/main/java/org/libresonic/player/booter/mac/StatusPanel.java
  22. 2
      libresonic-booter/src/main/resources/META-INF/MANIFEST.MF
  23. 33
      libresonic-booter/src/main/resources/applicationContext-agent.xml
  24. 15
      libresonic-booter/src/main/resources/applicationContext-deployer.xml
  25. 18
      libresonic-booter/src/main/resources/applicationContext-mac.xml
  26. BIN
      libresonic-booter/src/main/resources/images/libresonic-16.png
  27. BIN
      libresonic-booter/src/main/resources/images/libresonic-21.png
  28. BIN
      libresonic-booter/src/main/resources/images/libresonic-32.png
  29. BIN
      libresonic-booter/src/main/resources/images/libresonic-512.png
  30. BIN
      libresonic-booter/src/main/resources/images/libresonic-started-16.png
  31. BIN
      libresonic-booter/src/main/resources/images/libresonic-stopped-16.png
  32. BIN
      libresonic-booter/src/main/resources/libresonic.keystore
  33. 39
      libresonic-booter/src/main/resources/web-jetty.xml
  34. 24
      libresonic-booter/src/main/script/libresonic.bat
  35. 134
      libresonic-booter/src/main/script/libresonic.sh
  36. 87
      libresonic-installer-debian/pom.xml
  37. 1
      libresonic-installer-debian/src/DEBIAN/conffiles
  38. 18
      libresonic-installer-debian/src/DEBIAN/control
  39. 16
      libresonic-installer-debian/src/DEBIAN/postinst
  40. 9
      libresonic-installer-debian/src/DEBIAN/postrm
  41. 15
      libresonic-installer-debian/src/DEBIAN/preinst
  42. 8
      libresonic-installer-debian/src/DEBIAN/prerm
  43. 25
      libresonic-installer-debian/src/etc/default/libresonic
  44. 138
      libresonic-installer-debian/src/etc/init.d/libresonic
  45. 111
      libresonic-installer-mac/pom.xml
  46. BIN
      libresonic-installer-mac/src/libresonic.icns
  47. 883
      libresonic-installer-mac/src/libresonic.pkgproj
  48. BIN
      libresonic-installer-mac/src/libresonic.png
  49. 13
      libresonic-installer-mac/src/postinstall.sh
  50. 11
      libresonic-installer-mac/src/preinstall.sh
  51. 121
      libresonic-installer-rpm/pom.xml
  52. 104
      libresonic-installer-rpm/src/etc/init.d/libresonic
  53. 25
      libresonic-installer-rpm/src/etc/sysconfig/libresonic
  54. 78
      libresonic-installer-rpm/src/libresonic.spec
  55. 104
      libresonic-installer-windows/pom.xml
  56. BIN
      libresonic-installer-windows/src/main/exe4j/libresonic-16.ico
  57. 1
      libresonic-installer-windows/src/main/exe4j/libresonic-agent-elevated.exe.vmoptions
  58. 35
      libresonic-installer-windows/src/main/exe4j/libresonic-agent-elevated.exe4j
  59. 1
      libresonic-installer-windows/src/main/exe4j/libresonic-agent.exe.vmoptions
  60. 41
      libresonic-installer-windows/src/main/exe4j/libresonic-agent.exe4j
  61. 6
      libresonic-installer-windows/src/main/exe4j/libresonic-service.exe.vmoptions
  62. 41
      libresonic-installer-windows/src/main/exe4j/libresonic-service.exe4j
  63. BIN
      libresonic-installer-windows/src/main/nsis/jre-8u31-windows-i586-iftw.exe
  64. 213
      libresonic-installer-windows/src/main/nsis/libresonic.nsi
  65. 5
      libresonic-main/pom.xml
  66. 36
      libresonic-main/src/main/java/org/libresonic/player/boot/Application.java
  67. 2
      libresonic-main/src/main/java/org/libresonic/player/controller/AdvancedSettingsController.java
  68. 26
      libresonic-main/src/main/java/org/libresonic/player/controller/ControllerUtils.java
  69. 2
      libresonic-main/src/main/java/org/libresonic/player/controller/DBController.java
  70. 1
      libresonic-main/src/main/java/org/libresonic/player/controller/GettingStartedController.java
  71. 1
      libresonic-main/src/main/java/org/libresonic/player/controller/IndexController.java
  72. 2
      libresonic-main/src/main/java/org/libresonic/player/controller/StatusController.java
  73. 18
      libresonic-main/src/main/java/org/libresonic/player/dao/UserDao.java
  74. 133
      libresonic-main/src/main/java/org/libresonic/player/security/LibresonicUserDetailsContextMapper.java
  75. 23
      libresonic-main/src/main/java/org/libresonic/player/security/WebSecurityConfig.java
  76. 3
      libresonic-main/src/main/java/org/libresonic/player/service/PlaylistService.java
  77. 30
      libresonic-main/src/main/java/org/libresonic/player/service/SecurityService.java
  78. 1
      libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_en.properties
  79. 2
      libresonic-main/src/main/webapp/WEB-INF/jsp/advancedSettings.jsp
  80. 1
      libresonic-main/src/main/webapp/WEB-INF/jsp/albumMain.jsp
  81. 1
      libresonic-main/src/main/webapp/WEB-INF/jsp/artistMain.jsp
  82. 2
      libresonic-main/src/main/webapp/WEB-INF/jsp/changeCoverArt.jsp
  83. 1
      libresonic-main/src/main/webapp/WEB-INF/jsp/db.jsp
  84. 1
      libresonic-main/src/main/webapp/WEB-INF/jsp/dlnaSettings.jsp
  85. 10
      libresonic-main/src/main/webapp/WEB-INF/jsp/error.jsp
  86. 1
      libresonic-main/src/main/webapp/WEB-INF/jsp/importPlaylist.jsp
  87. 1
      libresonic-main/src/main/webapp/WEB-INF/jsp/internetRadioSettings.jsp
  88. 15
      libresonic-main/src/main/webapp/WEB-INF/jsp/more.jsp
  89. 1
      libresonic-main/src/main/webapp/WEB-INF/jsp/personalSettings.jsp
  90. 1
      libresonic-main/src/main/webapp/WEB-INF/jsp/recover.jsp
  91. 1
      libresonic-main/src/main/webapp/WEB-INF/jsp/shareSettings.jsp
  92. 1
      libresonic-main/src/main/webapp/WEB-INF/jsp/sonosSettings.jsp
  93. 1
      libresonic-main/src/main/webapp/WEB-INF/jsp/top.jsp
  94. 1
      libresonic-main/src/main/webapp/WEB-INF/jsp/transcodingSettings.jsp
  95. 12
      libresonic-main/src/test/java/org/libresonic/player/dao/UserDaoTestCase.java
  96. BIN
      libresonic-tools/ehcache-monitor/ehcache-monitor-kit-1.0.3-distribution.tar.gz
  97. BIN
      libresonic-tools/exe4j/exe4j_windows_4_5_1.exe
  98. BIN
      libresonic-tools/exe4j/exe4j_windows_4_5_1.zip
  99. BIN
      libresonic-tools/nsis/NSIS_Simple_Firewall_Plugin_1.20.zip
  100. BIN
      libresonic-tools/nsis/Processes.zip
  101. Some files were not shown because too many files have changed in this diff Show More

@ -7,9 +7,5 @@ cache:
- $HOME/.m2 - $HOME/.m2
install: install:
- sudo apt-get -qq update - sudo apt-get -qq update
- sudo apt-get -y install lintian fakeroot rpm python-rpm
- git clone https://github.com/rpm-software-management/rpmlint -o rpmlint-1.9
- sudo make -C rpmlint install
script: script:
- mvn -Pfull,rpm package install - mvn package install
- mvn -Pfull -pl libresonic-assembly assembly:single

@ -20,25 +20,32 @@ free.
## Libresonic configuration ## Libresonic configuration
A few settings can be tweaked in Libresonic's startup script or Tomcat A few settings should be tweaked via Spring Boot or Tomcat
configuration. configuration:
The reverse proxy will handle HTTPS connections, so there is no need for - Set the context path to `/libresonic`
Libresonic to handle them, which is why we set `httpsPort` to 0: - Set the correct address to listen to
- Set the correct port to listen to
libresonic.httpsPort=0 #### Spring Boot
Furthermore, the internal Libresonic server should only be accessible from the Add the following java args:
inside of the reverse proxy : we tell Libresonic to listen on the local IP
only:
libresonic.host=127.0.0.1 ```java -Dserver.port=4040 -Dserver.address=127.0.0.1 -Dserver.contextPath=/libresonic -jar libresonic.war```
libresonic.port=4040
Finally, if Libresonic should be accessible from a subdirectory, the context #### Tomcat
path must be set correctly: Modify your `<Connector>` with the proper address and port:
libresonic.contextPath=/libresonic ```
<Connector
port="4040"
address="127.0.0.1"
...
```
See [HTTP Connector](https://tomcat.apache.org/tomcat-7.0-doc/config/http.html) for further detail.
For the context path, tomcat will automatically deploy to a context path matching your war name. So if you're using
libresonic.war, you do not need to change anything.
## Reverse proxy configuration ## Reverse proxy configuration
@ -91,19 +98,39 @@ The following configuration works for Apache (without HTTPS):
### HAProxy ### HAProxy
The following configuration works for HAProxy (HTTPS only): The following configuration works for HAProxy 1.7 (HTTPS with HTTP
redirection):
```haproxy ```haproxy
frontend https frontend https
bind $server_public_ip$:443 ssl crt /etc/haproxy/ssl/$server_ssl_keys$.pem
# Let Libresonic handle all requests under /libresonic # Make sure that we are in HTTP mode so that we can rewrite headers
acl url_libresonic path_beg -i /libresonic mode http
use_backend libresonic-backend if url_libresonic
# Listen on the HTTPS and HTTP ports
bind :80
bind :443 ssl crt /etc/haproxy/cert_key.pem
# Some useful headers
option httpclose
option forwardfor
# Change default backend to libresonic backend if you don't have a web backend # HTTP: Redirect insecure requests to HTTPS
default_backend web-backend http-request redirect scheme https if !{ ssl_fc }
# HTTPS: Forward requests to the Libresonic backend
acl is_libresonic path_beg -i /libresonic
use_backend libresonic-backend if is_libresonic
backend libresonic-backend backend libresonic-backend
# Make sure that we are in HTTP mode so that we can rewrite headers
mode http
# Rewrite all redirects to use HTTPS, similar to what Nginx does in the
# proxy_redirect directive.
http-response replace-value Location ^http://(.*)$ https://\1
# Forward requests to Libresonic running on localhost on port 4040
server libresonic 127.0.0.1:4040 check server libresonic 127.0.0.1:4040 check
``` ```

@ -1,62 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>libresonic-assembly</artifactId>
<packaging>pom</packaging>
<name>Libresonic Assembly</name>
<parent>
<groupId>org.libresonic.player</groupId>
<artifactId>libresonic</artifactId>
<version>6.2.beta1.springboot</version>
</parent>
<dependencies>
<dependency>
<groupId>org.libresonic.player</groupId>
<artifactId>libresonic-main</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
</dependencies>
<build>
<finalName>libresonic-${project.version}</finalName>
<plugins>
<!-- Configuration of assembly plugin for creating the distributions. -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/war.xml</descriptor>
<descriptor>src/main/assembly/standalone.xml</descriptor>
<descriptor>src/main/assembly/src.xml</descriptor>
</descriptors>
</configuration>
</plugin>
<!-- Work-around since the target directory is not created automatically. -->
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>validate</phase>
<configuration>
<target>
<mkdir dir="target"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -1,56 +0,0 @@
<!-- Defines the set of files that should be included in the source distribution. -->
<assembly>
<id>src</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>..</directory>
<includes>
<include>pom.xml</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
<fileSet>
<directory>../repo</directory>
<outputDirectory>repo</outputDirectory>
</fileSet>
<fileSet>
<directory>../libresonic-main</directory>
<includes>
<include>src/**</include>
<include>pom.xml</include>
<include>target/classes/build_number.txt</include>
<include>LICENSE.TXT</include>
<include>README.TXT</include>
<include>Getting Started.html</include>
</includes>
<outputDirectory>libresonic-main</outputDirectory>
</fileSet>
<fileSet>
<directory>../libresonic-rest-api</directory>
<includes>
<include>src/**</include>
<include>pom.xml</include>
</includes>
<outputDirectory>libresonic-rest-api</outputDirectory>
</fileSet>
<fileSet>
<directory>../libresonic-sonos-api</directory>
<includes>
<include>src/**</include>
<include>pom.xml</include>
</includes>
<outputDirectory>libresonic-sonos-api</outputDirectory>
</fileSet>
</fileSets>
</assembly>

@ -1,43 +0,0 @@
<!-- Defines the set of files that should be included in the standalone distribution. -->
<assembly>
<id>standalone</id>
<formats>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>../libresonic-main</directory>
<outputDirectory/>
<includes>
<include>README.TXT</include>
<include>LICENSE.TXT</include>
<include>Getting Started.html</include>
</includes>
</fileSet>
<fileSet>
<directory>../libresonic-main/target</directory>
<outputDirectory/>
<includes>
<include>*.war</include>
</includes>
</fileSet>
<fileSet>
<directory>../libresonic-booter/target</directory>
<outputDirectory/>
<includes>
<include>libresonic-booter-jar-with-dependencies.jar</include>
</includes>
</fileSet>
<fileSet>
<directory>../libresonic-booter/src/main/script</directory>
<outputDirectory/>
<includes>
<include>libresonic.sh</include>
<include>libresonic.bat</include>
</includes>
<fileMode>0777</fileMode>
</fileSet>
</fileSets>
</assembly>

@ -1,27 +0,0 @@
<!-- Defines the set of files that should be included in the binary distribution. -->
<assembly>
<id>war</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>../libresonic-main</directory>
<outputDirectory></outputDirectory>
<includes>
<include>README.TXT</include>
<include>LICENSE.TXT</include>
<include>Getting Started.html</include>
</includes>
</fileSet>
<fileSet>
<directory>../libresonic-main/target</directory>
<outputDirectory></outputDirectory>
<includes>
<include>*.war</include>
</includes>
</fileSet>
</fileSets>
</assembly>

@ -1,98 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>libresonic-booter</artifactId>
<name>Libresonic Booter</name>
<parent>
<groupId>org.libresonic.player</groupId>
<artifactId>libresonic</artifactId>
<version>6.2.beta1.springboot</version>
</parent>
<dependencies>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>6.1.5</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-embedded</artifactId>
<version>6.1.5</version>
<exclusions>
<exclusion>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-2.0</artifactId>
<version>6.1.5</version>
<type>pom</type>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.jgoodies</groupId>
<artifactId>looks</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>com.jgoodies</groupId>
<artifactId>forms</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
<build>
<finalName>libresonic-booter</finalName>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifestFile>${basedir}/src/main/resources/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
<!-- Create executable jar file with all dependencies during 'package' phase. -->
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>attached</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -1,65 +0,0 @@
package org.libresonic.player.booter;
import java.util.Arrays;
import java.util.List;
import javax.swing.JOptionPane;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.libresonic.player.booter.agent.SettingsPanel;
import org.libresonic.player.booter.agent.LibresonicAgent;
/**
* Application entry point for Libresonic booter.
* <p/>
* Use command line argument "-agent" to start the Windows service monitoring agent,
* or "-mac" to start the Mac version of the deployer.
*
* @author Sindre Mehus
*/
public class Main {
public Main(String contextName, List<String> args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext" + contextName + ".xml");
if ("-agent".equals(contextName)) {
LibresonicAgent agent = (LibresonicAgent) context.getBean("agent");
SettingsPanel settingsPanel = (SettingsPanel) context.getBean("settingsPanel");
agent.setElevated(args.contains("-elevated"));
if (args.contains("-balloon")) {
agent.showTrayIconMessage();
}
if (args.contains("-stop")) {
agent.startOrStopService(false);
agent.showStatusPanel();
} else if (args.contains("-start")) {
agent.startOrStopService(true);
agent.showStatusPanel();
}
if (args.contains("-settings")) {
String[] settings = args.get(args.indexOf("-settings") + 1).split(",");
try {
agent.showSettingsPanel();
settingsPanel.saveSettings(Integer.valueOf(settings[0]), Integer.valueOf(settings[1]), Integer.valueOf(settings[2]), settings[3]);
settingsPanel.readValues();
} catch (Exception x) {
JOptionPane.showMessageDialog(settingsPanel, x.getMessage(), "Error", JOptionPane.WARNING_MESSAGE);
}
}
}
}
public static void main(String[] args) {
String context = "-deployer";
if (args.length > 0) {
context = args[0];
}
new Main(context, Arrays.asList(args));
}
}

@ -1,201 +0,0 @@
package org.libresonic.player.booter.agent;
import java.awt.Desktop;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import org.apache.commons.io.IOUtils;
import com.jgoodies.looks.plastic.PlasticXPLookAndFeel;
import org.libresonic.player.booter.deployer.DeploymentStatus;
import org.libresonic.player.booter.deployer.LibresonicDeployerService;
/**
* Responsible for deploying the Libresonic web app in
* the embedded Jetty container.
*
* @author Sindre Mehus
*/
public class LibresonicAgent {
private final List<LibresonicListener> listeners = new ArrayList<LibresonicListener>();
private final TrayController trayController;
private LibresonicFrame frame;
private final LibresonicDeployerService service;
private static final int POLL_INTERVAL_DEPLOYMENT_INFO_SECONDS = 5;
private static final int POLL_INTERVAL_SERVICE_STATUS_SECONDS = 5;
private String url;
private boolean serviceStatusPollingEnabled;
private boolean elevated;
public LibresonicAgent(LibresonicDeployerService service) {
this.service = service;
setLookAndFeel();
trayController = new TrayController(this);
startPolling();
}
public void setFrame(LibresonicFrame frame) {
this.frame = frame;
}
private void setLookAndFeel() {
// Set look-and-feel.
try {
UIManager.setLookAndFeel(new PlasticXPLookAndFeel());
} catch (Throwable x) {
System.err.println("Failed to set look-and-feel.\n" + x);
}
}
private void startPolling() {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
Runnable runnable = new Runnable() {
public void run() {
try {
notifyDeploymentInfo(service.getDeploymentInfo());
} catch (Throwable x) {
notifyDeploymentInfo(null);
}
}
};
executor.scheduleWithFixedDelay(runnable, 0, POLL_INTERVAL_DEPLOYMENT_INFO_SECONDS, TimeUnit.SECONDS);
runnable = new Runnable() {
public void run() {
if (serviceStatusPollingEnabled) {
try {
notifyServiceStatus(getServiceStatus());
} catch (Throwable x) {
notifyServiceStatus(null);
}
}
}
};
executor.scheduleWithFixedDelay(runnable, 0, POLL_INTERVAL_SERVICE_STATUS_SECONDS, TimeUnit.SECONDS);
}
private String getServiceStatus() throws Exception {
Process process = Runtime.getRuntime().exec("libresonic-service.exe -status");
return IOUtils.toString(process.getInputStream());
}
public void setServiceStatusPollingEnabled(boolean enabled) {
serviceStatusPollingEnabled = enabled;
}
public void startOrStopService(boolean start) {
try {
String cmd = "libresonic-service.exe " + (start ? "-start" : "-stop");
System.err.println("Executing: " + cmd);
Runtime.getRuntime().exec(cmd);
} catch (Exception x) {
x.printStackTrace();
}
}
/**
* If necessary, restart agent with elevated rights.
*/
public void checkElevation(String... args) {
if (isElevationNeeded() && !isElevated()) {
try {
List<String> command = new ArrayList<String>();
command.add("cmd");
command.add("/c");
command.add("libresonic-agent-elevated.exe");
command.addAll(Arrays.asList(args));
ProcessBuilder builder = new ProcessBuilder();
builder.command(command);
System.err.println("Executing: " + command + " with current dir: " + System.getProperty("user.dir"));
builder.start();
System.exit(0);
} catch (Exception x) {
JOptionPane.showMessageDialog(frame, "Failed to elevate Libresonic Control Panel. " + x, "Error", JOptionPane.WARNING_MESSAGE);
x.printStackTrace();
}
}
}
public void setElevated(boolean elevated) {
this.elevated = elevated;
}
private boolean isElevated() {
return elevated;
}
/**
* Returns whether UAC elevation is necessary (to start/stop services etc).
*/
private boolean isElevationNeeded() {
String osVersion = System.getProperty("os.version");
try {
int majorVersion = Integer.parseInt(osVersion.substring(0, osVersion.indexOf(".")));
// Elevation is necessary in Windows Vista (os.version=6.1) and later.
return majorVersion >= 6;
} catch (Exception x) {
System.err.println("Failed to resolve OS version from '" + osVersion + "'\n" + x);
return false;
}
}
public void addListener(LibresonicListener listener) {
listeners.add(listener);
}
private void notifyDeploymentInfo(DeploymentStatus status) {
if (status != null) {
url = status.getURL();
}
for (LibresonicListener listener : listeners) {
listener.notifyDeploymentStatus(status);
}
}
private void notifyServiceStatus(String status) {
for (LibresonicListener listener : listeners) {
listener.notifyServiceStatus(status);
}
}
public void showStatusPanel() {
frame.showStatusPanel();
}
public void showSettingsPanel() {
frame.showSettingsPanel();
}
public void showTrayIconMessage() {
trayController.showMessage();
}
public void exit() {
trayController.uninstallComponents();
System.exit(0);
}
public void openBrowser() {
try {
Desktop.getDesktop().browse(new URI(url));
} catch (Throwable x) {
x.printStackTrace();
}
}
}

@ -1,113 +0,0 @@
package org.libresonic.player.booter.agent;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.factories.ButtonBarFactory;
import org.libresonic.player.booter.Main;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* Frame that is activated by the tray icon. Contains a tabbed pane
* with status and settings panels.
*
* @author Sindre Mehus
*/
public class LibresonicFrame extends JFrame {
private final LibresonicAgent libresonicAgent;
private final StatusPanel statusPanel;
private final SettingsPanel settingsPanel;
private JTabbedPane tabbedPane;
private JButton closeButton;
public LibresonicFrame(LibresonicAgent libresonicAgent, StatusPanel statusPanel, SettingsPanel settingsPanel) {
super("Libresonic Control Panel");
this.libresonicAgent = libresonicAgent;
this.statusPanel = statusPanel;
this.settingsPanel = settingsPanel;
createComponents();
layoutComponents();
addBehaviour();
setupIcons();
pack();
centerComponent();
}
private void setupIcons() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
// Window.setIconImages() was added in Java 1.6. Since Libresonic only requires 1.5, we
// use reflection to invoke it.
try {
Method method = Window.class.getMethod("setIconImages", java.util.List.class);
java.util.List<Image> images = Arrays.asList(
toolkit.createImage(Main.class.getResource("/images/libresonic-16.png")),
toolkit.createImage(Main.class.getResource("/images/libresonic-32.png")),
toolkit.createImage(Main.class.getResource("/images/libresonic-512.png")));
method.invoke(this, images);
} catch (Throwable x) {
// Fallback to old method.
setIconImage(toolkit.createImage(Main.class.getResource("/images/libresonic-32.png")));
}
}
public void centerComponent() {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setLocation(screenSize.width / 2 - getWidth() / 2,
screenSize.height / 2 - getHeight() / 2);
}
private void createComponents() {
tabbedPane = new JTabbedPane();
closeButton = new JButton("Close");
}
private void layoutComponents() {
tabbedPane.add("Status", statusPanel);
tabbedPane.add("Settings", settingsPanel);
JPanel pane = (JPanel) getContentPane();
pane.setLayout(new BorderLayout(10, 10));
pane.add(tabbedPane, BorderLayout.CENTER);
pane.add(ButtonBarFactory.buildCloseBar(closeButton), BorderLayout.SOUTH);
pane.setBorder(Borders.TABBED_DIALOG_BORDER);
}
private void addBehaviour() {
closeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
});
}
@Override
public void setVisible(boolean b) {
super.setVisible(b);
libresonicAgent.setServiceStatusPollingEnabled(b);
}
public void showStatusPanel() {
settingsPanel.readValues();
tabbedPane.setSelectedComponent(statusPanel);
pack();
setVisible(true);
toFront();
}
public void showSettingsPanel() {
settingsPanel.readValues();
tabbedPane.setSelectedComponent(settingsPanel);
pack();
setVisible(true);
toFront();
}
}

@ -1,28 +0,0 @@
package org.libresonic.player.booter.agent;
import org.libresonic.player.booter.deployer.DeploymentStatus;
/**
* Callback interface implemented by GUI classes that wants to be notified when
* the state of the Libresonic deployment changes.
*
* @author Sindre Mehus
*/
public interface LibresonicListener {
/**
* Invoked when new information about the Libresonic deployment is available.
*
* @param deploymentStatus The new deployment status, or <code>null</code> if an
* error occurred while retrieving the status.
*/
void notifyDeploymentStatus(DeploymentStatus deploymentStatus);
/**
* Invoked when new information about the Libresonic Windows service is available.
*
* @param serviceStatus The new service status, or <code>null</code> if an
* error occurred while retrieving the status.
*/
void notifyServiceStatus(String serviceStatus);
}

@ -1,375 +0,0 @@
package org.libresonic.player.booter.agent;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.factories.ButtonBarFactory;
import com.jgoodies.forms.layout.FormLayout;
import org.libresonic.player.booter.deployer.DeploymentStatus;
import org.libresonic.player.booter.deployer.LibresonicDeployer;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.Format;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Panel displaying the settings of the Libresonic service.
*
* @author Sindre Mehus
*/
public class SettingsPanel extends JPanel implements LibresonicListener {
private static final Format INTEGER_FORMAT = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.UK));
private final LibresonicAgent libresonicAgent;
private JFormattedTextField portTextField;
private JCheckBox httpsPortCheckBox;
private JFormattedTextField httpsPortTextField;
private JComboBox contextPathComboBox;
private JFormattedTextField memoryTextField;
private JButton defaultButton;
private JButton saveButton;
public SettingsPanel(LibresonicAgent libresonicAgent) {
this.libresonicAgent = libresonicAgent;
createComponents();
configureComponents();
layoutComponents();
addBehaviour();
readValues();
libresonicAgent.addListener(this);
}
public void readValues() {
portTextField.setValue(getPortFromOptionsFile());
memoryTextField.setValue(getMemoryLimitFromOptionsFile());
contextPathComboBox.setSelectedItem(getContextPathFromOptionsFile());
int httpsPort = getHttpsPortFromOptionsFile();
boolean httpsEnabled = httpsPort != 0;
httpsPortTextField.setValue(httpsEnabled ? httpsPort : 4443);
httpsPortTextField.setEnabled(httpsEnabled);
httpsPortCheckBox.setSelected(httpsEnabled);
}
private int getHttpsPortFromOptionsFile() {
try {
String s = grep("-Dlibresonic.httpsPort=(\\d+)");
return Integer.parseInt(s);
} catch (Exception x) {
x.printStackTrace();
return LibresonicDeployer.DEFAULT_HTTPS_PORT;
}
}
private int getPortFromOptionsFile() {
try {
String s = grep("-Dlibresonic.port=(\\d+)");
return Integer.parseInt(s);
} catch (Exception x) {
x.printStackTrace();
return LibresonicDeployer.DEFAULT_PORT;
}
}
private int getMemoryLimitFromOptionsFile() {
try {
String s = grep("-Xmx(\\d+)m");
return Integer.parseInt(s);
} catch (Exception x) {
x.printStackTrace();
return LibresonicDeployer.DEFAULT_MEMORY_LIMIT;
}
}
private String getContextPathFromOptionsFile() {
try {
String s = grep("-Dlibresonic.contextPath=(.*)");
if (s == null) {
throw new NullPointerException();
}
return s;
} catch (Exception x) {
x.printStackTrace();
return LibresonicDeployer.DEFAULT_CONTEXT_PATH;
}
}
private void createComponents() {
portTextField = new JFormattedTextField(INTEGER_FORMAT);
httpsPortTextField = new JFormattedTextField(INTEGER_FORMAT);
httpsPortCheckBox = new JCheckBox("Enable https on port");
contextPathComboBox = new JComboBox();
memoryTextField = new JFormattedTextField(INTEGER_FORMAT);
defaultButton = new JButton("Restore defaults");
saveButton = new JButton("Save settings");
}
private void configureComponents() {
contextPathComboBox.setEditable(true);
contextPathComboBox.addItem("/");
contextPathComboBox.addItem("/libresonic");
contextPathComboBox.addItem("/music");
}
private void layoutComponents() {
FormLayout layout = new FormLayout("d, 6dlu, max(d;30dlu):grow");
DefaultFormBuilder builder = new DefaultFormBuilder(layout);
builder.append("Port number", portTextField);
builder.append(httpsPortCheckBox, httpsPortTextField);
builder.append("Memory limit (MB)", memoryTextField);
builder.append("Context path", contextPathComboBox);
setBorder(Borders.DIALOG_BORDER);
setLayout(new BorderLayout(12, 12));
add(builder.getPanel(), BorderLayout.CENTER);
add(ButtonBarFactory.buildCenteredBar(defaultButton, saveButton), BorderLayout.SOUTH);
}
private void addBehaviour() {
saveButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
libresonicAgent.checkElevation("-settings", getMemoryLimit() + "," + getPort() + "," + getHttpsPort() + "," + getContextPath());
saveSettings(getMemoryLimit(), getPort(), getHttpsPort(), getContextPath());
} catch (Exception x) {
JOptionPane.showMessageDialog(SettingsPanel.this, x.getMessage(), "Error", JOptionPane.WARNING_MESSAGE);
}
}
});
defaultButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
portTextField.setValue(LibresonicDeployer.DEFAULT_PORT);
httpsPortTextField.setValue(4443);
httpsPortTextField.setEnabled(false);
httpsPortCheckBox.setSelected(false);
memoryTextField.setValue(LibresonicDeployer.DEFAULT_MEMORY_LIMIT);
contextPathComboBox.setSelectedItem(LibresonicDeployer.DEFAULT_CONTEXT_PATH);
}
});
httpsPortCheckBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
httpsPortTextField.setEnabled(httpsPortCheckBox.isSelected());
}
});
}
private String getContextPath() throws SettingsException {
String contextPath = (String) contextPathComboBox.getSelectedItem();
if (contextPath.contains(" ") || !contextPath.startsWith("/")) {
throw new SettingsException("Please specify a valid context path.");
}
return contextPath;
}
private int getMemoryLimit() throws SettingsException {
int memoryLimit;
try {
memoryLimit = ((Number) memoryTextField.getValue()).intValue();
if (memoryLimit < 5) {
throw new Exception();
}
} catch (Exception x) {
throw new SettingsException("Please specify a valid memory limit.", x);
}
return memoryLimit;
}
private int getPort() throws SettingsException {
int port;
try {
port = ((Number) portTextField.getValue()).intValue();
if (port < 1 || port > 65535) {
throw new Exception();
}
} catch (Exception x) {
throw new SettingsException("Please specify a valid port number.", x);
}
return port;
}
private int getHttpsPort() throws SettingsException {
if (!httpsPortCheckBox.isSelected()) {
return 0;
}
int port;
try {
port = ((Number) httpsPortTextField.getValue()).intValue();
if (port < 1 || port > 65535) {
throw new Exception();
}
} catch (Exception x) {
throw new SettingsException("Please specify a valid https port number.", x);
}
return port;
}
public void saveSettings(int memoryLimit, int port, int httpsPort, String contextPath) throws SettingsException {
File file = getOptionsFile();
java.util.List<String> lines = readLines(file);
java.util.List<String> newLines = new ArrayList<String>();
boolean memoryLimitAdded = false;
boolean portAdded = false;
boolean httpsPortAdded = false;
boolean contextPathAdded = false;
for (String line : lines) {
if (line.startsWith("-Xmx")) {
newLines.add("-Xmx" + memoryLimit + "m");
memoryLimitAdded = true;
} else if (line.startsWith("-Dlibresonic.port=")) {
newLines.add("-Dlibresonic.port=" + port);
portAdded = true;
} else if (line.startsWith("-Dlibresonic.httpsPort=")) {
newLines.add("-Dlibresonic.httpsPort=" + httpsPort);
httpsPortAdded = true;
} else if (line.startsWith("-Dlibresonic.contextPath=")) {
newLines.add("-Dlibresonic.contextPath=" + contextPath);
contextPathAdded = true;
} else {
newLines.add(line);
}
}
if (!memoryLimitAdded) {
newLines.add("-Xmx" + memoryLimit + "m");
}
if (!portAdded) {
newLines.add("-Dlibresonic.port=" + port);
}
if (!httpsPortAdded) {
newLines.add("-Dlibresonic.httpsPort=" + httpsPort);
}
if (!contextPathAdded) {
newLines.add("-Dlibresonic.contextPath=" + contextPath);
}
writeLines(file, newLines);
JOptionPane.showMessageDialog(SettingsPanel.this,
"Please restart Libresonic for the new settings to take effect.",
"Settings changed", JOptionPane.INFORMATION_MESSAGE);
}
private File getOptionsFile() throws SettingsException {
File file = new File("libresonic-service.exe.vmoptions");
if (!file.isFile() || !file.exists()) {
throw new SettingsException("File " + file.getAbsolutePath() + " not found.");
}
return file;
}
private List<String> readLines(File file) throws SettingsException {
List<String> lines = new ArrayList<String>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
lines.add(line);
}
return lines;
} catch (IOException x) {
throw new SettingsException("Failed to read from file " + file.getAbsolutePath(), x);
} finally {
closeQuietly(reader);
}
}
private void writeLines(File file, List<String> lines) throws SettingsException {
PrintWriter writer = null;
try {
writer = new PrintWriter(new FileWriter(file));
for (String line : lines) {
writer.println(line);
}
} catch (IOException x) {
throw new SettingsException("Failed to write to file " + file.getAbsolutePath(), x);
} finally {
closeQuietly(writer);
}
}
private String grep(String regexp) throws SettingsException {
Pattern pattern = Pattern.compile(regexp);
File file = getOptionsFile();
for (String line : readLines(file)) {
Matcher matcher = pattern.matcher(line);
if (matcher.matches()) {
return matcher.group(1);
}
}
return null;
}
private void closeQuietly(Reader reader) {
if (reader == null) {
return;
}
try {
reader.close();
} catch (IOException x) {
// Intentionally ignored.
}
}
private void closeQuietly(Writer writer) {
if (writer == null) {
return;
}
try {
writer.close();
} catch (IOException x) {
// Intentionally ignored.
}
}
public void notifyDeploymentStatus(DeploymentStatus deploymentStatus) {
// Nothing here yet.
}
public void notifyServiceStatus(String serviceStatus) {
// Nothing here yet.
}
public static class SettingsException extends Exception {
public SettingsException(String message, Throwable cause) {
super(message, cause);
}
public SettingsException(String message) {
this(message, null);
}
@Override
public String getMessage() {
if (getCause() == null || getCause().getMessage() == null) {
return super.getMessage();
}
return super.getMessage() + " " + getCause().getMessage();
}
}
}

@ -1,116 +0,0 @@
package org.libresonic.player.booter.agent;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.factories.ButtonBarFactory;
import com.jgoodies.forms.layout.FormLayout;
import org.libresonic.player.booter.deployer.DeploymentStatus;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.util.Locale;
/**
* Panel displaying the status of the Libresonic service.
*
* @author Sindre Mehus
*/
public class StatusPanel extends JPanel implements LibresonicListener {
private static final DateFormat DATE_FORMAT = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.US);
private final LibresonicAgent libresonicAgent;
private JTextField statusTextField;
private JTextField startedTextField;
private JTextField memoryTextField;
private JTextArea errorTextField;
private JButton startButton;
private JButton stopButton;
private JButton urlButton;
public StatusPanel(LibresonicAgent libresonicAgent) {
this.libresonicAgent = libresonicAgent;
createComponents();
configureComponents();
layoutComponents();
addBehaviour();
libresonicAgent.addListener(this);
}
private void createComponents() {
statusTextField = new JTextField();
startedTextField = new JTextField();
memoryTextField = new JTextField();
errorTextField = new JTextArea(3, 24);
startButton = new JButton("Start");
stopButton = new JButton("Stop");
urlButton = new JButton();
}
private void configureComponents() {
statusTextField.setEditable(false);
startedTextField.setEditable(false);
memoryTextField.setEditable(false);
errorTextField.setEditable(false);
errorTextField.setLineWrap(true);
errorTextField.setBorder(startedTextField.getBorder());
urlButton.setBorderPainted(false);
urlButton.setContentAreaFilled(false);
urlButton.setForeground(Color.BLUE.darker());
urlButton.setHorizontalAlignment(SwingConstants.LEFT);
}
private void layoutComponents() {
JPanel buttons = ButtonBarFactory.buildRightAlignedBar(startButton, stopButton);
FormLayout layout = new FormLayout("right:d, 6dlu, max(d;30dlu):grow");
DefaultFormBuilder builder = new DefaultFormBuilder(layout, this);
builder.append("Service status", statusTextField);
builder.append("", buttons);
builder.appendParagraphGapRow();
builder.nextRow();
builder.append("Started on", startedTextField);
builder.append("Memory used", memoryTextField);
builder.append("Error message", errorTextField);
builder.append("Server address", urlButton);
setBorder(Borders.DIALOG_BORDER);
}
private void addBehaviour() {
urlButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
libresonicAgent.openBrowser();
}
});
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
libresonicAgent.checkElevation("-start");
libresonicAgent.startOrStopService(true);
}
});
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
libresonicAgent.checkElevation("-stop");
libresonicAgent.startOrStopService(false);
}
});
}
public void notifyDeploymentStatus(DeploymentStatus status) {
startedTextField.setText(status == null ? null : DATE_FORMAT.format(status.getStartTime()));
memoryTextField.setText(status == null ? null : status.getMemoryUsed() + " MB");
errorTextField.setText(status == null ? null : status.getErrorMessage());
urlButton.setText(status == null ? null : status.getURL());
}
public void notifyServiceStatus(String serviceStatus) {
statusTextField.setText(serviceStatus);
}
}

@ -1,125 +0,0 @@
package org.libresonic.player.booter.agent;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.net.URL;
import javax.swing.AbstractAction;
import javax.swing.Action;
import org.libresonic.player.booter.deployer.DeploymentStatus;
/**
* Controls the Libresonic tray icon.
*
* @author Sindre Mehus
*/
public class TrayController implements LibresonicListener {
private final LibresonicAgent libresonicAgent;
private TrayIcon trayIcon;
private Action openAction;
private Action controlPanelAction;
private Action hideAction;
private Image startedImage;
private Image stoppedImage;
public TrayController(LibresonicAgent libresonicAgent) {
this.libresonicAgent = libresonicAgent;
try {
createActions();
createComponents();
addBehaviour();
installComponents();
libresonicAgent.addListener(this);
} catch (Throwable x) {
System.err.println("Disabling tray support.");
}
}
public void showMessage() {
trayIcon.displayMessage("Libresonic", "Libresonic is now running. Click this balloon to get started.",
TrayIcon.MessageType.INFO);
}
private void createActions() {
openAction = new AbstractAction("Open Libresonic in Browser") {
public void actionPerformed(ActionEvent e) {
libresonicAgent.openBrowser();
}
};
controlPanelAction = new AbstractAction("Libresonic Control Panel") {
public void actionPerformed(ActionEvent e) {
libresonicAgent.showStatusPanel();
}
};
hideAction = new AbstractAction("Hide Tray Icon") {
public void actionPerformed(ActionEvent e) {
libresonicAgent.exit();
}
};
}
private void createComponents() {
startedImage = createImage("/images/libresonic-started-16.png");
stoppedImage = createImage("/images/libresonic-stopped-16.png");
PopupMenu menu = new PopupMenu();
menu.add(createMenuItem(openAction));
menu.add(createMenuItem(controlPanelAction));
menu.addSeparator();
menu.add(createMenuItem(hideAction));
trayIcon = new TrayIcon(stoppedImage, "Libresonic Music Streamer", menu);
}
private Image createImage(String resourceName) {
URL url = getClass().getResource(resourceName);
return Toolkit.getDefaultToolkit().createImage(url);
}
private MenuItem createMenuItem(Action action) {
MenuItem menuItem = new MenuItem((String) action.getValue(Action.NAME));
menuItem.addActionListener(action);
return menuItem;
}
private void addBehaviour() {
trayIcon.addActionListener(controlPanelAction);
}
private void installComponents() throws Throwable {
SystemTray.getSystemTray().add(trayIcon);
}
public void uninstallComponents() {
try {
SystemTray.getSystemTray().remove(trayIcon);
} catch (Throwable x) {
System.err.println("Disabling tray support.");
}
}
private void setTrayImage(Image image) {
if (trayIcon.getImage() != image) {
trayIcon.setImage(image);
}
}
public void notifyDeploymentStatus(DeploymentStatus deploymentStatus) {
setTrayImage(deploymentStatus == null ? stoppedImage : startedImage);
}
public void notifyServiceStatus(String serviceStatus) {
// Nothing here, but could potentially change tray icon and menu.
}
}

@ -1,44 +0,0 @@
package org.libresonic.player.booter.deployer;
import java.util.Date;
import java.io.Serializable;
/**
* @author Sindre Mehus
*/
public class DeploymentStatus implements Serializable {
private final Date startTime;
private final String url;
private final String httpsUrl;
private final int memoryUsed;
private final String errorMessage;
public DeploymentStatus(Date startTime, String url, String httpsUrl, int memoryUsed, String errorMessage) {
this.startTime = startTime;
this.url = url;
this.httpsUrl = httpsUrl;
this.memoryUsed = memoryUsed;
this.errorMessage = errorMessage;
}
public String getURL() {
return url;
}
public String getHttpsUrl() {
return httpsUrl;
}
public Date getStartTime() {
return startTime;
}
public int getMemoryUsed() {
return memoryUsed;
}
public String getErrorMessage() {
return errorMessage;
}
}

@ -1,338 +0,0 @@
package org.libresonic.player.booter.deployer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.net.BindException;
import java.util.Date;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import org.apache.commons.io.IOUtils;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.security.Constraint;
import org.mortbay.jetty.security.ConstraintMapping;
import org.mortbay.jetty.security.SslSocketConnector;
import org.mortbay.jetty.webapp.WebAppContext;
/**
* Responsible for deploying the Libresonic web app in
* the embedded Jetty container.
* <p/>
* The following system properties may be used to customize the behaviour:
* <ul>
* <li><code>libresonic.contextPath</code> - The context path at which Libresonic is deployed. Default "/".</li>
* <li><code>libresonic.port</code> - The port Libresonic will listen to. Default 4040.</li>
* <li><code>libresonic.httpsPort</code> - The port Libresonic will listen to for HTTPS. Default 0, which disables HTTPS.</li>
* <li><code>libresonic.war</code> - Libresonic WAR file, or exploded directory. Default "libresonic.war".</li>
* <li><code>libresonic.createLinkFile</code> - If set to "true", a Libresonic.url file is created in the working directory.</li>
* <li><code>libresonic.ssl.keystore</code> - Path to an alternate SSL keystore.</li>
* <li><code>libresonic.ssl.password</code> - Password of the alternate SSL keystore.</li>
* </ul>
*
* @author Sindre Mehus
*/
public class LibresonicDeployer implements LibresonicDeployerService {
public static final String DEFAULT_HOST = "0.0.0.0";
public static final int DEFAULT_PORT = 4040;
public static final int DEFAULT_HTTPS_PORT = 0;
public static final int DEFAULT_MEMORY_LIMIT = 150;
public static final String DEFAULT_CONTEXT_PATH = "/";
public static final String DEFAULT_WAR = "libresonic.war";
private static final int MAX_IDLE_TIME_MILLIS = 7 * 24 * 60 * 60 * 1000; // One week.
private static final int HEADER_BUFFER_SIZE = 64 * 1024;
// Libresonic home directory.
private static final File LIBRESONIC_HOME_WINDOWS = new File("c:/libresonic");
private static final File LIBRESONIC_HOME_OTHER = new File("/var/libresonic");
private Throwable exception;
private File libresonicHome;
private final Date startTime;
public LibresonicDeployer() {
// Enable shutdown hook for Ehcache.
System.setProperty("net.sf.ehcache.enableShutdownHook", "true");
startTime = new Date();
createLinkFile();
deployWebApp();
}
private void createLinkFile() {
if ("true".equals(System.getProperty("libresonic.createLinkFile"))) {
Writer writer = null;
try {
writer = new FileWriter("libresonic.url");
writer.append("[InternetShortcut]");
writer.append(System.getProperty("line.separator"));
writer.append("URL=").append(getUrl());
writer.flush();
} catch (Throwable x) {
System.err.println("Failed to create libresonic.url.");
x.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException x) {
// Ignored
}
}
}
}
}
private void deployWebApp() {
try {
Server server = new Server();
SelectChannelConnector connector = new SelectChannelConnector();
connector.setMaxIdleTime(MAX_IDLE_TIME_MILLIS);
connector.setHeaderBufferSize(HEADER_BUFFER_SIZE);
connector.setHost(getHost());
connector.setPort(getPort());
if (isHttpsEnabled()) {
connector.setConfidentialPort(getHttpsPort());
}
server.addConnector(connector);
if (isHttpsEnabled()) {
SslSocketConnector sslConnector = new SslSocketConnector();
sslConnector.setMaxIdleTime(MAX_IDLE_TIME_MILLIS);
sslConnector.setHeaderBufferSize(HEADER_BUFFER_SIZE);
sslConnector.setHost(getHost());
sslConnector.setPort(getHttpsPort());
sslConnector.setKeystore(System.getProperty("libresonic.ssl.keystore", getClass().getResource("/libresonic.keystore").toExternalForm()));
sslConnector.setPassword(System.getProperty("libresonic.ssl.password", "libresonic"));
server.addConnector(sslConnector);
}
WebAppContext context = new WebAppContext();
context.setTempDirectory(getJettyDirectory());
context.setContextPath(getContextPath());
context.setWar(getWar());
context.setOverrideDescriptor("/web-jetty.xml");
if (isHttpsEnabled()) {
// Allow non-https for streaming and cover art (for Chromecast, UPnP, Sonos etc)
context.getSecurityHandler().setConstraintMappings(new ConstraintMapping[]{
createConstraintMapping("/stream", Constraint.DC_NONE),
createConstraintMapping("/coverArt.view", Constraint.DC_NONE),
createConstraintMapping("/ws/*", Constraint.DC_NONE),
createConstraintMapping("/sonos/*", Constraint.DC_NONE),
createConstraintMapping("/", Constraint.DC_CONFIDENTIAL)
});
}
server.addHandler(context);
server.start();
System.err.println("Libresonic running on: " + getUrl());
if (isHttpsEnabled()) {
System.err.println(" and: " + getHttpsUrl());
}
} catch (Throwable x) {
x.printStackTrace();
exception = x;
}
}
private ConstraintMapping createConstraintMapping(String pathSpec, int dataConstraint) {
ConstraintMapping constraintMapping = new ConstraintMapping();
Constraint constraint = new Constraint();
constraint.setDataConstraint(dataConstraint);
constraintMapping.setPathSpec(pathSpec);
constraintMapping.setConstraint(constraint);
return constraintMapping;
}
private File getJettyDirectory() {
File dir = new File(getLibresonicHome(), "jetty");
String buildNumber = getLibresonicBuildNumber();
if (buildNumber != null) {
dir = new File(dir, buildNumber);
}
System.err.println("Extracting webapp to " + dir);
if (!dir.exists() && !dir.mkdirs()) {
System.err.println("Failed to create directory " + dir);
}
return dir;
}
private String getLibresonicBuildNumber() {
File war = new File(getWar());
InputStream in = null;
try {
if (war.isFile()) {
JarFile jar = new JarFile(war);
ZipEntry entry = jar.getEntry("WEB-INF\\classes\\build_number.txt");
if (entry == null) {
entry = jar.getEntry("WEB-INF/classes/build_number.txt");
}
in = jar.getInputStream(entry);
} else {
in = new FileInputStream(war.getPath() + "/WEB-INF/classes/build_number.txt");
}
return IOUtils.toString(in);
} catch (Exception x) {
System.err.println("Failed to resolve build number from WAR " + war + ": " + x);
return null;
} finally {
IOUtils.closeQuietly(in);
}
}
private String getContextPath() {
return System.getProperty("libresonic.contextPath", DEFAULT_CONTEXT_PATH);
}
private String getWar() {
String war = System.getProperty("libresonic.war");
if (war == null) {
war = DEFAULT_WAR;
}
File file = new File(war);
if (file.exists()) {
System.err.println("Using WAR file: " + file.getAbsolutePath());
} else {
System.err.println("Error: WAR file not found: " + file.getAbsolutePath());
}
return war;
}
private String getHost() {
return System.getProperty("libresonic.host", DEFAULT_HOST);
}
private int getPort() {
int port = DEFAULT_PORT;
String portString = System.getProperty("libresonic.port");
if (portString != null) {
port = Integer.parseInt(portString);
}
// Also set it so that the webapp can read it.
System.setProperty("libresonic.port", String.valueOf(port));
return port;
}
private int getHttpsPort() {
int port = DEFAULT_HTTPS_PORT;
String portString = System.getProperty("libresonic.httpsPort");
if (portString != null) {
port = Integer.parseInt(portString);
}
// Also set it so that the webapp can read it.
System.setProperty("libresonic.httpsPort", String.valueOf(port));
return port;
}
private boolean isHttpsEnabled() {
return getHttpsPort() > 0;
}
public String getErrorMessage() {
if (exception == null) {
return null;
}
if (exception instanceof BindException) {
return "Address already in use. Please change port number.";
}
return exception.toString();
}
public int getMemoryUsed() {
long freeBytes = Runtime.getRuntime().freeMemory();
long totalBytes = Runtime.getRuntime().totalMemory();
long usedBytes = totalBytes - freeBytes;
return (int) Math.round(usedBytes / 1024.0 / 1024.0);
}
private String getUrl() {
String host = DEFAULT_HOST.equals(getHost()) ? "localhost" : getHost();
StringBuilder url = new StringBuilder("http://").append(host);
if (getPort() != 80) {
url.append(":").append(getPort());
}
url.append(getContextPath());
return url.toString();
}
private String getHttpsUrl() {
if (!isHttpsEnabled()) {
return null;
}
String host = DEFAULT_HOST.equals(getHost()) ? "localhost" : getHost();
StringBuilder url = new StringBuilder("https://").append(host);
if (getHttpsPort() != 443) {
url.append(":").append(getHttpsPort());
}
url.append(getContextPath());
return url.toString();
}
/**
* Returns the Libresonic home directory.
*
* @return The Libresonic home directory, if it exists.
* @throws RuntimeException If directory doesn't exist.
*/
private File getLibresonicHome() {
if (libresonicHome != null) {
return libresonicHome;
}
File home;
String overrideHome = System.getProperty("libresonic.home");
if (overrideHome != null) {
home = new File(overrideHome);
} else {
boolean isWindows = System.getProperty("os.name", "Windows").toLowerCase().startsWith("windows");
home = isWindows ? LIBRESONIC_HOME_WINDOWS : LIBRESONIC_HOME_OTHER;
}
// Attempt to create home directory if it doesn't exist.
if (!home.exists() || !home.isDirectory()) {
boolean success = home.mkdirs();
if (success) {
libresonicHome = home;
} else {
String message = "The directory " + home + " does not exist. Please create it and make it writable. " +
"(You can override the directory location by specifying -Dlibresonic.home=... when " +
"starting the servlet container.)";
System.err.println("ERROR: " + message);
}
} else {
libresonicHome = home;
}
return home;
}
public DeploymentStatus getDeploymentInfo() {
return new DeploymentStatus(startTime, getUrl(), getHttpsUrl(), getMemoryUsed(), getErrorMessage());
}
}

@ -1,17 +0,0 @@
package org.libresonic.player.booter.deployer;
/**
* RMI interface implemented by the Libresonic deployer and used by the agent.
*
* @author Sindre Mehus
*/
public interface LibresonicDeployerService {
/**
* Returns information about the Libresonic deployment, such
* as URL, memory consumption, start time etc.
*
* @return Deployment information.
*/
DeploymentStatus getDeploymentInfo();
}

@ -1,89 +0,0 @@
package org.libresonic.player.booter.mac;
import org.libresonic.player.booter.deployer.LibresonicDeployerService;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.net.URL;
import java.net.URI;
/**
* Controller for the Mac booter.
*
* @author Sindre Mehus
*/
public class LibresonicController {
private final LibresonicDeployerService deployer;
private final LibresonicFrame frame;
private Action openAction;
private Action controlPanelAction;
private Action quitAction;
public LibresonicController(LibresonicDeployerService deployer, LibresonicFrame frame) {
this.deployer = deployer;
this.frame = frame;
createActions();
createComponents();
}
private void createActions() {
openAction = new AbstractAction("Open Libresonic Web Page") {
public void actionPerformed(ActionEvent e) {
openBrowser();
}
};
controlPanelAction = new AbstractAction("Libresonic Control Panel") {
public void actionPerformed(ActionEvent e) {
frame.setActive(false);
frame.setActive(true);
}
};
quitAction = new AbstractAction("Quit Libresonic") {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
};
}
private void createComponents() {
PopupMenu menu = new PopupMenu();
menu.add(createMenuItem(openAction));
menu.add(createMenuItem(controlPanelAction));
menu.addSeparator();
menu.add(createMenuItem(quitAction));
URL url = getClass().getResource("/images/libresonic-21.png");
Image image = Toolkit.getDefaultToolkit().createImage(url);
TrayIcon trayIcon = new TrayIcon(image, "Libresonic Music Streamer", menu);
trayIcon.setImageAutoSize(false);
try {
SystemTray.getSystemTray().add(trayIcon);
} catch (Throwable x) {
System.err.println("Failed to add tray icon.");
}
}
private MenuItem createMenuItem(Action action) {
MenuItem menuItem = new MenuItem((String) action.getValue(Action.NAME));
menuItem.addActionListener(action);
return menuItem;
}
private void openBrowser() {
String url = deployer.getDeploymentInfo().getURL();
if (url == null) {
return;
}
try {
Desktop.getDesktop().browse(new URI(url));
} catch (Throwable x) {
x.printStackTrace();
}
}
}

@ -1,82 +0,0 @@
package org.libresonic.player.booter.mac;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.factories.ButtonBarFactory;
import org.libresonic.player.booter.Main;
import org.libresonic.player.booter.deployer.LibresonicDeployerService;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
/**
* Frame with Libresonic status. Used on Mac installs.
*
* @author Sindre Mehus
*/
public class LibresonicFrame extends JFrame {
private final LibresonicDeployerService deployer;
private StatusPanel statusPanel;
private JButton hideButton;
private JButton exitButton;
public LibresonicFrame(LibresonicDeployerService deployer) {
super("Libresonic");
this.deployer = deployer;
createComponents();
layoutComponents();
addBehaviour();
URL url = Main.class.getResource("/images/libresonic-512.png");
setIconImage(Toolkit.getDefaultToolkit().createImage(url));
}
public void setActive(boolean active) {
if (active) {
pack();
centerComponent();
setVisible(true);
toFront();
} else {
dispose();
}
}
private void centerComponent() {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setLocation(screenSize.width / 2 - getWidth() / 2,
screenSize.height / 2 - getHeight() / 2);
}
private void createComponents() {
statusPanel = new StatusPanel(deployer);
hideButton = new JButton("Hide");
exitButton = new JButton("Exit");
}
private void layoutComponents() {
JPanel pane = (JPanel) getContentPane();
pane.setLayout(new BorderLayout(10, 10));
pane.add(statusPanel, BorderLayout.CENTER);
pane.add(ButtonBarFactory.buildRightAlignedBar(hideButton, exitButton), BorderLayout.SOUTH);
pane.setBorder(Borders.DIALOG_BORDER);
}
private void addBehaviour() {
hideButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setActive(false);
}
});
exitButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
}
}

@ -1,115 +0,0 @@
package org.libresonic.player.booter.mac;
import java.awt.Color;
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URI;
import java.text.DateFormat;
import java.util.Locale;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.Timer;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.layout.FormLayout;
import org.libresonic.player.booter.deployer.DeploymentStatus;
import org.libresonic.player.booter.deployer.LibresonicDeployerService;
/**
* Panel displaying the status of the Libresonic service.
*
* @author Sindre Mehus
*/
public class StatusPanel extends JPanel {
private static final DateFormat DATE_FORMAT = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.US);
private final LibresonicDeployerService deployer;
private JTextField startedTextField;
private JTextField memoryTextField;
private JTextArea errorTextField;
private JButton urlButton;
public StatusPanel(LibresonicDeployerService deployer) {
this.deployer = deployer;
createComponents();
configureComponents();
layoutComponents();
addBehaviour();
}
private void createComponents() {
startedTextField = new JTextField();
memoryTextField = new JTextField();
errorTextField = new JTextArea(3, 24);
urlButton = new JButton();
}
private void configureComponents() {
startedTextField.setEditable(false);
memoryTextField.setEditable(false);
errorTextField.setEditable(false);
errorTextField.setLineWrap(true);
errorTextField.setBorder(startedTextField.getBorder());
urlButton.setBorderPainted(false);
urlButton.setContentAreaFilled(false);
urlButton.setForeground(Color.BLUE.darker());
urlButton.setHorizontalAlignment(SwingConstants.LEFT);
}
private void layoutComponents() {
FormLayout layout = new FormLayout("right:d, 6dlu, max(d;30dlu):grow");
DefaultFormBuilder builder = new DefaultFormBuilder(layout, this);
builder.append("Started on", startedTextField);
builder.append("Memory used", memoryTextField);
builder.append("Error message", errorTextField);
builder.append("Server address", urlButton);
setBorder(Borders.DIALOG_BORDER);
}
private void addBehaviour() {
urlButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
openBrowser();
}
});
Timer timer = new Timer(3000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
updateStatus(deployer.getDeploymentInfo());
}
});
updateStatus(deployer.getDeploymentInfo());
timer.start();
}
private void openBrowser() {
String url = urlButton.getText();
if (url == null) {
return;
}
try {
Desktop.getDesktop().browse(new URI(url));
} catch (Throwable x) {
x.printStackTrace();
}
}
private void updateStatus(DeploymentStatus status) {
startedTextField.setText(status == null ? null : DATE_FORMAT.format(status.getStartTime()));
memoryTextField.setText(status == null ? null : status.getMemoryUsed() + " MB");
errorTextField.setText(status == null ? null : status.getErrorMessage());
urlButton.setText(status == null ? null : status.getURL());
}
}

@ -1,2 +0,0 @@
Manifest-Version: 1.0
Main-Class: org.libresonic.player.booter.Main

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="service" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://localhost:9412/LibresonicDeployerService"/>
<property name="serviceInterface" value="org.libresonic.player.booter.deployer.LibresonicDeployerService"/>
<property name="lookupStubOnStartup" value="false"/>
<property name="refreshStubOnConnectFailure" value="true"/>
</bean>
<bean id="agent" class="org.libresonic.player.booter.agent.LibresonicAgent">
<constructor-arg ref="service"/>
<property name="frame" ref="frame"/>
</bean>
<bean id="frame" class="org.libresonic.player.booter.agent.LibresonicFrame">
<constructor-arg ref="agent"/>
<constructor-arg ref="statusPanel"/>
<constructor-arg ref="settingsPanel"/>
</bean>
<bean id="settingsPanel" class="org.libresonic.player.booter.agent.SettingsPanel">
<constructor-arg ref="agent"/>
</bean>
<bean id="statusPanel" class="org.libresonic.player.booter.agent.StatusPanel">
<constructor-arg ref="agent"/>
</bean>
</beans>

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="service" class="org.libresonic.player.booter.deployer.LibresonicDeployer"/>
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="serviceName" value="LibresonicDeployerService"/>
<property name="service" ref="service"/>
<property name="serviceInterface" value="org.libresonic.player.booter.deployer.LibresonicDeployerService"/>
<property name="registryPort" value="9412"/>
</bean>
</beans>

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="deployer" class="org.libresonic.player.booter.deployer.LibresonicDeployer"/>
<bean id="frame" class="org.libresonic.player.booter.mac.LibresonicFrame">
<constructor-arg ref="deployer"/>
</bean>
<bean id="controller" class="org.libresonic.player.booter.mac.LibresonicController">
<constructor-arg ref="deployer"/>
<constructor-arg ref="frame"/>
</bean>
</beans>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 734 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 673 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 771 B

@ -1,39 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
~ This file is part of Libresonic.
~
~ Libresonic 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.
~
~ Libresonic 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 Libresonic. If not, see <http://www.gnu.org/licenses/>.
~
~ Copyright 2014 (C) Sindre Mehus
-->
<web-app id="libresonic" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<!--Enable compression for XML, JSON and JSONP in the REST API-->
<filter>
<filter-name>GzipFilter</filter-name>
<filter-class>org.mortbay.servlet.GzipFilter</filter-class>
<init-param>
<param-name>mimeTypes</param-name>
<param-value>text/xml,application/json,text/javascript</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>GzipFilter</filter-name>
<url-pattern>/rest/*</url-pattern>
</filter-mapping>
</web-app>

@ -1,24 +0,0 @@
@echo off
REM The directory where Libresonic will create files. Make sure it is writable.
set LIBRESONIC_HOME=c:\libresonic
REM The host name or IP address on which to bind Libresonic. Only relevant if you have
REM multiple network interfaces and want to make Libresonic available on only one of them.
REM The default value 0.0.0.0 will bind Libresonic to all available network interfaces.
set LIBRESONIC_HOST=0.0.0.0
REM The port on which Libresonic will listen for incoming HTTP traffic.
set LIBRESONIC_PORT=4040
REM The port on which Libresonic will listen for incoming HTTPS traffic (0 to disable).
set LIBRESONIC_HTTPS_PORT=0
REM The context path (i.e., the last part of the Libresonic URL). Typically "/" or "/libresonic".
set LIBRESONIC_CONTEXT_PATH=/
REM The memory limit (max Java heap size) in megabytes.
set MAX_MEMORY=150
java -Xmx%MAX_MEMORY%m -Dlibresonic.home=%LIBRESONIC_HOME% -Dlibresonic.host=%LIBRESONIC_HOST% -Dlibresonic.port=%LIBRESONIC_PORT% -Dlibresonic.httpsPort=%LIBRESONIC_HTTPS_PORT% -Dlibresonic.contextPath=%LIBRESONIC_CONTEXT_PATH% -jar libresonic-booter-jar-with-dependencies.jar

@ -1,134 +0,0 @@
#!/bin/sh
###################################################################################
# Shell script for starting Libresonic. See http://libresonic.org.
#
# Author: Sindre Mehus
###################################################################################
LIBRESONIC_HOME=/var/libresonic
LIBRESONIC_HOST=0.0.0.0
LIBRESONIC_PORT=4040
LIBRESONIC_HTTPS_PORT=0
LIBRESONIC_CONTEXT_PATH=/
LIBRESONIC_MAX_MEMORY=150
LIBRESONIC_PIDFILE=
LIBRESONIC_DEFAULT_MUSIC_FOLDER=/var/music
LIBRESONIC_DEFAULT_PODCAST_FOLDER=/var/music/Podcast
LIBRESONIC_DEFAULT_PLAYLIST_FOLDER=/var/playlists
quiet=0
usage() {
echo "Usage: libresonic.sh [options]"
echo " --help This small usage guide."
echo " --home=DIR The directory where Libresonic will create files."
echo " Make sure it is writable. Default: /var/libresonic"
echo " --host=HOST The host name or IP address on which to bind Libresonic."
echo " Only relevant if you have multiple network interfaces and want"
echo " to make Libresonic available on only one of them. The default value"
echo " will bind Libresonic to all available network interfaces. Default: 0.0.0.0"
echo " --port=PORT The port on which Libresonic will listen for"
echo " incoming HTTP traffic. Default: 4040"
echo " --https-port=PORT The port on which Libresonic will listen for"
echo " incoming HTTPS traffic. Default: 0 (disabled)"
echo " --context-path=PATH The context path, i.e., the last part of the Libresonic"
echo " URL. Typically '/' or '/libresonic'. Default '/'"
echo " --max-memory=MB The memory limit (max Java heap size) in megabytes."
echo " Default: 100"
echo " --pidfile=PIDFILE Write PID to this file. Default not created."
echo " --quiet Don't print anything to standard out. Default false."
echo " --default-music-folder=DIR Configure Libresonic to use this folder for music. This option "
echo " only has effect the first time Libresonic is started. Default '/var/music'"
echo " --default-podcast-folder=DIR Configure Libresonic to use this folder for Podcasts. This option "
echo " only has effect the first time Libresonic is started. Default '/var/music/Podcast'"
echo " --default-playlist-folder=DIR Configure Libresonic to use this folder for playlists. This option "
echo " only has effect the first time Libresonic is started. Default '/var/playlists'"
exit 1
}
# Parse arguments.
while [ $# -ge 1 ]; do
case $1 in
--help)
usage
;;
--home=?*)
LIBRESONIC_HOME=${1#--home=}
;;
--host=?*)
LIBRESONIC_HOST=${1#--host=}
;;
--port=?*)
LIBRESONIC_PORT=${1#--port=}
;;
--https-port=?*)
LIBRESONIC_HTTPS_PORT=${1#--https-port=}
;;
--context-path=?*)
LIBRESONIC_CONTEXT_PATH=${1#--context-path=}
;;
--max-memory=?*)
LIBRESONIC_MAX_MEMORY=${1#--max-memory=}
;;
--pidfile=?*)
LIBRESONIC_PIDFILE=${1#--pidfile=}
;;
--quiet)
quiet=1
;;
--default-music-folder=?*)
LIBRESONIC_DEFAULT_MUSIC_FOLDER=${1#--default-music-folder=}
;;
--default-podcast-folder=?*)
LIBRESONIC_DEFAULT_PODCAST_FOLDER=${1#--default-podcast-folder=}
;;
--default-playlist-folder=?*)
LIBRESONIC_DEFAULT_PLAYLIST_FOLDER=${1#--default-playlist-folder=}
;;
*)
usage
;;
esac
shift
done
# Use JAVA_HOME if set, otherwise assume java is in the path.
JAVA=java
if [ -e "${JAVA_HOME}" ]
then
JAVA=${JAVA_HOME}/bin/java
fi
# Create Libresonic home directory.
mkdir -p ${LIBRESONIC_HOME}
LOG=${LIBRESONIC_HOME}/libresonic_sh.log
rm -f ${LOG}
cd $(dirname $0)
if [ -L $0 ] && ([ -e /bin/readlink ] || [ -e /usr/bin/readlink ]); then
cd $(dirname $(readlink $0))
fi
${JAVA} -Xmx${LIBRESONIC_MAX_MEMORY}m \
-Dlibresonic.home=${LIBRESONIC_HOME} \
-Dlibresonic.host=${LIBRESONIC_HOST} \
-Dlibresonic.port=${LIBRESONIC_PORT} \
-Dlibresonic.httpsPort=${LIBRESONIC_HTTPS_PORT} \
-Dlibresonic.contextPath=${LIBRESONIC_CONTEXT_PATH} \
-Dlibresonic.defaultMusicFolder=${LIBRESONIC_DEFAULT_MUSIC_FOLDER} \
-Dlibresonic.defaultPodcastFolder=${LIBRESONIC_DEFAULT_PODCAST_FOLDER} \
-Dlibresonic.defaultPlaylistFolder=${LIBRESONIC_DEFAULT_PLAYLIST_FOLDER} \
-Djava.awt.headless=true \
-verbose:gc \
-jar libresonic-booter-jar-with-dependencies.jar > ${LOG} 2>&1 &
# Write pid to pidfile if it is defined.
if [ $LIBRESONIC_PIDFILE ]; then
echo $! > ${LIBRESONIC_PIDFILE}
fi
if [ $quiet = 0 ]; then
echo Started Libresonic [PID $!, ${LOG}]
fi

@ -1,87 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>libresonic-installer-debian</artifactId>
<packaging>pom</packaging>
<name>Libresonic Installer for Debian</name>
<parent>
<groupId>org.libresonic.player</groupId>
<artifactId>libresonic</artifactId>
<version>6.2.beta1.springboot</version>
</parent>
<profiles>
<profile>
<id>linux</id>
<activation>
<os>
<family>linux</family>
</os>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>dpkg</id>
<phase>compile</phase>
<configuration>
<target>
<echo>Creating Debian package...</echo>
<copy todir="${project.build.directory}/deb">
<fileset dir="${basedir}/src"/>
<filterset>
<filter token="VERSION" value="${project.version}"/>
</filterset>
</copy>
<copy file="../libresonic-booter/src/main/script/libresonic.sh" todir="${project.build.directory}/deb/usr/share/libresonic"/>
<copy file="../libresonic-booter/target/libresonic-booter-jar-with-dependencies.jar" todir="${project.build.directory}/deb/usr/share/libresonic"/>
<copy file="../libresonic-main/target/libresonic.war" todir="${project.build.directory}/deb/usr/share/libresonic"/>
<copy file="../libresonic-transcode/linux/ffmpeg" todir="${project.build.directory}/deb/var/libresonic/transcode"/>
<copy file="../libresonic-transcode/linux/lame" todir="${project.build.directory}/deb/var/libresonic/transcode"/>
<exec executable="chmod">
<arg value="oug+x"/>
<arg value="${project.build.directory}/deb/DEBIAN/preinst"/>
<arg value="${project.build.directory}/deb/DEBIAN/postinst"/>
<arg value="${project.build.directory}/deb/DEBIAN/prerm"/>
<arg value="${project.build.directory}/deb/DEBIAN/postrm"/>
<arg value="${project.build.directory}/deb/usr/share/libresonic/libresonic.sh"/>
<arg value="${project.build.directory}/deb/etc/init.d/libresonic"/>
<arg value="${project.build.directory}/deb/var/libresonic/transcode/ffmpeg"/>
<arg value="${project.build.directory}/deb/var/libresonic/transcode/lame"/>
</exec>
<exec executable="sleep">
<arg value="2"/>
</exec>
<exec executable="fakeroot">
<arg value="dpkg"/>
<arg value="--build"/>
<arg value="${project.build.directory}/deb"/>
<arg value="${project.build.directory}/libresonic-${project.version}.deb"/>
</exec>
<exec executable="lintian">
<arg value="${project.build.directory}/libresonic-${project.version}.deb"/>
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

@ -1 +0,0 @@
/etc/default/libresonic

@ -1,18 +0,0 @@
Package: libresonic
Version: @VERSION@
Section: Multimedia
Priority: optional
Recommends: ffmpeg
Architecture: all
Maintainer: Eugene E. Kashpureff Jr <eugene@kashpureff.org>
Description: A web-based music streamer, jukebox and Podcast receiver
Libresonic is a web-based music streamer, jukebox and Podcast receiver,
providing access to your music collection wherever you are. Use it
to share your music with friends, or to listen to your music while away
from home.
.
Apps for Android, iPhone and Windows Phone are also available.
.
Java 1.6 or higher is required to run Libresonic.
.
Libresonic can be found at http://libresonic.org

@ -1,16 +0,0 @@
#! /bin/sh
set -e
ln -sf /usr/share/libresonic/libresonic.sh /usr/bin/libresonic
chmod 750 /var/libresonic
# Clear jetty cache.
rm -rf /var/libresonic/jetty
# Configure Libresonic service.
update-rc.d libresonic defaults 99
# Start Libresonic service.
invoke-rc.d libresonic start

@ -1,9 +0,0 @@
#! /bin/sh
set -e
# Remove symlink.
rm -f /usr/bin/libresonic
# Remove startup scripts.
update-rc.d -f libresonic remove

@ -1,15 +0,0 @@
#! /bin/sh
set -e
# Stop Libresonic service.
if [ -e /etc/init.d/libresonic ]; then
invoke-rc.d libresonic stop
fi
# Backup database.
if [ -e /var/libresonic/db ]; then
rm -rf /var/libresonic/db.backup
cp -R /var/libresonic/db /var/libresonic/db.backup
fi

@ -1,8 +0,0 @@
#! /bin/sh
set -e
# Stop Libresonic service.
if [ -e /etc/init.d/libresonic ]; then
invoke-rc.d libresonic stop
fi

@ -1,25 +0,0 @@
#
# This is the configuration file for the Libresonic service
# (/etc/init.d/libresonic)
#
# To change the startup parameters of Libresonic, modify
# the LIBRESONIC_ARGS variable below.
#
# Type "/usr/share/libresonic/libresonic.sh --help" on the command line to read an
# explanation of the different options.
#
# For example, to specify that Libresonic should use port 80 (for http)
# and 443 (for https), and use a Java memory heap size of 200 MB, use
# the following:
#
# LIBRESONIC_ARGS="--port=80 --https-port=443 --max-memory=200"
LIBRESONIC_ARGS="--max-memory=150"
# The user which should run the Libresonic process. Default "root".
# Note that non-root users are by default not allowed to use ports
# below 1024. Also make sure to grant the user write permissions in
# the music directories, otherwise changing album art and tags will fail.
LIBRESONIC_USER=root

@ -1,138 +0,0 @@
#! /bin/sh
### BEGIN INIT INFO
# Provides: libresonic
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Libresonic daemon
# Description: Starts the Libresonic daemon. Libresonic is a web-based
# music streamer, jukebox and Podcast receiver.
# See http://libresonic.org for more details.
### END INIT INFO
# Author: Sindre Mehus <sindre@activeobjects.no>
# To change the startup parameters of Libresonic, modify the service
# configuration file /etc/default/libresonic rather than this file.
[ -r /etc/default/libresonic ] && . /etc/default/libresonic
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="Libresonic Daemon"
NAME=libresonic
PIDFILE=/var/run/$NAME.pid
DAEMON=/usr/bin/$NAME
DAEMON_ARGS="--pidfile=$PIDFILE $LIBRESONIC_ARGS"
SCRIPTNAME=/etc/init.d/$NAME
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# Run as root if LIBRESONIC_USER is not set.
[ "$LIBRESONIC_USER" = "" ] && LIBRESONIC_USER=root
# Make sure Libresonic is started with system locale
if [ -r /etc/default/locale ]; then
. /etc/default/locale
export LANG
fi
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions
#
# Function that starts the daemon/service
#
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
if [ -e $PIDFILE ]
then
ps -p $(cat $PIDFILE) > /dev/null
[ "$?" = 0 ] && return 1
fi
touch $PIDFILE
chown $LIBRESONIC_USER $PIDFILE
[ -e /var/libresonic ] && chown -R $LIBRESONIC_USER /var/libresonic
[ -e /tmp/libresonic ] && chown -R $LIBRESONIC_USER /tmp/libresonic
start-stop-daemon --start -c $LIBRESONIC_USER --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_ARGS || return 2
}
#
# Function that stops the daemon/service
#
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
# Many daemons don't delete their pidfiles when they exit.
rm -f $PIDFILE
return "$RETVAL"
}
case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
status)
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
;;
restart|force-reload)
#
# If the "reload" option is implemented then remove the
# 'force-reload' alias
#
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
exit 3
;;
esac
:

@ -1,111 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>libresonic-installer-mac</artifactId>
<packaging>pom</packaging>
<name>Libresonic Installer for Mac</name>
<parent>
<groupId>org.libresonic.player</groupId>
<artifactId>libresonic</artifactId>
<version>6.2.beta1.springboot</version>
</parent>
<dependencies>
<dependency>
<groupId>org.libresonic.player</groupId>
<artifactId>libresonic-main</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>org.libresonic.player</groupId>
<artifactId>libresonic-booter</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>mac</id>
<activation>
<os>
<family>mac</family>
</os>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>compile</phase>
<configuration>
<target>
<taskdef name="appbundler" classname="com.oracle.appbundler.AppBundlerTask"/>
<mkdir dir="${project.build.directory}"/>
<appbundler outputdirectory="target"
name="Libresonic"
displayname="Libresonic"
icon="src/libresonic.icns"
identifier="org.libresonic.player"
shortversion="${project.version}"
mainclassname="org.libresonic.player.booter.Main">
<runtime dir="${env.JAVA_HOME}"/>
<classpath dir="..">
<include name="libresonic-booter/target/libresonic-booter-jar-with-dependencies.jar"/>
<include name="libresonic-main/target/libresonic.war"/>
</classpath>
<option value="-Dlibresonic.war=$APP_ROOT/Contents/Java/libresonic.war"/>
<option value="-Dlibresonic.home=/Library/Application Support/Libresonic"/>
<option value="-Dlibresonic.defaultMusicFolder=/Users/Shared/Music/iTunes/iTunes Media"/>
<option value="-Dlibresonic.defaultPodcastFolder=/Users/Shared/Podcasts"/>
<option value="-Dlibresonic.defaultPlaylistFolder=/Users/Shared/Playlists"/>
<option value="-Dlibresonic.port=4040"/>
<option value="-Dlibresonic.httpsPort=0"/>
<option value="-Dlibresonic.contextPath=/"/>
<option value="-Dapple.awt.UIElement=true"/>
<option value="-Xmx150m"/>
<argument value="-mac"/>
</appbundler>
<!--Requires installation of Packages, see http://s.sudre.free.fr/Software/Packages/about.html or libresonic-tools-->
<exec executable="/usr/local/bin/packagesbuild">
<arg value="-v"/>
<arg value="${project.basedir}/src/libresonic.pkgproj"/>
</exec>
<exec executable="/usr/bin/productsign">
<arg value="--sign"/>
<arg value="Sindre Mehus"/>
<arg value="${project.build.directory}/libresonic.pkg"/>
<arg value="${project.build.directory}/libresonic-${project.version}.pkg"/>
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>appbundler</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

@ -1,883 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PACKAGES</key>
<array>
<dict>
<key>PACKAGE_FILES</key>
<dict>
<key>DEFAULT_INSTALL_LOCATION</key>
<string>/</string>
<key>HIERARCHY</key>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>../target/Libresonic.app</string>
<key>PATH_TYPE</key>
<integer>1</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>3</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Utilities</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Applications</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>509</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>../../libresonic-transcode/mac/ffmpeg</string>
<key>PATH_TYPE</key>
<integer>1</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>3</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>transcode</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>2</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Libresonic</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>2</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Application Support</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Documentation</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Filesystems</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Frameworks</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Input Methods</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Internet Plug-Ins</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>LaunchAgents</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>LaunchDaemons</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>PreferencePanes</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Preferences</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Printers</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>PrivilegedHelperTools</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>QuickLook</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>QuickTime</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Screen Savers</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Scripts</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Services</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Widgets</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Library</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Extensions</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Library</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>System</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<dict>
<key>CHILDREN</key>
<array>
<dict>
<key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>Shared</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>1023</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
<string>Users</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
</array>
<key>GID</key>
<integer>0</integer>
<key>PATH</key>
<string>/</string>
<key>PATH_TYPE</key>
<integer>0</integer>
<key>PERMISSIONS</key>
<integer>493</integer>
<key>TYPE</key>
<integer>1</integer>
<key>UID</key>
<integer>0</integer>
</dict>
<key>PAYLOAD_TYPE</key>
<integer>0</integer>
<key>VERSION</key>
<integer>2</integer>
</dict>
<key>PACKAGE_SCRIPTS</key>
<dict>
<key>POSTINSTALL_PATH</key>
<dict>
<key>PATH</key>
<string>postinstall.sh</string>
<key>PATH_TYPE</key>
<integer>1</integer>
</dict>
<key>PREINSTALL_PATH</key>
<dict>
<key>PATH</key>
<string>preinstall.sh</string>
<key>PATH_TYPE</key>
<integer>1</integer>
</dict>
<key>RESOURCES</key>
<array/>
</dict>
<key>PACKAGE_SETTINGS</key>
<dict>
<key>AUTHENTICATION</key>
<integer>1</integer>
<key>CONCLUSION_ACTION</key>
<integer>0</integer>
<key>IDENTIFIER</key>
<string>org.libresonic.player</string>
<key>NAME</key>
<string>libresonic</string>
<key>OVERWRITE_PERMISSIONS</key>
<false/>
<key>VERSION</key>
<string>1.0</string>
</dict>
<key>UUID</key>
<string>1804C6F2-A8D3-496B-B75B-8945F1A8CFEE</string>
</dict>
</array>
<key>PROJECT</key>
<dict>
<key>PROJECT_COMMENTS</key>
<dict>
<key>NOTES</key>
<data>
PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBIVE1M
IDQuMDEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDQv
c3RyaWN0LmR0ZCI+CjxodG1sPgo8aGVhZD4KPG1ldGEgaHR0cC1l
cXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7
IGNoYXJzZXQ9VVRGLTgiPgo8bWV0YSBodHRwLWVxdWl2PSJDb250
ZW50LVN0eWxlLVR5cGUiIGNvbnRlbnQ9InRleHQvY3NzIj4KPHRp
dGxlPjwvdGl0bGU+CjxtZXRhIG5hbWU9IkdlbmVyYXRvciIgY29u
dGVudD0iQ29jb2EgSFRNTCBXcml0ZXIiPgo8bWV0YSBuYW1lPSJD
b2NvYVZlcnNpb24iIGNvbnRlbnQ9IjEyNjUuMTkiPgo8c3R5bGUg
dHlwZT0idGV4dC9jc3MiPgo8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5
Pgo8L2JvZHk+CjwvaHRtbD4K
</data>
</dict>
<key>PROJECT_PRESENTATION</key>
<dict>
<key>BACKGROUND</key>
<dict>
<key>ALIGNMENT</key>
<integer>6</integer>
<key>BACKGROUND_PATH</key>
<dict>
<key>PATH</key>
<string>libresonic.png</string>
<key>PATH_TYPE</key>
<integer>1</integer>
</dict>
<key>CUSTOM</key>
<integer>1</integer>
<key>SCALING</key>
<integer>2</integer>
</dict>
<key>INSTALLATION_STEPS</key>
<array>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewIntroductionController</string>
<key>INSTALLER_PLUGIN</key>
<string>Introduction</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewReadMeController</string>
<key>INSTALLER_PLUGIN</key>
<string>ReadMe</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewLicenseController</string>
<key>INSTALLER_PLUGIN</key>
<string>License</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewDestinationSelectController</string>
<key>INSTALLER_PLUGIN</key>
<string>TargetSelect</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewInstallationTypeController</string>
<key>INSTALLER_PLUGIN</key>
<string>PackageSelection</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewInstallationController</string>
<key>INSTALLER_PLUGIN</key>
<string>Install</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
<dict>
<key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
<string>ICPresentationViewSummaryController</string>
<key>INSTALLER_PLUGIN</key>
<string>Summary</string>
<key>LIST_TITLE_KEY</key>
<string>InstallerSectionTitle</string>
</dict>
</array>
<key>INTRODUCTION</key>
<dict>
<key>LOCALIZATIONS</key>
<array/>
</dict>
<key>SUMMARY</key>
<dict>
<key>LOCALIZATIONS</key>
<array/>
</dict>
<key>TITLE</key>
<dict>
<key>LOCALIZATIONS</key>
<array>
<dict>
<key>LANGUAGE</key>
<string>English</string>
<key>VALUE</key>
<string>Libresonic</string>
</dict>
</array>
</dict>
</dict>
<key>PROJECT_REQUIREMENTS</key>
<dict>
<key>LIST</key>
<array/>
<key>POSTINSTALL_PATH</key>
<dict/>
<key>PREINSTALL_PATH</key>
<dict/>
<key>RESOURCES</key>
<array/>
<key>ROOT_VOLUME_ONLY</key>
<false/>
</dict>
<key>PROJECT_SETTINGS</key>
<dict>
<key>ADVANCED_OPTIONS</key>
<dict/>
<key>BUILD_FORMAT</key>
<integer>0</integer>
<key>BUILD_PATH</key>
<dict>
<key>PATH</key>
<string>../target</string>
<key>PATH_TYPE</key>
<integer>1</integer>
</dict>
<key>EXCLUDED_FILES</key>
<array>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.DS_Store</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Remove .DS_Store files</string>
<key>PROXY_TOOLTIP</key>
<string>Remove ".DS_Store" files created by the Finder.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.pbdevelopment</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Remove .pbdevelopment files</string>
<key>PROXY_TOOLTIP</key>
<string>Remove ".pbdevelopment" files created by ProjectBuilder or Xcode.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>CVS</string>
<key>TYPE</key>
<integer>1</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.cvsignore</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.cvspass</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.svn</string>
<key>TYPE</key>
<integer>1</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.git</string>
<key>TYPE</key>
<integer>1</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>.gitignore</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Remove SCM metadata</string>
<key>PROXY_TOOLTIP</key>
<string>Remove helper files and folders used by the CVS, SVN or Git Source Code Management systems.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>classes.nib</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>designable.db</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>info.nib</string>
<key>TYPE</key>
<integer>0</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Optimize nib files</string>
<key>PROXY_TOOLTIP</key>
<string>Remove "classes.nib", "info.nib" and "designable.nib" files within .nib bundles.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>PATTERNS_ARRAY</key>
<array>
<dict>
<key>REGULAR_EXPRESSION</key>
<false/>
<key>STRING</key>
<string>Resources Disabled</string>
<key>TYPE</key>
<integer>1</integer>
</dict>
</array>
<key>PROTECTED</key>
<true/>
<key>PROXY_NAME</key>
<string>Remove Resources Disabled folders</string>
<key>PROXY_TOOLTIP</key>
<string>Remove "Resources Disabled" folders.</string>
<key>STATE</key>
<true/>
</dict>
<dict>
<key>SEPARATOR</key>
<true/>
</dict>
</array>
<key>NAME</key>
<string>libresonic</string>
</dict>
</dict>
<key>TYPE</key>
<integer>0</integer>
<key>VERSION</key>
<integer>2</integer>
</dict>
</plist>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

@ -1,13 +0,0 @@
#!/bin/bash
LIBRESONIC_HOME="/Library/Application Support/Libresonic"
chmod oug+rwx "$LIBRESONIC_HOME"
chown root:admin "$LIBRESONIC_HOME"
chmod oug+rx "$LIBRESONIC_HOME/transcode"
chown root:admin "$LIBRESONIC_HOME/transcode"
rm -rf "$LIBRESONIC_HOME/jetty"
echo Libresonic installation done

@ -1,11 +0,0 @@
#!/bin/bash
LIBRESONIC_HOME="/Library/Application Support/Libresonic"
# Backup database.
if [ -e "$LIBRESONIC_HOME/db" ]; then
rm -rf "$LIBRESONIC_HOME/db.backup"
cp -R "$LIBRESONIC_HOME/db" "$LIBRESONIC_HOME/db.backup"
fi

@ -1,121 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>libresonic-installer-rpm</artifactId>
<packaging>pom</packaging>
<name>Libresonic Installer for RPM</name>
<parent>
<groupId>org.libresonic.player</groupId>
<artifactId>libresonic</artifactId>
<version>6.2.beta1.springboot</version>
</parent>
<profiles>
<profile>
<id>rpm</id>
<activation>
<property>
<name>rpm</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
<configuration>
<doCheck>false</doCheck>
<doUpdate>false</doUpdate>
</configuration>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>rpm</id>
<phase>compile</phase>
<configuration>
<target>
<echo>Creating RPM package...</echo>
<copy file="${basedir}/src/libresonic.spec"
todir="${project.build.directory}/rpm/SPECS">
<filterset>
<filter token="VERSION" value="${project.version}"/>
<filter token="BUILD_NUMBER" value="${buildNumber}"/>
</filterset>
</copy>
<!--Remove ".beta" suffix from version tag.-->
<replace file="${project.build.directory}/rpm/SPECS/libresonic.spec">
<replacetoken>.beta1</replacetoken>
<replacetoken>.beta2</replacetoken>
<replacetoken>.beta3</replacetoken>
<replacetoken>.beta4</replacetoken>
</replace>
<mkdir dir="${project.build.directory}/rpm/RPMS/i386"/>
<copy file="${basedir}/src/etc/init.d/libresonic"
todir="${project.build.directory}/rpm/buildroot/etc/init.d"/>
<copy file="${basedir}/src/etc/sysconfig/libresonic"
todir="${project.build.directory}/rpm/buildroot/etc/sysconfig"/>
<copy file="../libresonic-booter/src/main/script/libresonic.sh"
todir="${project.build.directory}/rpm/buildroot/usr/share/libresonic"/>
<copy file="../libresonic-booter/target/libresonic-booter-jar-with-dependencies.jar"
todir="${project.build.directory}/rpm/buildroot/usr/share/libresonic"/>
<copy file="../libresonic-main/target/libresonic.war"
todir="${project.build.directory}/rpm/buildroot/usr/share/libresonic"/>
<copy file="../libresonic-transcode/linux/ffmpeg"
todir="${project.build.directory}/rpm/buildroot/var/libresonic/transcode"/>
<copy file="../libresonic-transcode/linux/lame"
todir="${project.build.directory}/rpm/buildroot/var/libresonic/transcode"/>
<exec executable="rpmbuild">
<arg value="-bb"/>
<arg value="--buildroot"/>
<arg value="${project.build.directory}/rpm/buildroot"/>
<arg value="--define"/>
<arg value="_topdir ${project.build.directory}/rpm"/>
<arg value="--target"/>
<arg value="i386"/>
<arg value="${project.build.directory}/rpm/SPECS/libresonic.spec"/>
</exec>
<copy tofile="${project.build.directory}/libresonic-${project.version}.rpm">
<fileset dir="${project.build.directory}/rpm/RPMS/i386">
<include name="*.rpm"/>
</fileset>
</copy>
<exec executable="rpmlint">
<arg value="${project.build.directory}/libresonic-${project.version}.rpm"/>
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

@ -1,104 +0,0 @@
#!/bin/bash
#
# libresonic This shell script takes care of starting and stopping Libresonic
#
# chkconfig: - 80 20
#
### BEGIN INIT INFO
# Provides: libresonic
# Required-Start: $network $syslog
# Required-Stop: $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Libresonic daemon
# Description: Starts the Libresonic daemon. Libresonic is a web-based
# music streamer, jukebox and Podcast receiver.
# See http://libresonic.org for more details.
### END INIT INFO
# Author: Sindre Mehus <sindre@activeobjects.no>
# To change the startup parameters of Libresonic, modify the service
# configuration file /etc/sysconfig/libresonic rather than this file.
[ -r /etc/sysconfig/libresonic ] && . /etc/sysconfig/libresonic
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="Libresonic Daemon"
NAME=libresonic
PIDFILE=/var/run/$NAME.pid
LOCKFILE=/var/lock/subsys/$NAME
DAEMON=/usr/bin/$NAME
DAEMON_ARGS="--pidfile=$PIDFILE $LIBRESONIC_ARGS"
SCRIPTNAME=/etc/init.d/$NAME
# Exit if the package is not installed.
[ -x "$DAEMON" ] || exit 0
# Run as root if LIBRESONIC_USER is not set.
[ "$LIBRESONIC_USER" = "" ] && LIBRESONIC_USER=root
# Source function library.
. /etc/init.d/functions
#
# Function that starts the daemon/service
#
do_start()
{
# Check if daemon is already running.
if [ -e $PIDFILE ]
then
ps -p $(cat $PIDFILE) > /dev/null
[ "$?" = 0 ] && return 1
fi
touch $PIDFILE
chown $LIBRESONIC_USER $PIDFILE
[ -e /var/libresonic ] && chown -R $LIBRESONIC_USER /var/libresonic
[ -e /tmp/libresonic ] && chown -R $LIBRESONIC_USER /tmp/libresonic
echo $"Starting $NAME ..."
su -c "$DAEMON $DAEMON_ARGS" $LIBRESONIC_USER
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch $LOCKFILE
return $RETVAL
}
#
# Function that stops the daemon/service
#
do_stop()
{
# Check if pidfile exists
[ ! -e $PIDFILE ] && return 1
echo -n $"Stopping $NAME ..."
killproc -p $PIDFILE $DAEMON
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f $LOCKFILE
return $RETVAL
}
case "$1" in
start)
do_start
;;
stop)
do_stop
;;
status)
status -p $PIDFILE "$NAME"
;;
restart|force-reload)
do_stop
do_start
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
exit 3
;;
esac
:

@ -1,25 +0,0 @@
#
# This is the configuration file for the Libresonic service
# (/etc/init.d/libresonic)
#
# To change the startup parameters of Libresonic, modify
# the LIBRESONIC_ARGS variable below.
#
# Type "/usr/share/libresonic/libresonic.sh --help" on the command line to read an
# explanation of the different options.
#
# For example, to specify that Libresonic should use port 80 (for http)
# and 443 (for https), and use a Java memory heap size of 200 MB, use
# the following:
#
# LIBRESONIC_ARGS="--port=80 --https-port=443 --max-memory=200"
LIBRESONIC_ARGS="--max-memory=150"
# The user which should run the Libresonic process. Default "root".
# Note that non-root users are by default not allowed to use ports
# below 1024. Also make sure to grant the user write permissions in
# the music directories, otherwise changing album art and tags will fail.
LIBRESONIC_USER=root

@ -1,78 +0,0 @@
Name: libresonic
Version: @VERSION@
Release: @BUILD_NUMBER@
Summary: A web-based music streamer, jukebox and Podcast receiver
Group: Applications/Multimedia
License: GPLv3
URL: http://libresonic.org
%description
Libresonic is a web-based music streamer, jukebox and Podcast receiver,
providing access to your music collection wherever you are. Use it
to share your music with friends, or to listen to your music while away
from home.
Apps for Android, iPhone and Windows Phone are also available.
Java 1.6 or higher is required to run Libresonic.
Libresonic can be found at http://libresonic.org
%files
%defattr(644,root,root,755)
/usr/share/libresonic/libresonic-booter-jar-with-dependencies.jar
/usr/share/libresonic/libresonic.war
%attr(755,root,root) /usr/share/libresonic/libresonic.sh
%attr(755,root,root) /etc/init.d/libresonic
%attr(755,root,root) /var/libresonic/transcode/ffmpeg
%attr(755,root,root) /var/libresonic/transcode/lame
%config(noreplace) /etc/sysconfig/libresonic
%pre
# Stop Libresonic service.
if [ -e /etc/init.d/libresonic ]; then
service libresonic stop
fi
# Backup database.
if [ -e /var/libresonic/db ]; then
rm -rf /var/libresonic/db.backup
cp -R /var/libresonic/db /var/libresonic/db.backup
fi
exit 0
%post
ln -sf /usr/share/libresonic/libresonic.sh /usr/bin/libresonic
chmod 750 /var/libresonic
# Clear jetty cache.
rm -rf /var/libresonic/jetty
# For SELinux: Set security context
chcon -t java_exec_t /etc/init.d/libresonic 2>/dev/null
# Configure and start Libresonic service.
chkconfig --add libresonic
service libresonic start
exit 0
%preun
# Only do it if uninstalling, not upgrading.
if [ $1 = 0 ] ; then
# Stop the service.
[ -e /etc/init.d/libresonic ] && service libresonic stop
# Remove symlink.
rm -f /usr/bin/libresonic
# Remove startup scripts.
chkconfig --del libresonic
fi
exit 0

@ -1,104 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>libresonic-installer-windows</artifactId>
<packaging>pom</packaging>
<name>Libresonic Installer for Windows</name>
<parent>
<groupId>org.libresonic.player</groupId>
<artifactId>libresonic</artifactId>
<version>6.2.beta1.springboot</version>
</parent>
<properties>
<exe4j.home>c:/Program Files/exe4j</exe4j.home>
<nsis.home>c:/Program Files (x86)/NSIS</nsis.home>
</properties>
<dependencies>
<dependency>
<groupId>org.libresonic.player</groupId>
<artifactId>libresonic-main</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>org.libresonic.player</groupId>
<artifactId>libresonic-booter</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>windows</id>
<activation>
<os>
<family>windows</family>
</os>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>exe4j</id>
<phase>compile</phase>
<configuration>
<target>
<echo>Compiling exe4j...</echo>
<copy file="${basedir}/src/main/exe4j/libresonic-agent.exe.vmoptions" todir="${project.build.directory}"/>
<copy file="${basedir}/src/main/exe4j/libresonic-agent-elevated.exe.vmoptions" todir="${project.build.directory}"/>
<copy file="${basedir}/src/main/exe4j/libresonic-service.exe.vmoptions" todir="${project.build.directory}"/>
<exec executable="${exe4j.home}/bin/exe4jc">
</exec>
<exec executable="${exe4j.home}/bin/exe4jc">
<arg value="${basedir}/src/main/exe4j/libresonic-agent.exe4j"/>
</exec>
<exec executable="${exe4j.home}/bin/exe4jc">
<arg value="${basedir}/src/main/exe4j/libresonic-agent-elevated.exe4j"/>
</exec>
<exec executable="${exe4j.home}/bin/exe4jc">
<arg value="${basedir}/src/main/exe4j/libresonic-service.exe4j"/>
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>nsis</id>
<phase>compile</phase>
<configuration>
<target>
<echo>Compiling NSIS script...</echo>
<mkdir dir="${project.build.directory}"/>
<exec executable="${nsis.home}/makensis">
<arg value="${basedir}/src/main/nsis/libresonic.nsi"/>
<arg value="-XOutFile ${project.build.directory}/libresonic-${project.version}-setup.exe"/>
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<exe4j version="4.4.4" transformSequenceNumber="1">
<directoryPresets config="." />
<application name="Libresonic" distributionSourceDir="../../../target">
<languages>
<principalLanguage id="en" customLocalizationFile="" />
</languages>
</application>
<executable name="libresonic-agent-elevated" type="1" iconSet="true" iconFile="libresonic-16.ico" executableDir="" redirectStderr="true" stderrFile="log/libresonic-agent.log" stderrMode="overwrite" redirectStdout="false" stdoutFile="output.log" stdoutMode="overwrite" failOnStderrOutput="true" executableMode="1" changeWorkingDirectory="true" workingDirectory="." singleInstance="false" serviceStartType="2" serviceDependencies="" serviceDescription="Libresonic Music Streamer (http://libresonic.org)" jreLocation="" executionLevel="requireAdministrator" checkConsoleParameter="false" globalSingleInstance="false" amd64="false">
<messageSet>
<message id="NoJvmFound" text="Java was not found on your system. Please download Java from www.java.com." />
</messageSet>
<versionInfo include="false" fileVersion="" fileDescription="" legalCopyright="" internalName="" productName="" companyName="" productVersion="" />
</executable>
<splashScreen show="false" autoOff="false" alwaysOnTop="false" width="-1" height="-1" bitmapFile="" java6SplashScreen="false">
<text>
<statusLine x="0" y="0" text="" font="Arial" fontSize="8" fontColor="0,0,0" fontWeight="500" />
<versionLine x="0" y="0" text="" font="Arial" fontSize="8" fontColor="0,0,0" fontWeight="500" />
</text>
</splashScreen>
<java mainClass="org.libresonic.player.booter.Main" vmParameters="" arguments="-agent -elevated" allowVMPassthroughParameters="true" preferredVM="" bundleRuntime="true" minVersion="1.6" maxVersion="" allowBetaVM="true" jdkOnly="false">
<searchSequence>
<registry />
<envVar name="JAVA_HOME" />
<envVar name="JDK_HOME" />
</searchSequence>
<classPath>
<archive location="./libresonic-booter-jar-with-dependencies.jar" failOnError="false" />
</classPath>
<nativeLibraryDirectories />
</java>
<includedFiles />
<unextractableFiles />
</exe4j>

@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<exe4j version="4.5.1" transformSequenceNumber="1">
<directoryPresets config="." />
<application name="Libresonic" distributionSourceDir="../../../target">
<languages>
<principalLanguage id="en" customLocalizationFile="" />
</languages>
</application>
<executable name="libresonic-agent" type="1" iconSet="true" iconFile="libresonic-16.ico" executableDir="" redirectStderr="true" stderrFile="log/libresonic-agent.log" stderrMode="overwrite" redirectStdout="false" stdoutFile="output.log" stdoutMode="overwrite" failOnStderrOutput="true" executableMode="1" changeWorkingDirectory="true" workingDirectory="." singleInstance="false" serviceStartType="2" serviceDependencies="" serviceDescription="Libresonic Music Streamer (http://libresonic.org)" jreLocation="" executionLevel="asInvoker" checkConsoleParameter="false" globalSingleInstance="false" amd64="false">
<messageSet>
<message id="NoJvmFound" text="Java was not found on your system. Please download Java (32-bit version) from java.com." />
<message id="JvmInPath" text="Java was not found on your system. Please download Java (32-bit version) from java.com." />
<message id="JvmDefinedPath" text="Java was not found on your system. Please download Java (32-bit version) from java.com." />
<message id="NoJvmFound3264" text="Java was not found on your system. Please download Java (32-bit version) from java.com." />
<message id="JvmInPath3264" text="Java was not found on your system. Please download Java (32-bit version) from java.com." />
<message id="JvmDefinedPath32" text="Java was not found on your system. Please download Java (32-bit version) from java.com." />
<message id="JvmDefinedPath64" text="Java was not found on your system. Please download Java (32-bit version) from java.com." />
</messageSet>
<versionInfo include="false" fileVersion="" fileDescription="" legalCopyright="" internalName="" productName="" companyName="" productVersion="" />
</executable>
<splashScreen show="false" autoOff="false" alwaysOnTop="false" width="-1" height="-1" bitmapFile="" java6SplashScreen="false">
<text>
<statusLine x="0" y="0" text="" font="Arial" fontSize="8" fontColor="0,0,0" fontWeight="500" />
<versionLine x="0" y="0" text="" font="Arial" fontSize="8" fontColor="0,0,0" fontWeight="500" />
</text>
</splashScreen>
<java mainClass="org.libresonic.player.booter.Main" vmParameters="" arguments="-agent" allowVMPassthroughParameters="true" preferredVM="" bundleRuntime="true" minVersion="1.6" maxVersion="" allowBetaVM="true" jdkOnly="false">
<searchSequence>
<registry />
<envVar name="JAVA_HOME" />
<envVar name="JDK_HOME" />
</searchSequence>
<classPath>
<archive location="./libresonic-booter-jar-with-dependencies.jar" failOnError="false" />
</classPath>
<nativeLibraryDirectories />
</java>
<includedFiles />
<unextractableFiles />
</exe4j>

@ -1,6 +0,0 @@
-Xmx150m
-verbose:gc
-Dlibresonic.host=0.0.0.0
-Dlibresonic.port=4040
-Dlibresonic.httpsPort=0
-Dlibresonic.contextPath=/

@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<exe4j version="4.5.1" transformSequenceNumber="1">
<directoryPresets config="." />
<application name="Libresonic" distributionSourceDir="../../../target">
<languages>
<principalLanguage id="en" customLocalizationFile="" />
</languages>
</application>
<executable name="libresonic-service" type="1" iconSet="true" iconFile="libresonic-16.ico" executableDir="" redirectStderr="true" stderrFile="log/libresonic-service.log" stderrMode="overwrite" redirectStdout="false" stdoutFile="output.log" stdoutMode="overwrite" failOnStderrOutput="true" executableMode="3" changeWorkingDirectory="true" workingDirectory="." singleInstance="true" serviceStartType="2" serviceDependencies="" serviceDescription="Libresonic Music Streamer (http://libresonic.org)" jreLocation="" executionLevel="asInvoker" checkConsoleParameter="false" globalSingleInstance="false" amd64="false">
<messageSet>
<message id="NoJvmFound" text="Java was not found on your system. Please download Java (32-bit version) from java.com." />
<message id="JvmInPath" text="Java was not found on your system. Please download Java (32-bit version) from java.com." />
<message id="JvmDefinedPath" text="Java was not found on your system. Please download Java (32-bit version) from java.com." />
<message id="NoJvmFound3264" text="Java was not found on your system. Please download Java (32-bit version) from java.com." />
<message id="JvmInPath3264" text="Java was not found on your system. Please download Java (32-bit version) from java.com." />
<message id="JvmDefinedPath32" text="Java was not found on your system. Please download Java (32-bit version) from java.com." />
<message id="JvmDefinedPath64" text="Java was not found on your system. Please download Java (32-bit version) from java.com." />
</messageSet>
<versionInfo include="false" fileVersion="" fileDescription="" legalCopyright="" internalName="" productName="" companyName="" productVersion="" />
</executable>
<splashScreen show="false" autoOff="false" alwaysOnTop="false" width="-1" height="-1" bitmapFile="" java6SplashScreen="false">
<text>
<statusLine x="0" y="0" text="" font="Arial" fontSize="8" fontColor="0,0,0" fontWeight="500" />
<versionLine x="0" y="0" text="" font="Arial" fontSize="8" fontColor="0,0,0" fontWeight="500" />
</text>
</splashScreen>
<java mainClass="org.libresonic.player.booter.Main" vmParameters="-Dlibresonic.createLinkFile=true -Dlibresonic.windowsInstall=true" arguments="" allowVMPassthroughParameters="true" preferredVM="" bundleRuntime="true" minVersion="1.5" maxVersion="" allowBetaVM="true" jdkOnly="false">
<searchSequence>
<registry />
<envVar name="JAVA_HOME" />
<envVar name="JDK_HOME" />
</searchSequence>
<classPath>
<archive location="./libresonic-booter-jar-with-dependencies.jar" failOnError="false" />
</classPath>
<nativeLibraryDirectories />
</java>
<includedFiles />
<unextractableFiles />
</exe4j>

@ -1,213 +0,0 @@
# libresonic.nsi
!include "WordFunc.nsh"
!include "MUI.nsh"
!insertmacro VersionCompare
# The name of the installer
Name "Libresonic"
# The default installation directory
InstallDir $PROGRAMFILES\Libresonic
# Registry key to check for directory (so if you install again, it will
# overwrite the old one automatically)
InstallDirRegKey HKLM "Software\Libresonic" "Install_Dir"
#--------------------------------
#Interface Configuration
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Header\orange.bmp"
!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\Getting Started.html"
!define MUI_FINISHPAGE_SHOWREADME_TEXT "View Getting Started document"
#--------------------------------
# Pages
# This page checks for JRE
Page custom CheckInstalledJRE
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_WELCOME
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
# Languages
!insertmacro MUI_LANGUAGE "English"
Section "Libresonic"
SectionIn RO
# Install for all users
SetShellVarContext "all"
# Take backup of existing libresonic-service.exe.vmoptions
CopyFiles /SILENT $INSTDIR\libresonic-service.exe.vmoptions $TEMP\libresonic-service.exe.vmoptions
# Silently uninstall existing version.
ExecWait '"$INSTDIR\uninstall.exe" /S _?=$INSTDIR'
# Remove previous Jetty temp directory.
RMDir /r "c:\libresonic\jetty"
# Backup database.
RMDir /r "c:\libresonic\db.backup"
CreateDirectory "c:\libresonic\db.backup"
CopyFiles /SILENT "c:\libresonic\db\*" "c:\libresonic\db.backup"
# Set output path to the installation directory.
SetOutPath $INSTDIR
# Write files.
File ..\..\..\target\libresonic-agent.exe
File ..\..\..\target\libresonic-agent.exe.vmoptions
File ..\..\..\target\libresonic-agent-elevated.exe
File ..\..\..\target\libresonic-agent-elevated.exe.vmoptions
File ..\..\..\target\libresonic-service.exe
File ..\..\..\target\libresonic-service.exe.vmoptions
File ..\..\..\..\libresonic-booter\target\libresonic-booter-jar-with-dependencies.jar
File ..\..\..\..\libresonic-main\README.TXT
File ..\..\..\..\libresonic-main\LICENSE.TXT
File "..\..\..\..\libresonic-main\Getting Started.html"
File ..\..\..\..\libresonic-main\target\libresonic.war
File ..\..\..\..\libresonic-main\target\classes\version.txt
File ..\..\..\..\libresonic-main\target\classes\build_number.txt
# Write the installation path into the registry
WriteRegStr HKLM SOFTWARE\Libresonic "Install_Dir" "$INSTDIR"
# Write the uninstall keys for Windows
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Libresonic" "DisplayName" "Libresonic"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Libresonic" "UninstallString" '"$INSTDIR\uninstall.exe"'
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Libresonic" "NoModify" 1
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Libresonic" "NoRepair" 1
WriteUninstaller "uninstall.exe"
# Restore libresonic-service.exe.vmoptions
CopyFiles /SILENT $TEMP\libresonic-service.exe.vmoptions $INSTDIR\libresonic-service.exe.vmoptions
Delete $TEMP\libresonic-service.exe.vmoptions
# Write transcoding pack files.
SetOutPath "c:\libresonic\transcode"
File ..\..\..\..\libresonic-transcode\windows\*.*
# Add Windows Firewall exception.
# (Requires NSIS plugin found on http://nsis.sourceforge.net/NSIS_Simple_Firewall_Plugin to be installed
# as NSIS_HOME/Plugins/SimpleFC.dll)
SimpleFC::AdvAddRule "Libresonic Service (TCP)" "" "6" "1" "1" "7" "1" "$INSTDIR\libresonic-service.exe" "" "" "Libresonic" "" "" "" ""
SimpleFC::AdvAddRule "Libresonic Service (UDP)" "" "17" "1" "1" "7" "1" "$INSTDIR\libresonic-service.exe" "" "" "Libresonic" "" "" "" ""
SimpleFC::AdvAddRule "Libresonic Agent (TCP)" "" "6" "1" "1" "7" "1" "$INSTDIR\libresonic-agent.exe" "" "" "Libresonic" "" "" "" ""
SimpleFC::AdvAddRule "Libresonic Agent (UDP)" "" "17" "1" "1" "7" "1" "$INSTDIR\libresonic-agent.exe" "" "" "Libresonic" "" "" "" ""
SimpleFC::AdvAddRule "Libresonic Agent Elevated (TCP)" "" "6" "1" "1" "7" "1" "$INSTDIR\libresonic-agent-elevated.exe" "" "" "Libresonic" "" "" "" ""
SimpleFC::AdvAddRule "Libresonic Agent Elevated (UDP)" "" "17" "1" "1" "7" "1" "$INSTDIR\libresonic-agent-elevated.exe" "" "" "Libresonic" "" "" "" ""
# Install and start service.
ExecWait '"$INSTDIR\libresonic-service.exe" -install'
ExecWait '"$INSTDIR\libresonic-service.exe" -start'
# Start agent.
Exec '"$INSTDIR\libresonic-agent-elevated.exe" -balloon'
SectionEnd
Section "Start Menu Shortcuts"
CreateDirectory "$SMPROGRAMS\Libresonic"
CreateShortCut "$SMPROGRAMS\Libresonic\Open Libresonic.lnk" "$INSTDIR\libresonic.url" "" "$INSTDIR\libresonic-agent.exe" 0
CreateShortCut "$SMPROGRAMS\Libresonic\Libresonic Tray Icon.lnk" "$INSTDIR\libresonic-agent.exe" "-balloon" "$INSTDIR\libresonic-agent.exe" 0
CreateShortCut "$SMPROGRAMS\Libresonic\Start Libresonic Service.lnk" "$INSTDIR\libresonic-service.exe" "-start" "$INSTDIR\libresonic-service.exe" 0
CreateShortCut "$SMPROGRAMS\Libresonic\Stop Libresonic Service.lnk" "$INSTDIR\libresonic-service.exe" "-stop" "$INSTDIR\libresonic-service.exe" 0
CreateShortCut "$SMPROGRAMS\Libresonic\Uninstall Libresonic.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
CreateShortCut "$SMPROGRAMS\Libresonic\Getting Started.lnk" "$INSTDIR\Getting Started.html" "" "$INSTDIR\Getting Started.html" 0
CreateShortCut "$SMSTARTUP\Libresonic.lnk" "$INSTDIR\libresonic-agent.exe" "" "$INSTDIR\libresonic-agent.exe" 0
SectionEnd
# Uninstaller
Section "Uninstall"
# Uninstall for all users
SetShellVarContext "all"
# Stop and uninstall service if present.
ExecWait '"$INSTDIR\libresonic-service.exe" -stop'
ExecWait '"$INSTDIR\libresonic-service.exe" -uninstall'
# Stop agent by killing it.
# (Requires NSIS plugin found on http://nsis.sourceforge.net/Processes_plug-in to be installed
# as NSIS_HOME/Plugins/Processes.dll)
Processes::KillProcess "libresonic-agent"
Processes::KillProcess "libresonic-agent-elevated"
Processes::KillProcess "ffmpeg"
# Remove registry keys
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Libresonic"
DeleteRegKey HKLM SOFTWARE\Libresonic
# Remove files.
Delete "$SMSTARTUP\Libresonic.lnk"
RMDir /r "$SMPROGRAMS\Libresonic"
Delete "$INSTDIR\build_number.txt"
Delete "$INSTDIR\elevate.exe"
Delete "$INSTDIR\Getting Started.html"
Delete "$INSTDIR\LICENSE.TXT"
Delete "$INSTDIR\README.TXT"
Delete "$INSTDIR\libresonic.url"
Delete "$INSTDIR\libresonic.war"
Delete "$INSTDIR\libresonic-agent.exe"
Delete "$INSTDIR\libresonic-agent.exe.vmoptions"
Delete "$INSTDIR\libresonic-agent-elevated.exe"
Delete "$INSTDIR\libresonic-agent-elevated.exe.vmoptions"
Delete "$INSTDIR\libresonic-booter-jar-with-dependencies.jar"
Delete "$INSTDIR\libresonic-service.exe"
Delete "$INSTDIR\libresonic-service.exe.vmoptions"
Delete "$INSTDIR\uninstall.exe"
Delete "$INSTDIR\version.txt"
RMDir /r "$INSTDIR\log"
RMDir "$INSTDIR"
# Remove Windows Firewall exception.
# (Requires NSIS plugin found on http://nsis.sourceforge.net/NSIS_Simple_Firewall_Plugin to be installed
# as NSIS_HOME/Plugins/SimpleFC.dll)
SimpleFC::AdvRemoveRule "Libresonic Service (TCP)"
SimpleFC::AdvRemoveRule "Libresonic Service (UDP)"
SimpleFC::AdvRemoveRule "Libresonic Agent (TCP)"
SimpleFC::AdvRemoveRule "Libresonic Agent (UDP)"
SimpleFC::AdvRemoveRule "Libresonic Agent Elevated (TCP)"
SimpleFC::AdvRemoveRule "Libresonic Agent Elevated (UDP)"
SectionEnd
Function CheckInstalledJRE
# Read the value from the registry into the $0 register
ReadRegStr $0 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" CurrentVersion
# Check JRE version. At least 1.6 is required.
# $1=0 Versions are equal
# $1=1 Installed version is newer
# $1=2 Installed version is older (or non-existent)
${VersionCompare} $0 "1.6" $1
IntCmp $1 2 InstallJRE 0 0
Return
InstallJRE:
# Launch Java web installer.
MessageBox MB_OK "Java was not found and will now be installed."
File /oname=$TEMP\jre-setup.exe jre-8u31-windows-i586-iftw.exe
ExecWait '"$TEMP\jre-setup.exe"' $0
Delete "$TEMP\jre-setup.exe"
FunctionEnd

@ -68,6 +68,11 @@
<groupId>org.springframework.security</groupId> <groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId> <artifactId>spring-security-ldap</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.security</groupId> <groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId> <artifactId>spring-security-taglibs</artifactId>

@ -1,6 +1,9 @@
package org.libresonic.player.boot; package org.libresonic.player.boot;
import net.sf.ehcache.constructs.web.ShutdownListener; import net.sf.ehcache.constructs.web.ShutdownListener;
import org.apache.catalina.Container;
import org.apache.catalina.Wrapper;
import org.apache.catalina.webresources.StandardRoot;
import org.directwebremoting.servlet.DwrServlet; import org.directwebremoting.servlet.DwrServlet;
import org.libresonic.player.filter.*; import org.libresonic.player.filter.*;
import org.libresonic.player.spring.LibresonicPropertySourceConfigurer; import org.libresonic.player.spring.LibresonicPropertySourceConfigurer;
@ -11,6 +14,10 @@ import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration; import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.boot.web.support.SpringBootServletInitializer;
@ -32,7 +39,7 @@ import javax.servlet.ServletContextListener;
"classpath:/applicationContext-cache.xml", "classpath:/applicationContext-cache.xml",
"classpath:/applicationContext-sonos.xml", "classpath:/applicationContext-sonos.xml",
"classpath:/libresonic-servlet.xml"}) "classpath:/libresonic-servlet.xml"})
public class Application extends SpringBootServletInitializer { public class Application extends SpringBootServletInitializer implements EmbeddedServletContainerCustomizer {
/** /**
* Registers the DWR servlet. * Registers the DWR servlet.
@ -177,6 +184,33 @@ public class Application extends SpringBootServletInitializer {
return doConfigure(application); return doConfigure(application);
} }
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
TomcatEmbeddedServletContainerFactory tomcatFactory = (TomcatEmbeddedServletContainerFactory) container;
tomcatFactory.addContextCustomizers((TomcatContextCustomizer) context -> {
// Increase the size and time before eviction of the Tomcat
// cache so that resources aren't uncompressed too often.
// See https://github.com/jhipster/generator-jhipster/issues/3995
StandardRoot resources = new StandardRoot();
resources.setCacheMaxSize(100000);
resources.setCacheObjectMaxSize(4000);
resources.setCacheTtl(24 * 3600 * 1000); // 1 day, in milliseconds
context.setResources(resources);
// Put Jasper in production mode so that JSP aren't recompiled
// on each request.
// See http://stackoverflow.com/questions/29653326/spring-boot-application-slow-because-of-jsp-compilation
Container jsp = context.findChild("jsp");
if (jsp instanceof Wrapper) {
((Wrapper)jsp).addInitParameter("development", "false");
}
});
}
}
public static void main(String[] args) { public static void main(String[] args) {
SpringApplicationBuilder builder = new SpringApplicationBuilder(); SpringApplicationBuilder builder = new SpringApplicationBuilder();
doConfigure(builder).run(args); doConfigure(builder).run(args);

@ -98,6 +98,8 @@ public class AdvancedSettingsController {
settingsService.setSmtpPassword(command.getSmtpPassword()); settingsService.setSmtpPassword(command.getSmtpPassword());
} }
settingsService.save();
return "redirect:advancedSettings.view"; return "redirect:advancedSettings.view";
} }

@ -1,35 +1,9 @@
package org.libresonic.player.controller; package org.libresonic.player.controller;
import org.apache.commons.lang.ObjectUtils;
import org.libresonic.player.service.SettingsService;
import javax.servlet.http.HttpServletRequest;
/** /**
* This class has been created to refactor code previously present * This class has been created to refactor code previously present
* in the MultiController. * in the MultiController.
*/ */
public class ControllerUtils { public class ControllerUtils {
public static void updatePortAndContextPath(HttpServletRequest request, SettingsService settingsService) {
int port = Integer.parseInt(System.getProperty("libresonic.port", String.valueOf(request.getLocalPort())));
int httpsPort = Integer.parseInt(System.getProperty("libresonic.httpsPort", "0"));
String contextPath = request.getContextPath().replace("/", "");
if (settingsService.getPort() != port) {
settingsService.setPort(port);
settingsService.save();
}
if (settingsService.getHttpsPort() != httpsPort) {
settingsService.setHttpsPort(httpsPort);
settingsService.save();
}
if (!ObjectUtils.equals(settingsService.getUrlRedirectContextPath(), contextPath)) {
settingsService.setUrlRedirectContextPath(contextPath);
settingsService.save();
}
}
} }

@ -48,7 +48,7 @@ public class DBController {
@Autowired @Autowired
private DaoHelper daoHelper; private DaoHelper daoHelper;
@RequestMapping(method = RequestMethod.GET) @RequestMapping(method = { RequestMethod.GET, RequestMethod.POST })
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String, Object> map = new HashMap<String, Object>(); Map<String, Object> map = new HashMap<String, Object>();

@ -41,7 +41,6 @@ public class GettingStartedController {
@RequestMapping(method = RequestMethod.GET) @RequestMapping(method = RequestMethod.GET)
public ModelAndView gettingStarted(HttpServletRequest request) { public ModelAndView gettingStarted(HttpServletRequest request) {
ControllerUtils.updatePortAndContextPath(request,settingsService);
if (request.getParameter("hide") != null) { if (request.getParameter("hide") != null) {
settingsService.setGettingStartedEnabled(false); settingsService.setGettingStartedEnabled(false);

@ -29,7 +29,6 @@ public class IndexController {
@RequestMapping(method = { RequestMethod.GET}) @RequestMapping(method = { RequestMethod.GET})
public ModelAndView index(HttpServletRequest request) { public ModelAndView index(HttpServletRequest request) {
ControllerUtils.updatePortAndContextPath(request,settingsService);
UserSettings userSettings = settingsService.getUserSettings(securityService.getCurrentUsername(request)); UserSettings userSettings = settingsService.getUserSettings(securityService.getCurrentUsername(request));
Map<String, Object> map = new HashMap<String, Object>(); Map<String, Object> map = new HashMap<String, Object>();

@ -80,7 +80,7 @@ public class StatusController {
} }
private static class TransferStatusHolder { public static class TransferStatusHolder {
private TransferStatus transferStatus; private TransferStatus transferStatus;
private boolean isStream; private boolean isStream;
private boolean isDownload; private boolean isDownload;

@ -69,11 +69,23 @@ public class UserDao extends AbstractDao {
* Returns the user with the given username. * Returns the user with the given username.
* *
* @param username The username used when logging in. * @param username The username used when logging in.
* @param caseSensitive
* @return The user, or <code>null</code> if not found. * @return The user, or <code>null</code> if not found.
*/ */
public User getUserByName(String username) { public User getUserByName(String username, boolean caseSensitive) {
String sql = "select " + USER_COLUMNS + " from " + getUserTable() + " where username=?"; String sql;
User user = queryOne(sql, userRowMapper, username); if(caseSensitive) {
sql = "select " + USER_COLUMNS + " from " + getUserTable() + " where username=?";
} else {
sql = "select " + USER_COLUMNS + " from " + getUserTable() + " where UPPER(username)=UPPER(?)";
}
List<User> users = query(sql, userRowMapper, username);
User user = null;
if(users.size() == 1) {
user = users.iterator().next();
} else if (users.size() > 1) {
throw new RuntimeException("Too many matching users");
}
if(user != null) { if(user != null) {
readRoles(user); readRoles(user);
} }

@ -0,0 +1,133 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.libresonic.player.security;
import org.libresonic.player.Logger;
import org.libresonic.player.domain.User;
import org.libresonic.player.service.SecurityService;
import org.libresonic.player.service.SettingsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.ldap.ppolicy.PasswordPolicyControl;
import org.springframework.security.ldap.ppolicy.PasswordPolicyResponseControl;
import org.springframework.security.ldap.userdetails.LdapUserDetailsImpl;
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;
import org.springframework.stereotype.Component;
import java.util.Collection;
@Component
public class LibresonicUserDetailsContextMapper implements UserDetailsContextMapper {
// ~ Instance fields
// ================================================================================================
private final Logger logger = Logger.getLogger(LibresonicUserDetailsContextMapper.class);
private String passwordAttributeName = "userPassword";
@Autowired
SecurityService securityService;
@Autowired
SettingsService settingsService;
// ~ Methods
// ========================================================================================================
public UserDetails mapUserFromContext(DirContextOperations ctx, String username,
Collection<? extends GrantedAuthority> authorities) {
String dn = ctx.getNameInNamespace();
logger.debug("Mapping user details from context with DN: " + dn);
// User must be defined in Libresonic, unless auto-shadowing is enabled.
User user = securityService.getUserByName(username, false);
if (user == null && !settingsService.isLdapAutoShadowing()) {
throw new BadCredentialsException("User does not exist.");
}
if (user == null) {
User newUser = new User(username, "", null, true, 0L, 0L, 0L);
newUser.setStreamRole(true);
newUser.setSettingsRole(true);
securityService.createUser(newUser);
logger.info("Created local user '" + username + "' for DN " + dn);
user = securityService.getUserByName(username, false);
}
// LDAP authentication must be enabled for the given user.
if (!user.isLdapAuthenticated()) {
throw new BadCredentialsException("LDAP authentication disabled for user.");
}
LdapUserDetailsImpl.Essence essence = new LdapUserDetailsImpl.Essence();
essence.setDn(dn);
Object passwordValue = ctx.getObjectAttribute(passwordAttributeName);
if (passwordValue != null) {
essence.setPassword(mapPassword(passwordValue));
}
essence.setUsername(user.getUsername());
// Add the supplied authorities
for (GrantedAuthority authority : securityService.getGrantedAuthorities(user.getUsername())) {
essence.addAuthority(authority);
}
// Check for PPolicy data
PasswordPolicyResponseControl ppolicy = (PasswordPolicyResponseControl) ctx
.getObjectAttribute(PasswordPolicyControl.OID);
if (ppolicy != null) {
essence.setTimeBeforeExpiration(ppolicy.getTimeBeforeExpiration());
essence.setGraceLoginsRemaining(ppolicy.getGraceLoginsRemaining());
}
return essence.createUserDetails();
}
public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
throw new UnsupportedOperationException(
"LdapUserDetailsMapper only supports reading from a context. Please"
+ "use a subclass if mapUserToContext() is required.");
}
/**
* Extension point to allow customized creation of the user's password from the
* attribute stored in the directory.
*
* @param passwordValue the value of the password attribute
* @return a String representation of the password.
*/
protected String mapPassword(Object passwordValue) {
if (!(passwordValue instanceof String)) {
// Assume it's binary
passwordValue = new String((byte[]) passwordValue);
}
return (String) passwordValue;
}
}

@ -1,6 +1,7 @@
package org.libresonic.player.security; package org.libresonic.player.security;
import org.libresonic.player.service.SecurityService; import org.libresonic.player.service.SecurityService;
import org.libresonic.player.service.SettingsService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -18,20 +19,37 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired @Autowired
private SecurityService securityService; private SecurityService securityService;
@Autowired @Autowired
private CsrfSecurityRequestMatcher csrfSecurityRequestMatcher; private CsrfSecurityRequestMatcher csrfSecurityRequestMatcher;
@Autowired @Autowired
LoginFailureLogger loginFailureLogger; LoginFailureLogger loginFailureLogger;
@Autowired
SettingsService settingsService;
@Autowired
LibresonicUserDetailsContextMapper libresonicUserDetailsContextMapper;
@Override @Override
@Bean(name = "authenticationManager") @Bean(name = "authenticationManager")
public AuthenticationManager authenticationManagerBean() throws Exception { public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean(); return super.authenticationManagerBean();
} }
@Autowired @Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
if (settingsService.isLdapEnabled()) {
auth.ldapAuthentication()
.contextSource()
.managerDn(settingsService.getLdapManagerDn())
.managerPassword(settingsService.getLdapManagerPassword())
.url(settingsService.getLdapUrl())
.and()
.userSearchFilter(settingsService.getLdapSearchFilter())
.userDetailsContextMapper(libresonicUserDetailsContextMapper);
}
auth.userDetailsService(securityService); auth.userDetailsService(securityService);
} }
@ -89,7 +107,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.passwordParameter("j_password") .passwordParameter("j_password")
// see http://docs.spring.io/spring-security/site/docs/3.2.4.RELEASE/reference/htmlsingle/#csrf-logout // see http://docs.spring.io/spring-security/site/docs/3.2.4.RELEASE/reference/htmlsingle/#csrf-logout
.and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET")).logoutSuccessUrl("/login?logout") .and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET")).logoutSuccessUrl("/login?logout")
.and().rememberMe().userDetailsService(securityService).key("libresonic"); .and().rememberMe().key("libresonic");
} }
} }

@ -461,8 +461,7 @@ public class PlaylistService {
for (Object obj : tracks) { for (Object obj : tracks) {
Element track = (Element) obj; Element track = (Element) obj;
String location = track.getChildText("location", ns); String location = track.getChildText("location", ns);
if (location != null && location.startsWith("file://")) { if (location != null) {
location = location.replaceFirst("file://", "");
MediaFile file = getMediaFile(location); MediaFile file = getMediaFile(location);
if (file != null) { if (file != null) {
ok.add(file); ok.add(file);

@ -62,11 +62,22 @@ public class SecurityService implements UserDetailsService {
* @throws DataAccessException If user could not be found for a repository-specific reason. * @throws DataAccessException If user could not be found for a repository-specific reason.
*/ */
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
User user = getUserByName(username); return loadUserByUsername(username, true);
}
public UserDetails loadUserByUsername(String username, boolean caseSensitive)
throws UsernameNotFoundException, DataAccessException {
User user = getUserByName(username, caseSensitive);
if (user == null) { if (user == null) {
throw new UsernameNotFoundException("User \"" + username + "\" was not found."); throw new UsernameNotFoundException("User \"" + username + "\" was not found.");
} }
List<GrantedAuthority> authorities = getGrantedAuthorities(username);
return new org.springframework.security.core.userdetails.User(username, user.getPassword(), authorities);
}
public List<GrantedAuthority> getGrantedAuthorities(String username) {
String[] roles = userDao.getRolesForUser(username); String[] roles = userDao.getRolesForUser(username);
List<GrantedAuthority> authorities = new ArrayList<>(); List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("IS_AUTHENTICATED_ANONYMOUSLY")); authorities.add(new SimpleGrantedAuthority("IS_AUTHENTICATED_ANONYMOUSLY"));
@ -74,8 +85,7 @@ public class SecurityService implements UserDetailsService {
for (int i = 0; i < roles.length; i++) { for (int i = 0; i < roles.length; i++) {
authorities.add(new SimpleGrantedAuthority("ROLE_" + roles[i].toUpperCase())); authorities.add(new SimpleGrantedAuthority("ROLE_" + roles[i].toUpperCase()));
} }
return authorities;
return new org.springframework.security.core.userdetails.User(username, user.getPassword(), authorities);
} }
/** /**
@ -86,7 +96,7 @@ public class SecurityService implements UserDetailsService {
*/ */
public User getCurrentUser(HttpServletRequest request) { public User getCurrentUser(HttpServletRequest request) {
String username = getCurrentUsername(request); String username = getCurrentUsername(request);
return username == null ? null : userDao.getUserByName(username); return username == null ? null : getUserByName(username);
} }
/** /**
@ -106,7 +116,17 @@ public class SecurityService implements UserDetailsService {
* @return The user, or <code>null</code> if not found. * @return The user, or <code>null</code> if not found.
*/ */
public User getUserByName(String username) { public User getUserByName(String username) {
return userDao.getUserByName(username); return getUserByName(username, true);
}
/**
* Returns the user with the given username
* @param username
* @param caseSensitive If false, will do a case insensitive search
* @return
*/
public User getUserByName(String username, boolean caseSensitive) {
return userDao.getUserByName(username, caseSensitive);
} }
/** /**

@ -371,6 +371,7 @@ advancedsettings.ldapsearchfilter = LDAP search filter
advancedsettings.ldapmanagerdn = LDAP manager DN<br><div class="detail">(Optional)</div> advancedsettings.ldapmanagerdn = LDAP manager DN<br><div class="detail">(Optional)</div>
advancedsettings.ldapmanagerpassword = Password advancedsettings.ldapmanagerpassword = Password
advancedsettings.ldapautoshadowing = Automatically create users in {0} advancedsettings.ldapautoshadowing = Automatically create users in {0}
advancedsettings.ldapRequiresRestart = LDAP settings require a restart to take effect
advancedsettings.smtpPort = SMTP port advancedsettings.smtpPort = SMTP port
advancedsettings.smtpServer = SMTP server advancedsettings.smtpServer = SMTP server
advancedsettings.smtpEncryption = SMTP encryption advancedsettings.smtpEncryption = SMTP encryption

@ -138,6 +138,8 @@
</tr> </tr>
</table> </table>
<p class="warning"><fmt:message key="advancedsettings.ldapRequiresRestart"/></p>
<input type="submit" value="<fmt:message key="common.save"/>" style="margin-right:0.3em"> <input type="submit" value="<fmt:message key="common.save"/>" style="margin-right:0.3em">
<input type="button" value="<fmt:message key="common.cancel"/>" onclick="location.href='nowPlaying.view'"> <input type="button" value="<fmt:message key="common.cancel"/>" onclick="location.href='nowPlaying.view'">

@ -278,6 +278,7 @@
<div id="commentForm" style="display:none"> <div id="commentForm" style="display:none">
<form method="post" action="setMusicFileInfo.view"> <form method="post" action="setMusicFileInfo.view">
<sec:csrfInput />
<input type="hidden" name="action" value="comment"> <input type="hidden" name="action" value="comment">
<input type="hidden" name="id" value="${model.dir.id}"> <input type="hidden" name="id" value="${model.dir.id}">
<textarea name="comment" rows="6" cols="70">${model.dir.comment}</textarea> <textarea name="comment" rows="6" cols="70">${model.dir.comment}</textarea>

@ -208,6 +208,7 @@
<div id="commentForm" style="display:none"> <div id="commentForm" style="display:none">
<form method="post" action="setMusicFileInfo.view"> <form method="post" action="setMusicFileInfo.view">
<sec:csrfInput />
<input type="hidden" name="action" value="comment"> <input type="hidden" name="action" value="comment">
<input type="hidden" name="id" value="${model.dir.id}"> <input type="hidden" name="id" value="${model.dir.id}">
<textarea name="comment" rows="6" cols="70">${model.dir.comment}</textarea> <textarea name="comment" rows="6" cols="70">${model.dir.comment}</textarea>

@ -91,6 +91,7 @@
<body class="mainframe bgcolor1" onload="search()"> <body class="mainframe bgcolor1" onload="search()">
<h1><fmt:message key="changecoverart.title"/></h1> <h1><fmt:message key="changecoverart.title"/></h1>
<form action="javascript:search()"> <form action="javascript:search()">
<sec:csrfInput />
<table class="indent"><tr> <table class="indent"><tr>
<td><input id="artist" name="artist" placeholder="<fmt:message key="changecoverart.artist"/>" size="35" type="text" value="${model.artist}" onclick="select()"/></td> <td><input id="artist" name="artist" placeholder="<fmt:message key="changecoverart.artist"/>" size="35" type="text" value="${model.artist}" onclick="select()"/></td>
<td><input id="album" name="album" placeholder="<fmt:message key="changecoverart.album"/>" size="35" type="text" value="${model.album}" onclick="select()"/></td> <td><input id="album" name="album" placeholder="<fmt:message key="changecoverart.album"/>" size="35" type="text" value="${model.album}" onclick="select()"/></td>
@ -99,6 +100,7 @@
</form> </form>
<form action="javascript:setImage(dwr.util.getValue('url'))"> <form action="javascript:setImage(dwr.util.getValue('url'))">
<sec:csrfInput />
<table><tr> <table><tr>
<td><label for="url"><fmt:message key="changecoverart.address"/></label></td> <td><label for="url"><fmt:message key="changecoverart.address"/></label></td>
<td style="padding-left:0.5em"><input type="text" name="url" size="50" id="url" value="http://" onclick="select()"/></td> <td style="padding-left:0.5em"><input type="text" name="url" size="50" id="url" value="http://" onclick="select()"/></td>

@ -7,6 +7,7 @@
<h1>Database query</h1> <h1>Database query</h1>
<form method="post" action="db.view"> <form method="post" action="db.view">
<sec:csrfInput />
<textarea rows="10" cols="80" id="query" name="query" style="margin-top:1em">${model.query}</textarea> <textarea rows="10" cols="80" id="query" name="query" style="margin-top:1em">${model.query}</textarea>
<input type="submit" value="<fmt:message key="common.ok"/>"> <input type="submit" value="<fmt:message key="common.ok"/>">
</form> </form>

@ -34,6 +34,7 @@
</c:import> </c:import>
<form method="post" action="dlnaSettings.view"> <form method="post" action="dlnaSettings.view">
<sec:csrfInput />
<div> <div>
<input type="checkbox" name="dlnaEnabled" id="dlnaEnabled" class="checkbox" <input type="checkbox" name="dlnaEnabled" id="dlnaEnabled" class="checkbox"

@ -31,6 +31,16 @@
%> %>
<table class="ruleTable indent"> <table class="ruleTable indent">
<tr><td class="ruleTableHeader">Status</td>
<td class="ruleTableCell"><c:out value="${status}" /></td></tr>
<tr><td class="ruleTableHeader">Error</td>
<td class="ruleTableCell"><c:out value="${error}" /></td></tr>
<tr><td class="ruleTableHeader">Message</td>
<td class="ruleTableCell"><c:out value="${message}" /></td></tr>
<tr><td class="ruleTableHeader">Path</td>
<td class="ruleTableCell"><c:out value="${path}" /></td></tr>
<tr><td class="ruleTableHeader">Time</td>
<td class="ruleTableCell"><c:out value="${timestamp}" /></td></tr>
<tr><td class="ruleTableHeader">Exception</td> <tr><td class="ruleTableHeader">Exception</td>
<td class="ruleTableCell"><c:out value="${exception}" /></td></tr> <td class="ruleTableCell"><c:out value="${exception}" /></td></tr>
<tr><td class="ruleTableHeader">Java version</td> <tr><td class="ruleTableHeader">Java version</td>

@ -30,6 +30,7 @@
<fmt:message key="importPlaylist.text"/> <fmt:message key="importPlaylist.text"/>
</div> </div>
<form method="post" enctype="multipart/form-data" action="importPlaylist.view"> <form method="post" enctype="multipart/form-data" action="importPlaylist.view">
<sec:csrfInput />
<input type="file" id="file" name="file" size="40"/> <input type="file" id="file" name="file" size="40"/>
<input type="submit" value="<fmt:message key="common.ok"/>"/> <input type="submit" value="<fmt:message key="common.ok"/>"/>
</form> </form>

@ -12,6 +12,7 @@
</c:import> </c:import>
<form method="post" action="internetRadioSettings.view"> <form method="post" action="internetRadioSettings.view">
<sec:csrfInput />
<table class="indent"> <table class="indent">
<tr> <tr>
<th><fmt:message key="internetradiosettings.name"/></th> <th><fmt:message key="internetradiosettings.name"/></th>

@ -62,6 +62,7 @@
} catch(e) { return; } } catch(e) { return; }
elements = form.getElementsByTagName("input"); elements = form.getElementsByTagName("input");
for (var i = 0; i < elements.length; i++) { for (var i = 0; i < elements.length; i++) {
if (elements[i].type == "hidden") continue;
if (elements[i].type == "submit") continue; if (elements[i].type == "submit") continue;
if (data[elements[i].name]) elements[i].value = data[elements[i].name]; if (data[elements[i].name]) elements[i].value = data[elements[i].name];
} }
@ -87,9 +88,17 @@
var data = {} var data = {}
var elements = []; var elements = [];
elements = form.getElementsByTagName("input"); elements = form.getElementsByTagName("input");
for (var i = 0; i < elements.length; i++) data[elements[i].name] = elements[i].value; for (var i = 0; i < elements.length; i++) {
if (elements[i].type == "hidden") continue;
if (elements[i].type == "submit") continue;
data[elements[i].name] = elements[i].value;
}
elements = form.getElementsByTagName("select"); elements = form.getElementsByTagName("select");
for (var i = 0; i < elements.length; i++) data[elements[i].name] = elements[i].value; for (var i = 0; i < elements.length; i++) {
if (elements[i].type == "hidden") continue;
if (elements[i].type == "submit") continue;
data[elements[i].name] = elements[i].value;
}
localStorage.setItem("randomPlayQueue", JSON.stringify(data)); localStorage.setItem("randomPlayQueue", JSON.stringify(data));
} }
@ -122,6 +131,7 @@
</h2> </h2>
<form id="randomPlayQueue" method="post" action="randomPlayQueue.view?"> <form id="randomPlayQueue" method="post" action="randomPlayQueue.view?">
<sec:csrfInput />
<table> <table>
<tr> <tr>
<td><fmt:message key="more.random.text"/></td> <td><fmt:message key="more.random.text"/></td>
@ -291,6 +301,7 @@
</h2> </h2>
<form method="post" enctype="multipart/form-data" action="upload.view"> <form method="post" enctype="multipart/form-data" action="upload.view">
<sec:csrfInput />
<table> <table>
<tr> <tr>
<td><fmt:message key="more.upload.source"/></td> <td><fmt:message key="more.upload.source"/></td>

@ -241,6 +241,7 @@
</form:form> </form:form>
<form method="post" enctype="multipart/form-data" action="avatarUpload.view"> <form method="post" enctype="multipart/form-data" action="avatarUpload.view">
<sec:csrfInput />
<table> <table>
<tr> <tr>
<td style="padding-right:1em"><fmt:message key="personalsettings.avatar.changecustom"/></td> <td style="padding-right:1em"><fmt:message key="personalsettings.avatar.changecustom"/></td>

@ -8,6 +8,7 @@
<body class="mainframe bgcolor1" onload="document.getElementById('usernameOrEmail').focus()"> <body class="mainframe bgcolor1" onload="document.getElementById('usernameOrEmail').focus()">
<form action="recover.view" method="POST"> <form action="recover.view" method="POST">
<sec:csrfInput />
<div class="bgcolor2 shadow" style="padding:20px 50px 20px 50px; margin-top:100px;margin-left:50px;margin-right:50px"> <div class="bgcolor2 shadow" style="padding:20px 50px 20px 50px; margin-top:100px;margin-left:50px;margin-right:50px">
<div style="margin-left: auto; margin-right: auto; width: 45em"> <div style="margin-left: auto; margin-right: auto; width: 45em">

@ -14,6 +14,7 @@
</c:import> </c:import>
<form method="post" action="shareSettings.view"> <form method="post" action="shareSettings.view">
<sec:csrfInput />
<table class="music indent"> <table class="music indent">
<tr> <tr>

@ -34,6 +34,7 @@
</c:import> </c:import>
<form method="post" action="sonosSettings.view"> <form method="post" action="sonosSettings.view">
<sec:csrfInput />
<div> <div>
<input type="checkbox" name="sonosEnabled" id="sonosEnabled" class="checkbox" <input type="checkbox" name="sonosEnabled" id="sonosEnabled" class="checkbox"

@ -125,6 +125,7 @@
<td style="padding-left:1em"> <td style="padding-left:1em">
<form method="post" action="search.view" target="main" name="searchForm"> <form method="post" action="search.view" target="main" name="searchForm">
<sec:csrfInput />
<td><input type="text" name="query" id="query" size="28" placeholder="${search}" onclick="select();" <td><input type="text" name="query" id="query" size="28" placeholder="${search}" onclick="select();"
onkeyup="triggerInstantSearch();"></td> onkeyup="triggerInstantSearch();"></td>
<td><a href="javascript:document.searchForm.submit()"><img src="<spring:theme code="searchImage"/>" alt="${search}" title="${search}"></a></td> <td><a href="javascript:document.searchForm.submit()"><img src="<spring:theme code="searchImage"/>" alt="${search}" title="${search}"></a></td>

@ -14,6 +14,7 @@
</c:import> </c:import>
<form method="post" action="transcodingSettings.view"> <form method="post" action="transcodingSettings.view">
<sec:csrfInput />
<table class="indent"> <table class="indent">
<tr> <tr>
<th><fmt:message key="transcodingsettings.name"/></th> <th><fmt:message key="transcodingsettings.name"/></th>

@ -115,15 +115,15 @@ public class UserDaoTestCase extends DaoTestCaseBean2 {
User user = new User("sindre", "secret", null); User user = new User("sindre", "secret", null);
userDao.createUser(user); userDao.createUser(user);
User newUser = userDao.getUserByName("sindre"); User newUser = userDao.getUserByName("sindre", true);
assertNotNull("Error in getUserByName().", newUser); assertNotNull("Error in getUserByName().", newUser);
assertUserEquals(user, newUser); assertUserEquals(user, newUser);
assertNull("Error in getUserByName().", userDao.getUserByName("sindre2")); assertNull("Error in getUserByName().", userDao.getUserByName("sindre2", true));
assertNull("Error in getUserByName().", userDao.getUserByName("sindre ")); assertNull("Error in getUserByName().", userDao.getUserByName("sindre ", true));
assertNull("Error in getUserByName().", userDao.getUserByName("bente")); assertNull("Error in getUserByName().", userDao.getUserByName("bente", true));
assertNull("Error in getUserByName().", userDao.getUserByName("")); assertNull("Error in getUserByName().", userDao.getUserByName("", true));
assertNull("Error in getUserByName().", userDao.getUserByName(null)); assertNull("Error in getUserByName().", userDao.getUserByName(null, true));
} }
@Test @Test

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save