Files

208 lines
7.3 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file exoflickrauth.cpp
* @brief Handles all Flickr authentication issues
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (C) 2012 Katharine Berry
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "fscorehttputil.h"
#include "llwindow.h"
#include "llviewerwindow.h"
#include "llbufferstream.h"
#include "lluri.h"
#include "llviewercontrol.h"
#include "llnotificationsutil.h"
#include "exoflickr.h"
#include "llcorehttputil.h"
#include "exoflickrauth.h"
bool exoFlickrAuth::sAuthorisationInProgress = false;
void exoFlickrAuthResponse(const LLSD& aData, exoFlickrAuth::authorized_callback_t aCallback)
{
LLSD header = aData[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS][LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
LLCore::HttpStatus status =
LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(aData[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]);
const LLSD::Binary& rawData = aData[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_RAW].asBinary();
std::string result;
result.assign(rawData.begin(), rawData.end());
LLSD resultLLSD = LLURI::queryMap(result);
aCallback((status.getType() == HTTP_OK), resultLLSD);
}
exoFlickrAuth::exoFlickrAuth(authorized_callback_t callback) : mCallback(callback)
{
// Avoid doubled authentication attempts.
if (sAuthorisationInProgress)
{
delete this;
return;
}
mAuthenticating = true;
sAuthorisationInProgress = true;
if (gSavedPerAccountSettings.getString("ExodusFlickrToken").empty() ||
gSavedPerAccountSettings.getString("ExodusFlickrTokenSecret").empty())
{
beginAuthorisation();
}
else
{
checkAuthorisation();
}
}
exoFlickrAuth::~exoFlickrAuth()
{
if (mAuthenticating)
{
sAuthorisationInProgress = false;
}
}
void exoFlickrAuth::checkAuthorisation()
{
exoFlickr::request("flickr.test.login", LLSD(), boost::bind(&exoFlickrAuth::checkResult, this, _1, _2));
}
void exoFlickrAuth::checkResult(bool success, const LLSD& response)
{
if (!success)
{
LL_WARNS("Flickr") << "Login test failed (HTTP). Reauthenticating." << LL_ENDL;
beginAuthorisation();
}
else
{
if (response["stat"].asString() != "ok")
{
LL_WARNS("Flickr") << "Login test failed: " << response["message"] << "(" << response["code"] << "). Reauthenticating."
<< LL_ENDL;
beginAuthorisation();
}
else
{
LL_INFOS("Flickr") << "Stored Flickr tokens are valid." << LL_ENDL;
mCallback(true, LLSD());
delete this;
return;
}
}
}
void exoFlickrAuth::beginAuthorisation()
{
// Explain and confirm the process to the user.
LLNotificationsUtil::add("ExodusFlickrVerificationExplanation", LLSD(), LLSD(),
boost::bind(&exoFlickrAuth::explanationCallback, this, _1, _2));
}
void exoFlickrAuth::explanationCallback(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0) // OK
{
// Clear out any old authentication tokens
gSavedPerAccountSettings.setString("ExodusFlickrToken", "");
gSavedPerAccountSettings.setString("ExodusFlickrTokenSecret", "");
// Initiate authentication step one.
LLSD params;
params["oauth_callback"] = "oob";
LL_INFOS("Flickr") << "Initialising OAuth authorisation process." << LL_ENDL;
exoFlickr::signRequest(params, "GET", "https://www.flickr.com/services/oauth/request_token");
std::string url = LLURI::buildHTTP("https://www.flickr.com/services/oauth/request_token", LLSD::emptyArray(), params).asString();
exoFlickrAuth::authorized_callback_t callback = boost::bind(&exoFlickrAuth::gotRequestToken, this, _1, _2);
FSCoreHttpUtil::callbackHttpGetRaw(url, boost::bind(exoFlickrAuthResponse, _1, callback));
}
else
{
mCallback(false, LLSD());
delete this;
return;
}
}
void exoFlickrAuth::gotRequestToken(bool success, const LLSD& params)
{
LL_INFOS("Flickr") << "Got request token, success = " << success << LL_ENDL;
if (!success)
{
mCallback(false, LLSD());
delete this;
return;
}
std::string token = params["oauth_token"].asString();
std::string secret = params["oauth_token_secret"].asString();
gSavedPerAccountSettings.setString("ExodusFlickrToken", token);
gSavedPerAccountSettings.setString("ExodusFlickrTokenSecret", secret);
LL_INFOS("Flickr") << "Token = '" << token << "', secret = '" << secret << "'" << LL_ENDL;
// Proceed with stage two.
// We spawn the browser using spawnWebBrowser instead of LLWeb to bypass the
// browser prompt. This would a) be redundant to our earlier notice, and b)
// is unclickable because we have also presented a modal dialog.
gViewerWindow->getWindow()->spawnWebBrowser("https://www.flickr.com/services/oauth/authorize?perms=write&oauth_token=" + token, true);
LLNotificationsUtil::add("ExodusFlickrVerificationPrompt", LLSD(), LLSD(), boost::bind(&exoFlickrAuth::gotVerifier, this, _1, _2));
}
void exoFlickrAuth::gotVerifier(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 1) // Cancel
{
mCallback(false, LLSD());
delete this;
return;
}
// Proceed with stage three.
LLSD params;
params["oauth_verifier"] = response["oauth_verifier"];
exoFlickr::signRequest(params, "GET", "https://www.flickr.com/services/oauth/access_token");
std::string url = LLURI::buildHTTP("https://www.flickr.com/services/oauth/access_token", LLSD::emptyArray(), params).asString();
exoFlickrAuth::authorized_callback_t callback = boost::bind(&exoFlickrAuth::gotAccessToken, this, _1, _2);
FSCoreHttpUtil::callbackHttpGetRaw(url, boost::bind(exoFlickrAuthResponse, _1, callback));
}
void exoFlickrAuth::gotAccessToken(bool success, const LLSD& params)
{
if (success)
{
// Save all the information we got back.
gSavedPerAccountSettings.setString("ExodusFlickrToken", params["oauth_token"].asString());
gSavedPerAccountSettings.setString("ExodusFlickrTokenSecret", params["oauth_token_secret"].asString());
gSavedPerAccountSettings.setString("ExodusFlickrFullName", params["fullname"].asString());
gSavedPerAccountSettings.setString("ExodusFlickrNSID", params["user_nsid"].asString());
gSavedPerAccountSettings.setString("ExodusFlickrUsername", params["username"].asString());
mCallback(true, params);
}
else
{
LLNotificationsUtil::add("ExodusFlickrVerificationFailed");
mCallback(false, params);
}
delete this;
}