MuseScore/mscore/loginmanager.cpp
Joachim Schmitz 356a7c85dd Simplify texts in various dialogs, for translators' benefit
by eliminating html stuff from the to be translated texts.
Move urls out of translations, which is also good for security
reasons, to protect us from bogus and malicous translations.
Some formatting changes and getting some error messages to stderr.
Updating copyright to 2016 in the due course.
2016-03-25 09:06:56 +01:00

470 lines
20 KiB
C++

//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2014 Werner Schweer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation and appearing in
// the file LICENCE.GPL
//=============================================================================
#include "loginmanager.h"
#include "musescore.h"
#include "kQOAuth/kqoauthrequest.h"
#include "kQOAuth/kqoauthrequest_xauth.h"
namespace Ms {
extern QString dataPath;
//---------------------------------------------------------
// LoginManager
//---------------------------------------------------------
LoginManager::LoginManager(QObject* parent)
: QObject(parent)
{
_oauthManager = new KQOAuthManager(this);
connect(_oauthManager, SIGNAL(accessTokenReceived(QString, QString)),
this, SLOT(onAccessTokenReceived(QString, QString)));
connect(_oauthManager, SIGNAL(authorizedRequestDone()),
this, SLOT(onAuthorizedRequestDone()));
QByteArray ba;
ba.resize(32);
ba[0] = 0x68; ba[1] = 0x74; ba[2] = 0x55; ba[3] = 0x38;
ba[4] = 0x48; ba[5] = 0x45; ba[6] = 0x4c; ba[7] = 0x45;
ba[8] = 0x4d; ba[9] = 0x47; ba[10] = 0x43; ba[11] = 0x55;
ba[12] = 0x6e; ba[13] = 0x6f; ba[14] = 0x53; ba[15] = 0x54;
ba[16] = 0x38; ba[17] = 0x67; ba[18] = 0x6b; ba[19] = 0x78;
ba[20] = 0x34; ba[21] = 0x77; ba[22] = 0x33; ba[23] = 0x69;
ba[24] = 0x52; ba[25] = 0x63; ba[26] = 0x64; ba[27] = 0x6e;
ba[28] = 0x41; ba[29] = 0x6a; ba[30] = 0x37; ba[31] = 0x51;
_consumerKey = QString(ba);
ba[0] = 0x52; ba[1] = 0x50; ba[2] = 0x75; ba[3] = 0x32;
ba[4] = 0x79; ba[5] = 0x52; ba[6] = 0x69; ba[7] = 0x52;
ba[8] = 0x6f; ba[9] = 0x58; ba[10] = 0x53; ba[11] = 0x41;
ba[12] = 0x48; ba[13] = 0x6d; ba[14] = 0x4a; ba[15] = 0x6f;
ba[16] = 0x6b; ba[17] = 0x61; ba[18] = 0x62; ba[19] = 0x59;
ba[20] = 0x35; ba[21] = 0x37; ba[22] = 0x59; ba[23] = 0x74;
ba[24] = 0x66; ba[25] = 0x51; ba[26] = 0x5a; ba[27] = 0x36;
ba[28] = 0x77; ba[29] = 0x35; ba[30] = 0x69; ba[31] = 0x77;
_consumerSecret = QString(ba);
load();
}
//---------------------------------------------------------
// save
//---------------------------------------------------------
bool LoginManager::save()
{
if (_accessToken.isEmpty() || _accessTokenSecret.isEmpty())
return true;
QFile saveFile(dataPath + "/cred.dat");
if (!saveFile.open(QIODevice::WriteOnly))
return false;
QJsonObject saveObject;
saveObject["accessToken"] = _accessToken;
saveObject["accessTokenSecret"] = _accessTokenSecret;
QJsonDocument saveDoc(saveObject);
saveFile.write(saveDoc.toBinaryData());
saveFile.close();
return true;
}
//---------------------------------------------------------
// load
//---------------------------------------------------------
bool LoginManager::load()
{
QFile loadFile(dataPath + "/cred.dat");
if (!loadFile.open(QIODevice::ReadOnly))
return false;
QByteArray saveData = loadFile.readAll();
QJsonDocument loadDoc(QJsonDocument::fromBinaryData(saveData));
QJsonObject saveObject = loadDoc.object();
_accessToken = saveObject["accessToken"].toString();
_accessTokenSecret = saveObject["accessTokenSecret"].toString();
loadFile.close();
return true;
}
//---------------------------------------------------------
// onAuthorizedRequestDone
//---------------------------------------------------------
void LoginManager::onAuthorizedRequestDone()
{
if (_oauthManager->lastError() == KQOAuthManager::NetworkError)
QMessageBox::critical(0, tr("Network error"), tr("Please check your Internet connection"));
else if (_oauthManager->lastError() == KQOAuthManager::ContentOperationNotPermittedError)
QMessageBox::critical(0, tr("Please upgrade"), tr("Your MuseScore version is too old to use this feature.\n"
"%1Please upgrade first%2.")
.arg("<a href=\"http://musescore.org\">")
.arg("</a>")
.replace("\n", "<br/>"));
// don't do that, it will logout user if score is private and already known
//else if (_oauthManager->lastError() == KQOAuthManager::RequestUnauthorized){
// logout();
// mscore->showLoginDialog();
// }
}
/*------- TRY LOGIN ROUTINES ----------------------------*/
/* Try to get user information, if error, */
/* display login form until quit or successful login */
//---------------------------------------------------------
// tryLogin
//---------------------------------------------------------
void LoginManager::tryLogin()
{
disconnect(this, SIGNAL(loginSuccess()), this, SLOT(tryLogin()));
connect(this, SIGNAL(getUserSuccess()), this, SLOT(onTryLoginSuccess()));
connect(this, SIGNAL(getUserError(QString)), this, SLOT(onTryLoginError(QString)));
getUser();
}
//---------------------------------------------------------
// onTryLoginSuccess
//---------------------------------------------------------
void LoginManager::onTryLoginSuccess()
{
disconnect(this, SIGNAL(getUserSuccess()), this, SLOT(onTryLoginSuccess()));
disconnect(this, SIGNAL(getUserError(QString)), this, SLOT(onTryLoginError(QString)));
emit tryLoginSuccess();
}
//---------------------------------------------------------
// onTryLoginError
//---------------------------------------------------------
void LoginManager::onTryLoginError(const QString& error)
{
Q_UNUSED(error);
disconnect(this, SIGNAL(getUserSuccess()), this, SLOT(onTryLoginSuccess()));
disconnect(this, SIGNAL(getUserError(QString)), this, SLOT(onTryLoginError(QString)));
connect(this, SIGNAL(loginSuccess()), this, SLOT(tryLogin()));
logout();
mscore->showLoginDialog();
}
/*------- END - TRY LOGIN ROUTINES ----------------------------*/
//---------------------------------------------------------
// login
//---------------------------------------------------------
void LoginManager::login(QString login, QString password)
{
if(login == "" || password == "")
return;
connect(_oauthManager, SIGNAL(requestReady(QByteArray)),
this, SLOT(onAccessTokenRequestReady(QByteArray)), Qt::UniqueConnection);
KQOAuthRequest_XAuth *oauthRequest = new KQOAuthRequest_XAuth(this);
oauthRequest->initRequest(KQOAuthRequest::AccessToken, QUrl("https://api.musescore.com/oauth/access_token"));
oauthRequest->setConsumerKey(_consumerKey);
oauthRequest->setConsumerSecretKey(_consumerSecret);
oauthRequest->setXAuthLogin(login, password);
_oauthManager->executeRequest(oauthRequest);
}
//---------------------------------------------------------
// onAccessTokenReceived
//---------------------------------------------------------
void LoginManager::onAccessTokenReceived(QString token, QString tokenSecret)
{
//qDebug() << "Access token received: " << token << tokenSecret;
_accessToken = token;
_accessTokenSecret = tokenSecret;
disconnect(_oauthManager, SIGNAL(requestReady(QByteArray)), this, SLOT(onAccessTokenRequestReady(QByteArray)));
emit loginSuccess();
}
//---------------------------------------------------------
// onAccessTokenRequestReady
//---------------------------------------------------------
void LoginManager::onAccessTokenRequestReady(QByteArray ba)
{
//qDebug() << "onAccessTokenRequestReady" << ba;
if (_oauthManager->lastError() == KQOAuthManager::RequestUnauthorized) { // 401/406
QJsonDocument jsonResponse = QJsonDocument::fromJson(ba);
QJsonArray array = jsonResponse.array();
QString message = tr("Unsuccessful login. Please try again.");
if (array.size() > 0) {
QJsonObject o = array.at(0).toObject();
if (o.value("code") != QJsonValue::Undefined) {
QString code = o["code"].toString();
if (code == "USER_AUTHENTICATION_FAILED") {
message = tr("Sorry, wrong email address, username or password. Please check again. %1Have you forgotten your password%2?")
.arg("<a href=\"https://musescore.com/user/password\">")
.arg("</a>");
}
else if (code == "USER_DENIED") {
message = tr("This account has been blocked.");
}
else if (code == "USER_NOT_ACTIVATED") {
message = tr("Your account has not been activated yet. Please check your mailbox to activate your account or %1request a new activation email%2.")
.arg("<a href=\"https://musescore.com/user/resendregistrationpassword\">")
.arg("</a>");
}
else if (code == "USER_TIMESTAMP_EXPIRED") {
message = tr("The local time on your device is not set right. Please check it and adjust. It's advised to set the time/timezone to automatic. If you still can't log in, %1contact us%2.")
.arg("<a href=\"https://musescore.com/contact?category=Login%20problems\">")
.arg("</a>");
}
}
}
emit loginError(message);
}
else if (_oauthManager->lastError() == KQOAuthManager::NetworkError) {
QMessageBox::critical(0, tr("Network error"), tr("Please check your Internet connection"));
}
else if (_oauthManager->lastError() == KQOAuthManager::ContentOperationNotPermittedError) {
QMessageBox::critical(0, tr("Please upgrade"), tr("Your MuseScore version is too old to use this feature.\n"
"%1Please upgrade first%2.")
.arg("<a href=\"http://musescore.org\">")
.arg("</a>")
.replace("\n", "<br/>"));
}
}
//---------------------------------------------------------
// getUser
//---------------------------------------------------------
void LoginManager::getUser()
{
//qDebug() << "getUser";
if (_accessToken.isEmpty() || _accessTokenSecret.isEmpty()) {
emit getUserError("getUser - No token");
return;
}
KQOAuthRequest * oauthRequest = new KQOAuthRequest();
oauthRequest->initRequest(KQOAuthRequest::AuthorizedRequest, QUrl("https://api.musescore.com/services/rest/me.json"));
oauthRequest->setHttpMethod(KQOAuthRequest::GET);
oauthRequest->setConsumerKey(_consumerKey);
oauthRequest->setConsumerSecretKey(_consumerSecret);
oauthRequest->setToken(_accessToken);
oauthRequest->setTokenSecret(_accessTokenSecret);
connect(_oauthManager, SIGNAL(requestReady(QByteArray)),
this, SLOT(onGetUserRequestReady(QByteArray)));
_oauthManager->executeRequest(oauthRequest);
}
//---------------------------------------------------------
// onGetUserRequestReady
//---------------------------------------------------------
void LoginManager::onGetUserRequestReady(QByteArray ba)
{
//qDebug() << "onGetUserRequestReady" << ba;
disconnect(_oauthManager, SIGNAL(requestReady(QByteArray)),
this, SLOT(onGetUserRequestReady(QByteArray)));
if (_oauthManager->lastError() == KQOAuthManager::NoError) {
QJsonDocument jsonResponse = QJsonDocument::fromJson(ba);
QJsonObject user = jsonResponse.object();
if (user.value("name") != QJsonValue::Undefined) {
_userName = user.value("name").toString();
_uid = user.value("id").toString().toInt();
emit getUserSuccess();
}
else {
emit getUserError(tr("Error while getting user info. Please try again"));
}
}
else if (_oauthManager->lastError() != KQOAuthManager::NetworkError) {
emit getUserError(tr("Error while getting user info: %1").arg(_oauthManager->lastError()));
}
}
//---------------------------------------------------------
// getScore
//---------------------------------------------------------
void LoginManager::getScore(int nid)
{
//qDebug() << "getScore";
if (_accessToken.isEmpty() || _accessTokenSecret.isEmpty()) {
emit getScoreError("getScore - No token");
return;
}
KQOAuthRequest * oauthRequest = new KQOAuthRequest();
oauthRequest->initRequest(KQOAuthRequest::AuthorizedRequest, QUrl(QString("https://api.musescore.com/services/rest/score/%1.json").arg(nid)));
oauthRequest->setHttpMethod(KQOAuthRequest::GET);
oauthRequest->setConsumerKey(_consumerKey);
oauthRequest->setConsumerSecretKey(_consumerSecret);
oauthRequest->setToken(_accessToken);
oauthRequest->setTokenSecret(_accessTokenSecret);
connect(_oauthManager, SIGNAL(requestReady(QByteArray)),
this, SLOT(onGetScoreRequestReady(QByteArray)));
_oauthManager->executeRequest(oauthRequest);
}
//---------------------------------------------------------
// onGetUserRequestReady
//---------------------------------------------------------
void LoginManager::onGetScoreRequestReady(QByteArray ba)
{
//qDebug() << "onGetScoreRequestReady" << ba;
//qDebug() << _oauthManager->lastError();
disconnect(_oauthManager, SIGNAL(requestReady(QByteArray)),
this, SLOT(onGetScoreRequestReady(QByteArray)));
if (_oauthManager->lastError() == KQOAuthManager::NoError) {
QJsonDocument jsonResponse = QJsonDocument::fromJson(ba);
QJsonObject score = jsonResponse.object();
if (score.value("user") != QJsonValue::Undefined) {
QJsonObject user = score.value("user").toObject();
QString title = score.value("title").toString();
QString description = score.value("description").toString();
QString sharing = score.value("sharing").toString();
QString license = score.value("license").toString();
QString tags = score.value("tags").toString();
QString url = score.value("custom_url").toString();
if (user.value("uid") != QJsonValue::Undefined) {
int uid = user.value("uid").toString().toInt();
if (uid == _uid)
emit getScoreSuccess(title, description, (sharing == "private"), license, tags, url);
else
emit getScoreError("");
}
else {
emit getScoreError("");
}
}
else {
emit getScoreError("");
}
}
else {
emit getScoreError("");
}
}
//---------------------------------------------------------
// upload
//---------------------------------------------------------
void LoginManager::upload(const QString &path, int nid, const QString &title, const QString &description, const QString& priv, const QString& license, const QString& tags)
{
//qDebug() << "file upload";
KQOAuthRequest *oauthRequest = new KQOAuthRequest(this);
QUrl url("https://api.musescore.com/services/rest/score.json");
if (nid > 0)
url = QUrl(QString("https://api.musescore.com/services/rest/score/%1/update.json").arg(nid));
oauthRequest->initRequest(KQOAuthRequest::AuthorizedRequest, url);
oauthRequest->setConsumerKey(_consumerKey);
oauthRequest->setConsumerSecretKey(_consumerSecret);
oauthRequest->setToken(_accessToken);
oauthRequest->setTokenSecret(_accessTokenSecret);
oauthRequest->setContentType("multipart/form-data");
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart filePart;
filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"score_data\"; filename=\"temp.mscz\""));
QFile *file = new QFile(path);
file->open(QIODevice::ReadOnly);
filePart.setBodyDevice(file);
file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart
multiPart->append(filePart);
QHttpPart titlePart;
titlePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"title\""));
titlePart.setBody(title.toUtf8());
multiPart->append(titlePart);
QHttpPart descriptionPart;
descriptionPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"description\""));
descriptionPart.setBody(description.toUtf8());
multiPart->append(descriptionPart);
QHttpPart privatePart;
privatePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"private\""));
privatePart.setBody(priv.toUtf8());
multiPart->append(privatePart);
QHttpPart licensePart;
licensePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"license\""));
licensePart.setBody(license.toUtf8());
multiPart->append(licensePart);
QHttpPart tagsPart;
tagsPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"tags\""));
tagsPart.setBody(tags.toUtf8());
multiPart->append(tagsPart);
connect(_oauthManager, SIGNAL(requestReady(QByteArray)),
this, SLOT(onUploadRequestReady(QByteArray)));
oauthRequest->setHttpMultiPart(multiPart);
_oauthManager->executeRequest(oauthRequest);
}
//---------------------------------------------------------
// onUploadRequestReady
//---------------------------------------------------------
void LoginManager::onUploadRequestReady(QByteArray ba)
{
disconnect(_oauthManager, SIGNAL(requestReady(QByteArray)),
this, SLOT(onUploadRequestReady(QByteArray)));
//qDebug() << "onUploadRequestReady" << ba;
if (_oauthManager->lastError() == KQOAuthManager::NoError) {
QJsonDocument jsonResponse = QJsonDocument::fromJson(ba);
QJsonObject score = jsonResponse.object();
if (score.value("permalink") != QJsonValue::Undefined) {
emit uploadSuccess(score.value("permalink").toString());
}
else {
emit uploadError(tr("An error occurred during the file transfer. Please try again"));
}
}
else {
emit uploadError(tr("Cannot upload: %1").arg(_oauthManager->lastError()));
}
}
//---------------------------------------------------------
// hasAccessToken
//---------------------------------------------------------
bool LoginManager::hasAccessToken()
{
return !_accessTokenSecret.isEmpty() && !_accessToken.isEmpty();
}
//---------------------------------------------------------
// logout
//---------------------------------------------------------
bool LoginManager::logout()
{
_accessToken = "";
_accessTokenSecret = "";
QFile loadFile(dataPath + "/cred.dat");
if (!loadFile.exists())
return true;
return loadFile.remove();
}
}