From 99b56da15f5da2ba5f8e4ef55ef44a4876059d21 Mon Sep 17 00:00:00 2001 From: emeric Date: Sun, 7 Apr 2019 17:55:25 +0200 Subject: [PATCH] Subsonic API: send back an error on bad login parameters --- src/api/subsonic/SubsonicResource.cpp | 62 +++++++++++---------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/src/api/subsonic/SubsonicResource.cpp b/src/api/subsonic/SubsonicResource.cpp index cfd24622..a66a05a0 100644 --- a/src/api/subsonic/SubsonicResource.cpp +++ b/src/api/subsonic/SubsonicResource.cpp @@ -187,42 +187,32 @@ getMandatoryParameterAs(const Wt::Http::ParameterMap& parameterMap, const std::s struct ClientInfo { std::string name; - ResponseFormat format; std::string user; std::string password; }; -boost::optional +ClientInfo getClientInfo(const Wt::Http::ParameterMap& parameters) { - boost::optional res {ClientInfo {}}; + ClientInfo res; // Mandatory parameters - auto param {getParameterAs(parameters, "c")}; - if (!param) - return {}; - res->name = *param; + res.name = getMandatoryParameterAs(parameters, "c"); + res.user = getMandatoryParameterAs(parameters, "u"); - param = getParameterAs(parameters, "u"); - if (!param) - return {}; - res->user = *param; - - param = getParameterAs(parameters, "p"); - if (!param) - return {}; - - if (param->find("enc:") == 0) { - param = stringFromHex(param->substr(4)); - if (!param) - return {}; - } - res->password = *param; + std::string password {getMandatoryParameterAs(parameters, "p")}; + if (password.find("enc:") == 0) + { + auto decodedPassword {stringFromHex(password.substr(4))}; + if (!decodedPassword) + throw Error {Error::Code::WrongUsernameOrPassword}; - // Optional parameters - param = getParameterAs(parameters, "f"); - res->format = (param ? ResponseFormat::json : ResponseFormat::xml); // TODO + res.password = *decodedPassword; + } + else + res.password = password; + } return res; } @@ -265,30 +255,28 @@ SubsonicResource::handleRequest(const Wt::Http::Request &request, Wt::Http::Resp { LMS_LOG(API_SUBSONIC, DEBUG) << "REQUEST " << request.path(); - const Wt::Http::ParameterMap parameters {request.getParameterMap()}; + const Wt::Http::ParameterMap& parameters {request.getParameterMap()}; - auto clientInfo {getClientInfo(parameters)}; - if (!clientInfo) - { - LMS_LOG(API_SUBSONIC, ERROR) << "Failed to parse client info"; - return; - } + // Optional parameters + ResponseFormat format {getParameterAs(parameters, "f").get_value_or("xml") == "json" ? ResponseFormat::json : ResponseFormat::xml}; try { static std::mutex mutex; + ClientInfo clientInfo {getClientInfo(parameters)}; + std::unique_lock lock{mutex}; // For now just handle request s one by one - if (!checkPassword(_db, *clientInfo)) + if (!checkPassword(_db, clientInfo)) throw Error {Error::Code::WrongUsernameOrPassword}; auto itHandler {requestHandlers.find(request.path())}; if (itHandler != requestHandlers.end()) { Response resp {(itHandler->second)(request.getParameterMap(), _db)}; - resp.write(response.out(), clientInfo->format); - response.setMimeType(ResponseFormatToMimeType(clientInfo->format)); + resp.write(response.out(), format); + response.setMimeType(ResponseFormatToMimeType(format)); return; } @@ -306,8 +294,8 @@ SubsonicResource::handleRequest(const Wt::Http::Request &request, Wt::Http::Resp { LMS_LOG(API_SUBSONIC, ERROR) << "Error while processing command. code = " << static_cast(e.getCode()) << ", msg = '" << e.getMessage() << "'"; Response resp {Response::createFailedResponse(e)}; - resp.write(response.out(), clientInfo->format); - response.setMimeType(ResponseFormatToMimeType(clientInfo->format)); + resp.write(response.out(), format); + response.setMimeType(ResponseFormatToMimeType(format)); } }