Subsonic API: added missing getAlbumList types to make Ultrasonic happy + added a protocol version check

This commit is contained in:
emeric
2019-08-03 15:02:20 +02:00
parent 1a1c523d14
commit bbfb2ac736
7 changed files with 97 additions and 10 deletions
+62 -3
View File
@@ -73,11 +73,54 @@ readAs(const std::string& str)
namespace API::Subsonic
{
struct ClientVersion
{
unsigned major;
unsigned minor;
unsigned patch;
};
}
template<>
boost::optional<API::Subsonic::ClientVersion>
readAs(const std::string& str)
{
// Expects "X.Y.Z"
const auto numbers {splitString(str, ".")};
if (numbers.size() != 3)
return boost::none;
API::Subsonic::ClientVersion version;
auto number {readAs<unsigned>(numbers[0])};
if (!number)
return boost::none;
version.major = *number;
number = {readAs<unsigned>(numbers[1])};
if (!number)
return boost::none;
version.minor = *number;
number = {readAs<unsigned>(numbers[2])};
if (!number)
return boost::none;
version.patch = *number;
return version;
}
namespace API::Subsonic
{
struct ClientInfo
{
std::string name;
std::string user;
std::string password;
ClientVersion version;
};
struct RequestContext
@@ -215,6 +258,7 @@ getClientInfo(const Wt::Http::ParameterMap& parameters)
res.name = getMandatoryParameterAs<std::string>(parameters, "c");
res.user = getMandatoryParameterAs<std::string>(parameters, "u");
res.password = decodePasswordIfNeeded(getMandatoryParameterAs<std::string>(parameters, "p"));
res.version = getMandatoryParameterAs<ClientVersion>(parameters, "v");
return res;
}
@@ -757,6 +801,10 @@ handleGetAlbumListRequestCommon(const RequestContext& context, bool id3)
{
releases = Release::getAll(context.dbSession, offset, size);
}
else if (type == "alphabeticalByArtist")
{
releases = Release::getAllOrderedByArtist(context.dbSession, offset, size);
}
else if (type == "byYear")
{
int fromYear {getMandatoryParameterAs<int>(context.parameters, "fromYear")};
@@ -764,6 +812,10 @@ handleGetAlbumListRequestCommon(const RequestContext& context, bool id3)
releases = Release::getByYear(context.dbSession, fromYear, toYear, offset, size);
}
else if (type == "starred")
{
releases = user->getStarredReleases(offset, size);
}
else if (type == "byGenre")
{
// Mandatory param
@@ -878,7 +930,7 @@ handleGetArtistInfoRequestCommon(RequestContext& context, bool id3)
throw Error {Error::CustomType::BadIdFormat};
// Optional params
std::size_t count {getParameterAs<std::size_t>(context.parameters, "count").get_value_or(10)};
std::size_t count {getParameterAs<std::size_t>(context.parameters, "count").get_value_or(20)};
Response response {Response::createOkResponse()};
Response::Node& artistInfoNode {response.createNode(id3 ? "artistInfo2" : "artistInfo")};
@@ -1814,9 +1866,16 @@ SubsonicResource::handleRequest(const Wt::Http::Request &request, Wt::Http::Resp
try
{
Session& dbSession {getOrCreateDbSession(_db)};
// Mandatory parameters
const ClientInfo clientInfo {getClientInfo(parameters)};
if (clientInfo.version.major > API_VERSION_MAJOR)
throw Error {Error::Code::ServerMustUpgrade};
if (clientInfo.version.major < API_VERSION_MAJOR)
throw Error {Error::Code::ClientMustUpgrade};
if (clientInfo.version.minor > API_VERSION_MINOR)
throw Error {Error::Code::ServerMustUpgrade};
Session& dbSession {getOrCreateDbSession(_db)};
switch (getService<Auth::PasswordService>()->checkUserPassword(dbSession,
boost::asio::ip::address::from_string(request.clientAddress()),
+2 -4
View File
@@ -29,8 +29,6 @@
#include "utils/Exception.hpp"
#define API_VERSION "1.12.0"
namespace API::Subsonic
{
@@ -163,7 +161,7 @@ Response::createOkResponse()
Node& responseNode {response._root.createChild("subsonic-response")};
responseNode.setAttribute("status", "ok");
responseNode.setAttribute("version", API_VERSION);
responseNode.setAttribute("version", API_VERSION_STR);
return response;
}
@@ -175,7 +173,7 @@ Response::createFailedResponse(const Error& error)
Node& responseNode {response._root.createChild("subsonic-response")};
responseNode.setAttribute("status", "failed");
responseNode.setAttribute("version", API_VERSION);
responseNode.setAttribute("version", API_VERSION_STR);
Node& errorNode {responseNode.createChild("error")};
errorNode.setAttribute("code", std::to_string(static_cast<int>(error.getCode())));
+6
View File
@@ -21,9 +21,15 @@
#include <string>
#include <vector>
namespace API::Subsonic
{
#define API_VERSION_MAJOR 1
#define API_VERSION_MINOR 12
#define API_VERSION_PATCH 0
#define API_VERSION_STR "1.12.0"
enum class ResponseFormat
{
xml,