phoenix-firestorm/indra/newview/exoflickrauth.cpp

209 lines
6.8 KiB
C++
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/**
* @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( LLSD const &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)
{
int 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)
{
int 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;
}