diff --git a/src/Cloud/BodyMeasuresDownload.cpp b/src/Cloud/BodyMeasuresDownload.cpp index 39bc8edf1..8563c8ee2 100644 --- a/src/Cloud/BodyMeasuresDownload.cpp +++ b/src/Cloud/BodyMeasuresDownload.cpp @@ -111,7 +111,9 @@ BodyMeasuresDownload::BodyMeasuresDownload(Context *context) : context(context) QString strToken =appsettings->cvalue(context->athlete->cyclist, GC_WITHINGS_TOKEN, "").toString(); QString strSecret= appsettings->cvalue(context->athlete->cyclist, GC_WITHINGS_SECRET, "").toString(); - if (strToken == "" && strSecret == "") { + QString strToken2 =appsettings->cvalue(context->athlete->cyclist, GC_NOKIA_TOKEN, "").toString(); + + if (strToken2 =="" && strToken == "" && strSecret == "") { downloadWithings->setEnabled(false); } diff --git a/src/Cloud/OAuthDialog.cpp b/src/Cloud/OAuthDialog.cpp index b4f4ad4a9..76adbbfdd 100644 --- a/src/Cloud/OAuthDialog.cpp +++ b/src/Cloud/OAuthDialog.cpp @@ -180,29 +180,12 @@ OAuthDialog::OAuthDialog(Context *context, OAuthSite site, CloudService *service } else if (site == WITHINGS) { - // Withings is the only service that uses KQOauth for now. - -#ifdef GC_HAVE_KQOAUTH - oauthRequest = new KQOAuthRequest; - oauthManager = new KQOAuthManager(this); - - connect(oauthManager, SIGNAL(temporaryTokenReceived(QString,QString)), this, SLOT(onTemporaryTokenReceived(QString, QString))); - connect(oauthManager, SIGNAL(authorizationReceived(QString,QString)), this, SLOT( onAuthorizationReceived(QString, QString))); - connect(oauthManager, SIGNAL(accessTokenReceived(QString,QString)), this, SLOT(onAccessTokenReceived(QString,QString))); - connect(oauthManager, SIGNAL(requestReady(QByteArray)), this, SLOT(onRequestReady(QByteArray))); - connect(oauthManager, SIGNAL(authorizationPageRequested(QUrl)), this, SLOT(onAuthorizationPageRequested(QUrl))); - - oauthRequest->initRequest(KQOAuthRequest::TemporaryCredentials, QUrl("https://oauth.withings.com/account/request_token")); - //oauthRequest->setEnableDebugOutput(true); - oauthRequest->setHttpMethod(KQOAuthRequest::GET); - oauthRequest->setConsumerKey(GC_WITHINGS_CONSUMER_KEY); - oauthRequest->setConsumerSecretKey(GC_WITHINGS_CONSUMER_SECRET); - //oauthRequest->setCallbackUrl(QUrl("http://www.goldencheetah.org")); - oauthManager->setHandleUserAuthorization(true); // false to use callback - oauthManager->setHandleAuthorizationPageOpening(false); - - oauthManager->executeRequest(oauthRequest); -#endif + urlstr = QString("https://account.health.nokia.com/oauth2_user/authorize2?"); + urlstr.append("redirect_uri=http://www.goldencheetah.org&"); + urlstr.append("scope=user.info,user.metrics&"); + urlstr.append("response_type=code&"); + urlstr.append("state=xyzzy&"); + urlstr.append("client_id=").append(GC_NOKIA_CLIENT_ID); } else if (site == XERT) { urlChanged(QUrl("http://www.goldencheetah.org/?code=0")); @@ -211,7 +194,7 @@ OAuthDialog::OAuthDialog(Context *context, OAuthSite site, CloudService *service // // STEP 1: LOGIN AND AUTHORISE THE APPLICATION // - if (site == DROPBOX || site == STRAVA || site == CYCLING_ANALYTICS || site == POLAR || site == SPORTTRACKS || site == GOOGLE_DRIVE || site == KENTUNI || site == TODAYSPLAN) { + if (site == DROPBOX || site == STRAVA || site == CYCLING_ANALYTICS || site == POLAR || site == SPORTTRACKS || site == GOOGLE_DRIVE || site == KENTUNI || site == TODAYSPLAN || site == WITHINGS) { url = QUrl(urlstr); view->setUrl(url); @@ -230,113 +213,6 @@ OAuthDialog::onSslErrors(QNetworkReply *reply, const QList&) } -#ifdef GC_HAVE_KQOAUTH - -// -// KQOauth call backs -// -void -OAuthDialog::onTemporaryTokenReceived(QString, QString) -{ - //qDebug() << "onTemporaryTokenReceived"; - QUrl userAuthURL; - - if (site == WITHINGS) { - userAuthURL = "https://oauth.withings.com/account/authorize"; - } - - if(oauthManager->lastError() == KQOAuthManager::NoError) { - oauthManager->getUserAuthorization(userAuthURL); - } else - qDebug() << "error" << oauthManager->lastError(); - -} - -void -OAuthDialog::onAuthorizationReceived(QString, QString) -{ - //qDebug() << "Authorization token received: " << token << verifier; - - if (site == WITHINGS) { - oauthManager->getUserAccessTokens(QUrl("https://oauth.withings.com/account/access_token")); - } - - if(oauthManager->lastError() != KQOAuthManager::NoError) { - QString error = QString(tr("Error fetching OAuth credentials - Endpoint: /oauth/access_token")); - QMessageBox oautherr(QMessageBox::Critical, tr("Authorization Error"), error); - oautherr.exec(); - accept(); - } -} - -void -OAuthDialog::onAccessTokenReceived(QString token, QString tokenSecret) -{ - //qDebug() << "Access token received: " << token << tokenSecret; - - QString info; - if (site == WITHINGS) { - service->setSetting(GC_WITHINGS_TOKEN, token); - service->setSetting(GC_WITHINGS_SECRET, tokenSecret); - appsettings->setCValue(context->athlete->cyclist, GC_NOKIA_REFRESH_TOKEN, ""); - - info = QString(tr("Nokia Health (Withings) authorization was successful.")); - } - - - QMessageBox information(QMessageBox::Information, tr("Information"), info); - information.exec(); - accept(); -} - - -void -OAuthDialog::onAuthorizedRequestDone() {} // request sent - do nothing - -void -OAuthDialog::onRequestReady(QByteArray response) -{ - //qDebug() << "Response received: " << response; - - QString r = response; - if (r.contains("\"errors\"", Qt::CaseInsensitive)) { - - QMessageBox oautherr(QMessageBox::Critical, tr("Error in authorization"), - tr("There was an error during authorization. Please check the error description.")); - oautherr.setDetailedText(r); // probably blank - oautherr.exec(); - - } else { - - if (site == WITHINGS) { - - QString userid; - -#if QT_VERSION > 0x050000 - QUrlQuery params; - params.setQuery(response); -#else - QUrl params; - params.setEncodedQuery(response); -#endif - userid = params.queryItemValue("userid"); - - if (userid.isEmpty() == false) { - service->setSetting(GC_WIUSER, userid); - } - } - } -} - - -void OAuthDialog::onAuthorizationPageRequested(QUrl url) { - // open Authorization page in view - view->setUrl(url); - -} -#endif // KQOAuth callbacks used by Withings only - - // // STEP 2: AUTHORISATION REDIRECT WITH TEMPORARY CODE // @@ -351,7 +227,7 @@ OAuthDialog::urlChanged(const QUrl &url) QString authheader; // sites that use this scheme - if (site == DROPBOX || site == STRAVA || site == CYCLING_ANALYTICS || site == TODAYSPLAN || site == POLAR || site == SPORTTRACKS || site == XERT) { + if (site == DROPBOX || site == STRAVA || site == CYCLING_ANALYTICS || site == TODAYSPLAN || site == POLAR || site == SPORTTRACKS || site == XERT || site == WITHINGS) { if (url.toString().startsWith("http://www.goldencheetah.org/?state=&code=") || url.toString().contains("blank.html?code=") || @@ -442,6 +318,14 @@ OAuthDialog::urlChanged(const QUrl &url) params.addQueryItem("grant_type", "password"); authheader = QString("%1:%1").arg("xert_public"); + } else if (site == WITHINGS) { + + urlstr = QString("https://account.health.nokia.com/oauth2/token?"); + params.addQueryItem("client_id", GC_NOKIA_CLIENT_ID); + params.addQueryItem("client_secret", GC_NOKIA_CLIENT_SECRET); + params.addQueryItem("redirect_uri","http://www.goldencheetah.org"); + params.addQueryItem("grant_type", "authorization_code"); + } // all services will need us to send the temporary code received @@ -713,6 +597,19 @@ OAuthDialog::networkRequestFinished(QNetworkReply *reply) service->message = "Xert authorization was successful."; + } else if (site == WITHINGS) { + + service->setSetting(GC_NOKIA_TOKEN, access_token); + service->setSetting(GC_NOKIA_REFRESH_TOKEN, refresh_token); + + // We have to ask for userid ? + + + + QString info = QString(tr("Withings/Nokia authorization was successful.")); + QMessageBox information(QMessageBox::Information, tr("Information"), info); + information.exec(); + } } else { diff --git a/src/Cloud/OAuthDialog.h b/src/Cloud/OAuthDialog.h index ca755e5a1..395740a6f 100644 --- a/src/Cloud/OAuthDialog.h +++ b/src/Cloud/OAuthDialog.h @@ -85,15 +85,6 @@ private slots: void networkRequestFinished(QNetworkReply *reply); void onSslErrors(QNetworkReply *reply, const QList&error); -#ifdef GC_HAVE_KQOAUTH - void onTemporaryTokenReceived(QString, QString); - void onAuthorizationReceived(QString, QString); - void onAccessTokenReceived(QString token, QString tokenSecret); - void onAuthorizedRequestDone(); - void onRequestReady(QByteArray response); - void onAuthorizationPageRequested (QUrl pageUrl); -#endif - private: Context *context; diff --git a/src/Cloud/Withings.cpp b/src/Cloud/Withings.cpp index e48a3f2b7..edddae3f6 100644 --- a/src/Cloud/Withings.cpp +++ b/src/Cloud/Withings.cpp @@ -24,9 +24,8 @@ Withings::Withings(Context *context) : CloudService(context), context(context) { // config - settings.insert(OAuthToken, GC_WITHINGS_TOKEN); - settings.insert(Local1, GC_WITHINGS_SECRET); - settings.insert(Local2, GC_WIUSER); + settings.insert(OAuthToken, GC_NOKIA_TOKEN); + settings.insert(Local1, GC_NOKIA_REFRESH_TOKEN); } static bool addWithings() { diff --git a/src/Cloud/WithingsDownload.cpp b/src/Cloud/WithingsDownload.cpp index e8b988765..d8a8a3e2e 100644 --- a/src/Cloud/WithingsDownload.cpp +++ b/src/Cloud/WithingsDownload.cpp @@ -30,6 +30,28 @@ #include #endif +#ifndef WITHINGS_DEBUG +#define WITHINGS_DEBUG true +#endif +#ifdef Q_CC_MSVC +#define printd(fmt, ...) do { \ + if (WITHINGS_DEBUG) { \ + printf("[%s:%d %s] " fmt , __FILE__, __LINE__, \ + __FUNCTION__, __VA_ARGS__); \ + fflush(stdout); \ + } \ +} while(0) +#else +#define printd(fmt, args...) \ + do { \ + if (WITHINGS_DEBUG) { \ + printf("[%s:%d %s] " fmt , __FILE__, __LINE__, \ + __FUNCTION__, ##args); \ + fflush(stdout); \ + } \ + } while(0) +#endif + WithingsDownload::WithingsDownload(Context *context) : context(context) { nam = new QNetworkAccessManager(this); @@ -75,7 +97,8 @@ WithingsDownload::getBodyMeasures(QString &error, QDateTime from, QDateTime to, if((strToken.isEmpty() || strSecret.isEmpty() || strToken == "" || strToken == "0" || strSecret == "" || strSecret == "0" ) && - (strOldKey.isEmpty() || strOldKey == "" || strOldKey == "0" )) + (strOldKey.isEmpty() || strOldKey == "" || strOldKey == "0" ) && + (strNokiaRefreshToken.isEmpty() || strNokiaRefreshToken == "" || strNokiaRefreshToken == "0" )) { #ifdef Q_OS_MACX #define GC_PREF tr("Golden Cheetah->Preferences") @@ -88,10 +111,11 @@ WithingsDownload::getBodyMeasures(QString &error, QDateTime from, QDateTime to, return false; } - if(!strToken.isEmpty() &&! strSecret.isEmpty() && + if(!strNokiaRefreshToken.isEmpty() || + (!strToken.isEmpty() &&! strSecret.isEmpty() && strToken != "" && strToken != "0" && - strSecret != "" && strSecret != "0" ) { - qDebug() << "OAuth 2.0 API"; + strSecret != "" && strSecret != "0" )) { + printd("OAuth 2.0 API"); #if QT_VERSION > 0x050000 QUrlQuery postData; @@ -99,21 +123,15 @@ WithingsDownload::getBodyMeasures(QString &error, QDateTime from, QDateTime to, QUrl postData; #endif - //appsettings->setCValue(context->athlete->cyclist, GC_NOKIA_REFRESH_TOKEN, ""); - qDebug() << "refresh_token" << appsettings->cvalue(context->athlete->cyclist, GC_NOKIA_REFRESH_TOKEN, QString("%1:%2").arg(strToken).arg(strSecret)); - QString refresh_token = appsettings->cvalue(context->athlete->cyclist, GC_NOKIA_REFRESH_TOKEN).toString(); if (refresh_token.isEmpty()) refresh_token = QString("%1:%2").arg(strToken).arg(strSecret); - qDebug() << "refresh_token" << refresh_token; postData.addQueryItem("grant_type", "refresh_token"); postData.addQueryItem("client_id", GC_NOKIA_CLIENT_ID ); postData.addQueryItem("client_secret", GC_NOKIA_CLIENT_SECRET ); postData.addQueryItem("refresh_token", refresh_token ); - - qDebug() << appsettings->cvalue(context->athlete->cyclist, GC_NOKIA_REFRESH_TOKEN, QString("%1:%2").arg(strToken).arg(strSecret)).toString(); QUrl url = QUrl( "https://account.withings.com/oauth2/token" ); emit downloadStarted(100); @@ -122,11 +140,13 @@ WithingsDownload::getBodyMeasures(QString &error, QDateTime from, QDateTime to, QNetworkRequest request(url); request.setRawHeader("Content-Type", "application/x-www-form-urlencoded"); nam->post(request, postData.toString(QUrl::FullyEncoded).toUtf8()); + printd("url %s %s", url.toString().toStdString().c_str(), postData.toString().toStdString().c_str()); // blocking request loop.exec(); // we go on after receiving the data in SLOT(onRequestReady(QByteArray)) - qDebug() << "response" << response; + printd("response: %s", response.toStdString().c_str()); + if (response.contains("\"access_token\"", Qt::CaseInsensitive)) { @@ -135,9 +155,13 @@ WithingsDownload::getBodyMeasures(QString &error, QDateTime from, QDateTime to, access_token = migrateJson.object()["access_token"].toString(); QString refresh_token = migrateJson.object()["refresh_token"].toString(); + QString userid = QString("%1").arg(migrateJson.object()["userid"].toInt()); + if (access_token != "") appsettings->setCValue(context->athlete->cyclist, GC_NOKIA_TOKEN, access_token); if (refresh_token != "") appsettings->setCValue(context->athlete->cyclist, GC_NOKIA_REFRESH_TOKEN, refresh_token); + if (userid != "") appsettings->setCValue(context->athlete->cyclist, GC_WIUSER, userid); + #if QT_VERSION > 0x050000 QUrlQuery params; @@ -147,14 +171,20 @@ WithingsDownload::getBodyMeasures(QString &error, QDateTime from, QDateTime to, emit downloadStarted(100); - params.addQueryItem("userid", appsettings->cvalue(context->athlete->cyclist, GC_WIUSER, "").toString()); + params.addQueryItem("action", "getmeas"); + //params.addQueryItem("userid", userid); params.addQueryItem("access_token", access_token); + params.addQueryItem("startdate", QString::number(from.toMSecsSinceEpoch()/1000)); + params.addQueryItem("enddate", QString::number(to.toMSecsSinceEpoch()/1000)); + QUrl url = QUrl( "https://api.health.nokia.com/measure?" + params.toString() ); - qDebug() << "URL used: " << url.url(); + printd("URL: %s", url.url().toStdString().c_str()); QNetworkRequest request(url); + //request.setRawHeader("Authorization", QString("Bearer %1").arg(access_token).toLatin1()); + nam->get(request); emit downloadProgress(50); @@ -171,7 +201,7 @@ WithingsDownload::getBodyMeasures(QString &error, QDateTime from, QDateTime to, if(access_token.isEmpty() && !strToken.isEmpty() &&! strSecret.isEmpty() && strToken != "" && strToken != "0" && strSecret != "" && strSecret != "0" ) { - qDebug() << "OAuth 1.0 API"; + printd("OAuth 1.0 API"); #ifdef GC_HAVE_KQOAUTH oauthRequest->initRequest(KQOAuthRequest::AuthorizedRequest, QUrl("http://wbsapi.withings.net/measure")); @@ -219,7 +249,7 @@ WithingsDownload::getBodyMeasures(QString &error, QDateTime from, QDateTime to, params2.addQueryItem("enddate", QString::number(to.toMSecsSinceEpoch()/1000)); QUrl url = QUrl( "https://wbsapi.withings.net/measure?" + params2.toString() ); - //qDebug() << "URL used: " << url.url(); + printd("URL : ", url.url().toStdString().c_str()); emit downloadStarted(100); @@ -234,7 +264,8 @@ WithingsDownload::getBodyMeasures(QString &error, QDateTime from, QDateTime to, emit downloadEnded(100); #endif - } else { + } else if (access_token.isEmpty()) { + printd("Withings password API"); // account for trailing slash, remove it if it is there (it was the default in preferences) QString server = appsettings->cvalue(context->athlete->cyclist, GC_WIURL, "http://wbsapi.withings.net").toString(); @@ -261,7 +292,7 @@ WithingsDownload::getBodyMeasures(QString &error, QDateTime from, QDateTime to, } } - qDebug() << "response:" << response; + printd("response: %s", response.toStdString().c_str()); QJsonParseError parseResult; if (response.contains("\"status\":0", Qt::CaseInsensitive)) @@ -384,12 +415,12 @@ WithingsDownload::downloadFinished(QNetworkReply *reply) #ifdef GC_HAVE_KQOAUTH void WithingsDownload::onAuthorizedRequestDone() { - // qDebug() << "Request sent to Withings!"; + // printd("Request sent to Withings!"); } void WithingsDownload::onRequestReady(QByteArray r) { - //qDebug() << "Response from the Withings's service: " << response; + //printd("Response from the Withings's service: %s", response..toStdString().c_str()); response = r; loop.exit(0);