From cec2745dc0f2f0a19de0ff7f5dc402235196045f Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Sun, 22 Sep 2019 17:10:04 +0200 Subject: [PATCH] Qobuz: Send mac address as device_manufacturer_id in login --- src/qobuz/qobuzbaserequest.cpp | 4 +- src/qobuz/qobuzbaserequest.h | 3 ++ src/qobuz/qobuzservice.cpp | 74 +++++++++++++++++++++++++++-- src/qobuz/qobuzservice.h | 6 +++ src/qobuz/qobuzstreamurlrequest.cpp | 15 +++--- 5 files changed, 86 insertions(+), 16 deletions(-) diff --git a/src/qobuz/qobuzbaserequest.cpp b/src/qobuz/qobuzbaserequest.cpp index cbe9b523f..fb0688276 100644 --- a/src/qobuz/qobuzbaserequest.cpp +++ b/src/qobuz/qobuzbaserequest.cpp @@ -108,7 +108,7 @@ QByteArray QobuzBaseRequest::GetReplyData(QNetworkReply *reply) { QString error; QJsonParseError parse_error; QJsonDocument json_doc = QJsonDocument::fromJson(data, &parse_error); - if (parse_error.error == QJsonParseError::NoError && !json_doc.isNull() && !json_doc.isEmpty() && json_doc.isObject()) { + if (parse_error.error == QJsonParseError::NoError && !json_doc.isEmpty() && json_doc.isObject()) { QJsonObject json_obj = json_doc.object(); if (!json_obj.isEmpty() && json_obj.contains("status") && json_obj.contains("code") && json_obj.contains("message")) { QString status = json_obj["status"].toString(); @@ -144,7 +144,7 @@ QJsonObject QobuzBaseRequest::ExtractJsonObj(QByteArray &data) { return QJsonObject(); } - if (json_doc.isNull() || json_doc.isEmpty()) { + if (json_doc.isEmpty()) { Error("Received empty Json document.", data); return QJsonObject(); } diff --git a/src/qobuz/qobuzbaserequest.h b/src/qobuz/qobuzbaserequest.h index cfdc61b28..dd9039d16 100644 --- a/src/qobuz/qobuzbaserequest.h +++ b/src/qobuz/qobuzbaserequest.h @@ -89,7 +89,10 @@ class QobuzBaseRequest : public QObject { int albumssearchlimit() { return service_->albumssearchlimit(); } int songssearchlimit() { return service_->songssearchlimit(); } + qint64 user_id() { return service_->user_id(); } QString user_auth_token() { return service_->user_auth_token(); } + QString device_id() { return service_->device_id(); } + qint64 credential_id() { return service_->credential_id(); } bool authenticated() { return service_->authenticated(); } bool login_sent() { return service_->login_sent(); } diff --git a/src/qobuz/qobuzservice.cpp b/src/qobuz/qobuzservice.cpp index c7adce662..569064d0f 100644 --- a/src/qobuz/qobuzservice.cpp +++ b/src/qobuz/qobuzservice.cpp @@ -96,6 +96,8 @@ QobuzService::QobuzService(Application *app, QObject *parent) albumssearchlimit_(1), songssearchlimit_(1), download_album_covers_(true), + user_id_(-1), + credential_id_(-1), pending_search_id_(0), next_pending_search_id_(1), search_id_(0), @@ -238,6 +240,8 @@ void QobuzService::ReloadSettings() { songssearchlimit_ = s.value("songssearchlimit", 10).toInt(); download_album_covers_ = s.value("downloadalbumcovers", true).toBool(); + user_id_ = s.value("user_id").toInt(); + device_id_ = s.value("device_id").toString(); user_auth_token_ = s.value("user_auth_token").toString(); s.endGroup(); @@ -261,7 +265,8 @@ void QobuzService::SendLogin(const QString &app_id, const QString &username, con const ParamList params = ParamList() << Param("app_id", app_id) << Param("username", username) - << Param("password", password); + << Param("password", password) + << Param("device_manufacturer_id", Utilities::MacAddress()); QUrlQuery url_query; for (const Param ¶m : params) { @@ -309,7 +314,7 @@ void QobuzService::HandleAuthReply(QNetworkReply *reply) { QByteArray data(reply->readAll()); QJsonParseError json_error; QJsonDocument json_doc = QJsonDocument::fromJson(data, &json_error); - if (json_error.error == QJsonParseError::NoError && !json_doc.isNull() && !json_doc.isEmpty() && json_doc.isObject()) { + if (json_error.error == QJsonParseError::NoError && !json_doc.isEmpty() && json_doc.isObject()) { QJsonObject json_obj = json_doc.object(); if (!json_obj.isEmpty() && json_obj.contains("status") && json_obj.contains("code") && json_obj.contains("message")) { QString status = json_obj["status"].toString(); @@ -342,7 +347,7 @@ void QobuzService::HandleAuthReply(QNetworkReply *reply) { return; } - if (json_doc.isNull() || json_doc.isEmpty()) { + if (json_doc.isEmpty()) { LoginError("Authentication reply from server has empty Json document."); return; } @@ -362,15 +367,68 @@ void QobuzService::HandleAuthReply(QNetworkReply *reply) { LoginError("Authentication reply from server is missing user_auth_token", json_obj); return; } - user_auth_token_ = json_obj["user_auth_token"].toString(); + if (!json_obj.contains("user")) { + LoginError("Authentication reply from server is missing user", json_obj); + return; + } + QJsonValue json_user = json_obj["user"]; + if (!json_user.isObject()) { + LoginError("Authentication reply user is not a object", json_obj); + return; + } + QJsonObject json_obj_user = json_user.toObject(); + + if (!json_obj_user.contains("id")) { + LoginError("Authentication reply from server is missing user id", json_obj_user); + return; + } + user_id_ = json_obj_user["id"].toInt(); + + if (!json_obj_user.contains("device")) { + LoginError("Authentication reply from server is missing user device", json_obj_user); + return; + } + QJsonValue json_device = json_obj_user["device"]; + if (!json_device.isObject()) { + LoginError("Authentication reply from server user device is not a object", json_device); + return; + } + QJsonObject json_obj_device = json_device.toObject(); + + if (!json_obj_device.contains("device_manufacturer_id")) { + LoginError("Authentication reply from server device is missing device_manufacturer_id", json_obj_device); + return; + } + device_id_ = json_obj_device["device_manufacturer_id"].toString(); + + if (!json_obj_user.contains("credential")) { + LoginError("Authentication reply from server is missing user credential", json_obj_user); + return; + } + QJsonValue json_credential = json_obj_user["credential"]; + if (!json_credential.isObject()) { + LoginError("Authentication reply from serve userr credential is not a object", json_device); + return; + } + QJsonObject json_obj_credential = json_credential.toObject(); + + if (!json_obj_credential.contains("id")) { + LoginError("Authentication reply user credential from server is missing user credential id", json_obj_device); + return; + } + credential_id_ = json_obj_credential["id"].toInt(); + QSettings s; s.beginGroup(QobuzSettingsPage::kSettingsGroup); s.setValue("user_auth_token", user_auth_token_); + s.setValue("user_id", user_id_); + s.setValue("credential_id", credential_id_); + s.setValue("device_id", device_id_); s.endGroup(); - qLog(Debug) << "Qobuz: Login successful" << "user auth token" << user_auth_token_; + qLog(Debug) << "Qobuz: Login successful" << "user id" << user_id_ << "user auth token" << user_auth_token_ << "device id" << device_id_; login_attempts_ = 0; if (timer_login_attempt_->isActive()) timer_login_attempt_->stop(); @@ -383,9 +441,15 @@ void QobuzService::HandleAuthReply(QNetworkReply *reply) { void QobuzService::Logout() { user_auth_token_.clear(); + device_id_.clear(); + user_id_ = -1; + credential_id_ = -1; QSettings s; s.beginGroup(QobuzSettingsPage::kSettingsGroup); + s.remove("user_id"); + s.remove("credential_id"); + s.remove("device_id"); s.remove("user_auth_token"); s.endGroup(); diff --git a/src/qobuz/qobuzservice.h b/src/qobuz/qobuzservice.h index 5ed2264d7..2c8110bc8 100644 --- a/src/qobuz/qobuzservice.h +++ b/src/qobuz/qobuzservice.h @@ -83,6 +83,9 @@ class QobuzService : public InternetService { bool download_album_covers() { return download_album_covers_; } QString user_auth_token() { return user_auth_token_; } + qint64 user_id() { return user_id_; } + QString device_id() { return device_id_; } + qint64 credential_id() { return credential_id_; } bool authenticated() { return (!app_id_.isEmpty() && !app_secret_.isEmpty() && !user_auth_token_.isEmpty()); } bool login_sent() { return login_sent_; } @@ -204,7 +207,10 @@ class QobuzService : public InternetService { int songssearchlimit_; bool download_album_covers_; + qint64 user_id_; QString user_auth_token_; + QString device_id_; + qint64 credential_id_; int pending_search_id_; int next_pending_search_id_; diff --git a/src/qobuz/qobuzstreamurlrequest.cpp b/src/qobuz/qobuzstreamurlrequest.cpp index 4494588ec..5fd693f84 100644 --- a/src/qobuz/qobuzstreamurlrequest.cpp +++ b/src/qobuz/qobuzstreamurlrequest.cpp @@ -20,7 +20,6 @@ #include "config.h" #include -#include #include #include #include @@ -31,7 +30,6 @@ #include #include #include -#include #include "core/logging.h" #include "core/network.h" @@ -122,9 +120,7 @@ void QobuzStreamURLRequest::GetStreamURL() { QString data_to_sign; data_to_sign += "trackgetFileUrl"; for (const Param ¶m : params_to_sign) { - EncodedParam encoded_param(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second)); - data_to_sign += param.first; - data_to_sign += param.second; + data_to_sign += param.first + param.second; } data_to_sign += QString::number(timestamp); data_to_sign += app_secret(); @@ -147,12 +143,14 @@ void QobuzStreamURLRequest::GetStreamURL() { void QobuzStreamURLRequest::StreamURLReceived() { if (!reply_) return; - disconnect(reply_, 0, this, 0); - reply_->deleteLater(); QByteArray data = GetReplyData(reply_); + + disconnect(reply_, 0, this, 0); + reply_->deleteLater(); + reply_ = nullptr; + if (data.isEmpty()) { - reply_ = nullptr; if (!authenticated() && login_sent() && tries_ <= 1) { need_login_ = true; return; @@ -160,7 +158,6 @@ void QobuzStreamURLRequest::StreamURLReceived() { emit StreamURLFinished(original_url_, original_url_, Song::FileType_Stream, -1, -1, -1, errors_.first()); return; } - reply_ = nullptr; QJsonObject json_obj = ExtractJsonObj(data); if (json_obj.isEmpty()) {