|
|
@ -23,8 +23,12 @@ import org.airsonic.player.ajax.LyricsInfo; |
|
|
|
import org.airsonic.player.ajax.LyricsService; |
|
|
|
import org.airsonic.player.ajax.LyricsService; |
|
|
|
import org.airsonic.player.ajax.PlayQueueService; |
|
|
|
import org.airsonic.player.ajax.PlayQueueService; |
|
|
|
import org.airsonic.player.command.UserSettingsCommand; |
|
|
|
import org.airsonic.player.command.UserSettingsCommand; |
|
|
|
import org.airsonic.player.dao.*; |
|
|
|
import org.airsonic.player.dao.AlbumDao; |
|
|
|
|
|
|
|
import org.airsonic.player.dao.ArtistDao; |
|
|
|
|
|
|
|
import org.airsonic.player.dao.MediaFileDao; |
|
|
|
|
|
|
|
import org.airsonic.player.dao.PlayQueueDao; |
|
|
|
import org.airsonic.player.domain.*; |
|
|
|
import org.airsonic.player.domain.*; |
|
|
|
|
|
|
|
import org.airsonic.player.domain.Bookmark; |
|
|
|
import org.airsonic.player.service.*; |
|
|
|
import org.airsonic.player.service.*; |
|
|
|
import org.airsonic.player.util.Pair; |
|
|
|
import org.airsonic.player.util.Pair; |
|
|
|
import org.airsonic.player.util.StringUtil; |
|
|
|
import org.airsonic.player.util.StringUtil; |
|
|
@ -43,7 +47,6 @@ import org.springframework.web.servlet.ModelAndView; |
|
|
|
import org.subsonic.restapi.*; |
|
|
|
import org.subsonic.restapi.*; |
|
|
|
import org.subsonic.restapi.PodcastStatus; |
|
|
|
import org.subsonic.restapi.PodcastStatus; |
|
|
|
|
|
|
|
|
|
|
|
import javax.annotation.PostConstruct; |
|
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest; |
|
|
|
import javax.servlet.http.HttpServletRequest; |
|
|
|
import javax.servlet.http.HttpServletRequestWrapper; |
|
|
|
import javax.servlet.http.HttpServletRequestWrapper; |
|
|
|
import javax.servlet.http.HttpServletResponse; |
|
|
|
import javax.servlet.http.HttpServletResponse; |
|
|
@ -65,9 +68,9 @@ import static org.springframework.web.bind.ServletRequestUtils.*; |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@Controller |
|
|
|
@Controller |
|
|
|
@RequestMapping(value = "/rest", method = {RequestMethod.GET, RequestMethod.POST}) |
|
|
|
@RequestMapping(value = "/rest", method = {RequestMethod.GET, RequestMethod.POST}) |
|
|
|
public class RESTController { |
|
|
|
public class SubsonicRESTController { |
|
|
|
|
|
|
|
|
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(RESTController.class); |
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(SubsonicRESTController.class); |
|
|
|
|
|
|
|
|
|
|
|
@Autowired |
|
|
|
@Autowired |
|
|
|
private SettingsService settingsService; |
|
|
|
private SettingsService settingsService; |
|
|
@ -124,7 +127,7 @@ public class RESTController { |
|
|
|
@Autowired |
|
|
|
@Autowired |
|
|
|
private AlbumDao albumDao; |
|
|
|
private AlbumDao albumDao; |
|
|
|
@Autowired |
|
|
|
@Autowired |
|
|
|
private BookmarkDao bookmarkDao; |
|
|
|
private BookmarkService bookmarkService; |
|
|
|
@Autowired |
|
|
|
@Autowired |
|
|
|
private PlayQueueDao playQueueDao; |
|
|
|
private PlayQueueDao playQueueDao; |
|
|
|
@Autowired |
|
|
|
@Autowired |
|
|
@ -136,18 +139,6 @@ public class RESTController { |
|
|
|
private static final String NOT_YET_IMPLEMENTED = "Not yet implemented"; |
|
|
|
private static final String NOT_YET_IMPLEMENTED = "Not yet implemented"; |
|
|
|
private static final String NO_LONGER_SUPPORTED = "No longer supported"; |
|
|
|
private static final String NO_LONGER_SUPPORTED = "No longer supported"; |
|
|
|
|
|
|
|
|
|
|
|
@PostConstruct |
|
|
|
|
|
|
|
public void init() { |
|
|
|
|
|
|
|
refreshBookmarkCache(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void refreshBookmarkCache() { |
|
|
|
|
|
|
|
bookmarkCache.clear(); |
|
|
|
|
|
|
|
for (org.airsonic.player.domain.Bookmark bookmark : bookmarkDao.getBookmarks()) { |
|
|
|
|
|
|
|
bookmarkCache.put(BookmarkKey.forBookmark(bookmark), bookmark); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@RequestMapping(value = "/ping") |
|
|
|
@RequestMapping(value = "/ping") |
|
|
|
public void ping(HttpServletRequest request, HttpServletResponse response) throws Exception { |
|
|
|
public void ping(HttpServletRequest request, HttpServletResponse response) throws Exception { |
|
|
|
Response res = createResponse(); |
|
|
|
Response res = createResponse(); |
|
|
@ -1337,12 +1328,12 @@ public class RESTController { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@RequestMapping(value = "/download") |
|
|
|
@RequestMapping(value = "/download") |
|
|
|
public ModelAndView download(HttpServletRequest request, HttpServletResponse response) throws Exception { |
|
|
|
public void download(HttpServletRequest request, HttpServletResponse response) throws Exception { |
|
|
|
request = wrapRequest(request); |
|
|
|
request = wrapRequest(request); |
|
|
|
org.airsonic.player.domain.User user = securityService.getCurrentUser(request); |
|
|
|
org.airsonic.player.domain.User user = securityService.getCurrentUser(request); |
|
|
|
if (!user.isDownloadRole()) { |
|
|
|
if (!user.isDownloadRole()) { |
|
|
|
error(request, response, ErrorCode.NOT_AUTHORIZED, user.getUsername() + " is not authorized to download files."); |
|
|
|
error(request, response, ErrorCode.NOT_AUTHORIZED, user.getUsername() + " is not authorized to download files."); |
|
|
|
return null; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
long ifModifiedSince = request.getDateHeader("If-Modified-Since"); |
|
|
|
long ifModifiedSince = request.getDateHeader("If-Modified-Since"); |
|
|
@ -1350,49 +1341,47 @@ public class RESTController { |
|
|
|
|
|
|
|
|
|
|
|
if (ifModifiedSince != -1 && lastModified != -1 && lastModified <= ifModifiedSince) { |
|
|
|
if (ifModifiedSince != -1 && lastModified != -1 && lastModified <= ifModifiedSince) { |
|
|
|
response.sendError(HttpServletResponse.SC_NOT_MODIFIED); |
|
|
|
response.sendError(HttpServletResponse.SC_NOT_MODIFIED); |
|
|
|
return null; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (lastModified != -1) { |
|
|
|
if (lastModified != -1) { |
|
|
|
response.setDateHeader("Last-Modified", lastModified); |
|
|
|
response.setDateHeader("Last-Modified", lastModified); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return downloadController.handleRequest(request, response); |
|
|
|
downloadController.handleRequest(request, response); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@RequestMapping(value = "/stream") |
|
|
|
@RequestMapping(value = "/stream") |
|
|
|
public ModelAndView stream(HttpServletRequest request, HttpServletResponse response) throws Exception { |
|
|
|
public void stream(HttpServletRequest request, HttpServletResponse response) throws Exception { |
|
|
|
request = wrapRequest(request); |
|
|
|
request = wrapRequest(request); |
|
|
|
org.airsonic.player.domain.User user = securityService.getCurrentUser(request); |
|
|
|
org.airsonic.player.domain.User user = securityService.getCurrentUser(request); |
|
|
|
if (!user.isStreamRole()) { |
|
|
|
if (!user.isStreamRole()) { |
|
|
|
error(request, response, ErrorCode.NOT_AUTHORIZED, user.getUsername() + " is not authorized to play files."); |
|
|
|
error(request, response, ErrorCode.NOT_AUTHORIZED, user.getUsername() + " is not authorized to play files."); |
|
|
|
return null; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
streamController.handleRequest(request, response); |
|
|
|
streamController.handleRequest(request, response); |
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@RequestMapping(value = "/hls") |
|
|
|
@RequestMapping(value = "/hls") |
|
|
|
public ModelAndView hls(HttpServletRequest request, HttpServletResponse response) throws Exception { |
|
|
|
public void hls(HttpServletRequest request, HttpServletResponse response) throws Exception { |
|
|
|
request = wrapRequest(request); |
|
|
|
request = wrapRequest(request); |
|
|
|
org.airsonic.player.domain.User user = securityService.getCurrentUser(request); |
|
|
|
org.airsonic.player.domain.User user = securityService.getCurrentUser(request); |
|
|
|
if (!user.isStreamRole()) { |
|
|
|
if (!user.isStreamRole()) { |
|
|
|
error(request, response, ErrorCode.NOT_AUTHORIZED, user.getUsername() + " is not authorized to play files."); |
|
|
|
error(request, response, ErrorCode.NOT_AUTHORIZED, user.getUsername() + " is not authorized to play files."); |
|
|
|
return null; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
int id = getRequiredIntParameter(request, "id"); |
|
|
|
int id = getRequiredIntParameter(request, "id"); |
|
|
|
MediaFile video = mediaFileDao.getMediaFile(id); |
|
|
|
MediaFile video = mediaFileDao.getMediaFile(id); |
|
|
|
if (video == null || video.isDirectory()) { |
|
|
|
if (video == null || video.isDirectory()) { |
|
|
|
error(request, response, ErrorCode.NOT_FOUND, "Video not found."); |
|
|
|
error(request, response, ErrorCode.NOT_FOUND, "Video not found."); |
|
|
|
return null; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
if (!securityService.isFolderAccessAllowed(video, user.getUsername())) { |
|
|
|
if (!securityService.isFolderAccessAllowed(video, user.getUsername())) { |
|
|
|
error(request, response, ErrorCode.NOT_AUTHORIZED, "Access denied"); |
|
|
|
error(request, response, ErrorCode.NOT_AUTHORIZED, "Access denied"); |
|
|
|
return null; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
hlsController.handleRequest(request, response); |
|
|
|
hlsController.handleRequest(request, response); |
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@RequestMapping(value = "/scrobble") |
|
|
|
@RequestMapping(value = "/scrobble") |
|
|
@ -1702,7 +1691,7 @@ public class RESTController { |
|
|
|
String username = securityService.getCurrentUsername(request); |
|
|
|
String username = securityService.getCurrentUsername(request); |
|
|
|
|
|
|
|
|
|
|
|
Bookmarks result = new Bookmarks(); |
|
|
|
Bookmarks result = new Bookmarks(); |
|
|
|
for (org.airsonic.player.domain.Bookmark bookmark : bookmarkDao.getBookmarks(username)) { |
|
|
|
for (Bookmark bookmark : bookmarkService.getBookmarks(username)) { |
|
|
|
org.subsonic.restapi.Bookmark b = new org.subsonic.restapi.Bookmark(); |
|
|
|
org.subsonic.restapi.Bookmark b = new org.subsonic.restapi.Bookmark(); |
|
|
|
result.getBookmark().add(b); |
|
|
|
result.getBookmark().add(b); |
|
|
|
b.setPosition(bookmark.getPositionMillis()); |
|
|
|
b.setPosition(bookmark.getPositionMillis()); |
|
|
@ -1729,9 +1718,8 @@ public class RESTController { |
|
|
|
String comment = request.getParameter("comment"); |
|
|
|
String comment = request.getParameter("comment"); |
|
|
|
Date now = new Date(); |
|
|
|
Date now = new Date(); |
|
|
|
|
|
|
|
|
|
|
|
org.airsonic.player.domain.Bookmark bookmark = new org.airsonic.player.domain.Bookmark(0, mediaFileId, position, username, comment, now, now); |
|
|
|
Bookmark bookmark = new Bookmark(0, mediaFileId, position, username, comment, now, now); |
|
|
|
bookmarkDao.createOrUpdateBookmark(bookmark); |
|
|
|
bookmarkService.createOrUpdateBookmark(bookmark); |
|
|
|
refreshBookmarkCache(); |
|
|
|
|
|
|
|
writeEmptyResponse(request, response); |
|
|
|
writeEmptyResponse(request, response); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1741,8 +1729,7 @@ public class RESTController { |
|
|
|
|
|
|
|
|
|
|
|
String username = securityService.getCurrentUsername(request); |
|
|
|
String username = securityService.getCurrentUsername(request); |
|
|
|
int mediaFileId = getRequiredIntParameter(request, "id"); |
|
|
|
int mediaFileId = getRequiredIntParameter(request, "id"); |
|
|
|
bookmarkDao.deleteBookmark(username, mediaFileId); |
|
|
|
bookmarkService.deleteBookmark(username, mediaFileId); |
|
|
|
refreshBookmarkCache(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
writeEmptyResponse(request, response); |
|
|
|
writeEmptyResponse(request, response); |
|
|
|
} |
|
|
|
} |
|
|
@ -1954,15 +1941,15 @@ public class RESTController { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@RequestMapping(value = "/getCoverArt") |
|
|
|
@RequestMapping(value = "/getCoverArt") |
|
|
|
public ModelAndView getCoverArt(HttpServletRequest request, HttpServletResponse response) throws Exception { |
|
|
|
public void getCoverArt(HttpServletRequest request, HttpServletResponse response) throws Exception { |
|
|
|
request = wrapRequest(request); |
|
|
|
request = wrapRequest(request); |
|
|
|
return coverArtController.handleRequest(request, response); |
|
|
|
coverArtController.handleRequest(request, response); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@RequestMapping(value = "/getAvatar") |
|
|
|
@RequestMapping(value = "/getAvatar") |
|
|
|
public ModelAndView getAvatar(HttpServletRequest request, HttpServletResponse response) throws Exception { |
|
|
|
public void getAvatar(HttpServletRequest request, HttpServletResponse response) throws Exception { |
|
|
|
request = wrapRequest(request); |
|
|
|
request = wrapRequest(request); |
|
|
|
return avatarController.handleRequest(request, response); |
|
|
|
avatarController.handleRequest(request, response); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@RequestMapping(value = "/changePassword") |
|
|
|
@RequestMapping(value = "/changePassword") |
|
|
@ -2237,7 +2224,7 @@ public class RESTController { |
|
|
|
|
|
|
|
|
|
|
|
MediaFile mediaFile = this.mediaFileService.getMediaFile(id); |
|
|
|
MediaFile mediaFile = this.mediaFileService.getMediaFile(id); |
|
|
|
if (mediaFile == null) { |
|
|
|
if (mediaFile == null) { |
|
|
|
error(request, response, RESTController.ErrorCode.NOT_FOUND, "Media file not found."); |
|
|
|
error(request, response, SubsonicRESTController.ErrorCode.NOT_FOUND, "Media file not found."); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
AlbumNotes albumNotes = this.lastFmService.getAlbumNotes(mediaFile); |
|
|
|
AlbumNotes albumNotes = this.lastFmService.getAlbumNotes(mediaFile); |
|
|
@ -2256,7 +2243,7 @@ public class RESTController { |
|
|
|
|
|
|
|
|
|
|
|
Album album = this.albumDao.getAlbum(id); |
|
|
|
Album album = this.albumDao.getAlbum(id); |
|
|
|
if (album == null) { |
|
|
|
if (album == null) { |
|
|
|
error(request, response, RESTController.ErrorCode.NOT_FOUND, "Album not found."); |
|
|
|
error(request, response, SubsonicRESTController.ErrorCode.NOT_FOUND, "Album not found."); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
AlbumNotes albumNotes = this.lastFmService.getAlbumNotes(album); |
|
|
|
AlbumNotes albumNotes = this.lastFmService.getAlbumNotes(album); |