JD2022-TU1/main/extern/Camcam/TestApp/account.cpp

3503 lines
100 KiB
C++

#include <windows.h>
#include "DEFINES.H"
//#pragma optimize("",off)
/*
* Version configuration is now in camcam_httpclient.cpp
*/
extern char UserAgent [];
extern char WSBaseURL [];
extern char WebBaseURL [];
volatile int NeedRelaunching = 0;
volatile bool NeedExit = false;
#ifdef ONLINE_MODE
//#undef YOUUP_ORIGIN
//#define YOUUP_ORIGIN "Ubisoft"
//
//#undef ENV_UAT
//#define ENV_UAT
#include <sstream>
#include "ole2.h"
#include "Exdisp.h"
#include "Scene.h"
#include "json-c/json.h"
#include "sha1.h"
#include <process.h>
#include "account.h"
#include "Mshtml.h"
//#define CAMCAM_BRANCH_DEV
//#undef CAMCAM_BRANCH_TEST
//#undef CAMCAM_BRANCH_LIVE
extern u32 ProtocolVersionNumber;
extern bool SetFirstRunFlag();
void LaunchUpdater(const char *proxy)
{
std::string cl = "./gu.exe -background";
if (proxy)
cl += std::string(" -proxy=") + proxy;
WinExec(cl.c_str(), SW_SHOW);
}
const char *WebPageStr [CCamCamAccount::NbWebPages] =
{
"/my-profile",
"/my-collection",
"http://www.youup.com/forum",
"/forum",
"/help",
"/refill"
};
extern HWND hWnd;
extern bool MDString (char *inString, char *digest);
extern char CurrentDir[];
extern CCamCamAccount Account;
extern WORLD *TheScene;
#define HashKeySize 6
static const char Hashkey1[HashKeySize+1] = "4rdZ4c";
#define USE_ACCMAN
#ifdef USE_ACCMAN
static const char *LogInActionPage = "site/app-login";
#else
static const char *LogInActionPage = "site/wlive-login";
static const char *LogOutActionPage = "http://login.live.com/logout.srf";
#endif
const char *ThumbnailPath = "/Disguises/Thumb/";
#ifdef USER_MODE
const char *AdUrl = "http://static5.cdn.ubi.com/u/youup/application/ads/autopromo.html";
#else
const char *AdUrl = "http://static5.cdn.ubi.com/u/youup/application/ads/autopromo23.html";
#endif
static const char Hashkey2[HashKeySize+1] = "{mcc4M";
// Ask for relaunch, will be done in main loop of main thread
void PleaseRelaunchCamCam(int error=1)
{
NeedRelaunching = error;
}
int PageReloaded = 0;
bool IsLeaving = false;
// TEMP Facebook
//std::string TmpFilenameToExport;
// Lua callback utility
// Ex:
// if (prepareLuaFunction("OnBrowserLoading"))
// {
// prepareLuaArg(number, getBrowserId(srcBrowser);
// prepareLuaArg(boolean, true);
// callPreparedLuaCallback(2);
// if (!callbackSuccess)
// return false;
// }
#define ifPrepareLuaFunction(functionName) \
const char *funcName##functionName = #functionName; \
if (TheScene) \
lua_getglobal(TheScene->luaScriptTable[TheScene->currentScript], funcName##functionName); \
if (TheScene)
#define prepareLuaArg(typeToPush, value) \
lua_push##typeToPush(TheScene->luaScriptTable[TheScene->currentScript], value);
#ifndef USER_MODE
#define callPreparedLuaCallback(functionName, nbArgs) \
bool callbackSuccess = true; \
extern int mainThread; \
if (mainThread != GetCurrentThreadId()) MessageBox(NULL, "Bad Threard Access 1!", "YouUp", MB_OK | MB_ICONERROR); \
if (lua_pcall(TheScene->luaScriptTable[TheScene->currentScript],nbArgs,0,0) != 0) \
{ \
char *luaRes = (char *)lua_tostring(TheScene->luaScriptTable[TheScene->currentScript], -1); \
logStr(__FUNCTION__"-err: %s failed: %s", funcName##functionName, luaRes ? luaRes : "unknown error"); \
callbackSuccess = false; \
}
#else
#define callPreparedLuaCallback(functionName, nbArgs) \
bool callbackSuccess = true; \
if (lua_pcall(TheScene->luaScriptTable[TheScene->currentScript],nbArgs,0,0) != 0) \
{ \
char *luaRes = (char *)lua_tostring(TheScene->luaScriptTable[TheScene->currentScript], -1); \
logStr(__FUNCTION__"-err: %s failed: %s", funcName##functionName, luaRes ? luaRes : "unknown error"); \
callbackSuccess = false; \
}
#endif
// ***************************************************************************
bool CCamCamAccount::init()
{
extern const char *VersionStr;
logStr("Starting v%s", VersionStr);
if (!CamCamHttpClient::init(&_IdAccount))
return false;
if (!DownloadQueueTask.init(&_IdAccount))
return false;
if (!_BufferedRequester.init(&_IdAccount))
return false;
_FlashMessageMutex = CreateMutex(NULL, false, "FlashMessageMutex");
return true;
}
// ***************************************************************************
void CCamCamAccount::release()
{
if (_LogInTask && _LogInTask->isRunning())
{
// Cleanly exit if closing during log-in
_HttpClient.abortRequest();
_LogInTask->waitForExit();
}
if (_IsLogged)
logOut();
_HttpClient.release();
}
// ***************************************************************************
bool CamCamHttpClient::onPageError(const char *errorText, const char *func, bool logError)
{
const HttpPage& buffer = _HttpClient.getResponsePage();
const char *sep = strchr(buffer.c_str(), '|');
const char *moreInfoStr = "";
if (sep != NULL)
{
char errCode [64];
strncpy(errCode, buffer.c_str(), min(63, sep-buffer.c_str()));
errCode[min(63, sep-buffer.c_str())] = '\0';
_WSErrorCode = atoi(errCode);
switch (_WSErrorCode)
{
case ERROR_MISSING_ARG:
case ERROR_VERSION_MISMATCH:
LaunchUpdater(_HttpClient.getProxy());
moreInfoStr = getLocErrorMsg(YOUR_APPLICATION_WILL_BE_PATCHED_NOW);
break;
case ERROR_PAGE_DELETED_ACCOUNT:
case ERROR_PAGE_BANNED_ACCOUNT:
case ERROR_INVALID_TOKEN:
if (!_HttpClient.isAborting() && (!Account.getLogin().empty())) // empty login can occur when exiting, from background thread
{
if (NeedRelaunching == 0) // display message only once, even if several events occur before actual relaunch
{
PleaseRelaunchCamCam(_WSErrorCode); // go back to sign-in screen
}
_WSErrorCode = 0; // avoid displaying a tracking error
return false;
}
break;
case ERROR_OBSOLETE_MACADDRESS:
if (!NeedExit)
{
_ErrorString.sprintf("%s: %s", errorText, buffer.substr(0, 4096).c_str());
MessageBox(hWnd, _ErrorString.c_str(), "YouUp", MB_OK | MB_ICONWARNING);
_ErrorString.clear();
NeedExit = true;
}
return false;
break;
case ERROR_ENDOF_DEMO:
//_ErrorString.sprintf("%s: %s - %s", errorText, buffer.substr(0, 4096).c_str(), moreInfoStr);
return false;
break;
default:;
}
}
else
_WSErrorCode = -1;
_ErrorString.sprintf("%s: %s - %s", errorText, buffer.substr(0, 4096).c_str(), moreInfoStr);
if (logError)
logStr("%s-error: %s", func, _ErrorString.c_str());
return false;
}
#ifndef USER_MODE
bool mustKeepAssetFiles()
{
// Note: these variables seem to be always true on start-up (when logging in), but have
// the correct value on release, where we want them to be correct.
if (!TheScene)
return true;
lua_State *L = TheScene->luaScriptTable[TheScene->currentScript];
bool b;
lua_getglobal(L, "prepareOfflineMode");
b = lua_toboolean(L, 1); lua_pop(L, 1);
if (b)
return true;
lua_getglobal(L, "offlineMode");
b = lua_toboolean(L, 1); lua_pop(L, 1);
if (b)
return true;
return false;
}
#endif
//// ***************************************************************************
//bool CCamCamAccount::sameCurrentDemoAndBeta()
//{
// ensureBetaIdDownloaded();
// return (_BetaGameId != "mustdownload");
//}
//
//// ***************************************************************************
//std::string CCamCamAccount::getBetaGameId()
//{
// ensureBetaIdDownloaded();
// return _BetaGameId;
//}
//
//// ***************************************************************************
//void CCamCamAccount::ensureBetaIdDownloaded()
//{
// // TODO: synchronize with log-in thread
//
// if (!_BetaGameId.empty())
// return;
//
// SimpleString<32> args;
// args.sprintf("");
// if (!doRequest("get-beta", "", USE_MORE_INFO, __FUNCTION__, "Could not get beta status"))
// return;
//
// const HttpPage& buffer = _HttpClient.getResponsePage();
// const char *bufPos = buffer.c_str() + 2; // skip "0|"
// _BetaGameId = getNextResultField(&bufPos);
//}
// ***************************************************************************
void CCamCamAccount::clearCards()
{
DownloadQueueTask.clear();
DownloadQueueTask.waitUntilNoCardsNeeded();
#ifndef USER_MODE
if (!mustKeepAssetFiles())
#endif
compactAssetCache();
_Cards.clear();
}
// ***************************************************************************
void CCamCamAccount::compactAssetCache()
{
for (CardElemContainer::CardMap::const_iterator it=_Cards.cardMap().begin(); it!=_Cards.cardMap().end(); ++it)
{
if (it->second && it->second->getType() == CardElement::Zcc)
{
ZccCard *zccCard = static_cast<ZccCard*>(it->second);
TheScene->UNPACK(&zccCard->getFilename()[0], 0, 1, true);
}
}
}
// ***************************************************************************
void CCamCamAccount::makeURL(SimpleString<2048> *url, const char *action, const char *args, const char *baseURL) const
{
if (!baseURL)
baseURL = WSBaseURL;
url->sprintf("%s%s.php?v=%u&ia=%s&lg=%s%s%s", baseURL, action, ProtocolVersionNumber, _IdAccount.c_str(), _LanguageCode.c_str(), ((args[0]!='\0') ? "&" : ""), args);
}
// ***************************************************************************
void CCamCamAccount::makeURL2(SimpleString<2048> *url, const char *actionAndParams, const char *baseURL) const
{
std::string sActionAndParams = actionAndParams;
std::string::size_type p = sActionAndParams.find("?");
if (p != std::string::npos)
{
std::string sAction = sActionAndParams.substr(0, p);
sAction = sAction.substr(0, sAction.rfind(".php"));
std::string sParams = sActionAndParams.substr(p+1);
makeURL(url, sAction.c_str(), sParams.c_str(), baseURL);
}
else
makeURL(url, sActionAndParams.substr(0, sActionAndParams.rfind(".php")).c_str(), "", baseURL);
}
// ***************************************************************************
/*bool CCamCamAccount::getIniValue(const char *iniFilename, const char *varPath1, const char *varPath2, char *dest, const char *func)
{
char varName[1024];
strncpy(varName, varPath1, 1023);
strncat(varName, varPath2, 1023-strlen(varPath2));
if (!TheScene->GetIniValue(const_cast<char*>(iniFilename), varName, dest))
{
_ErrorString.sprintf("IniValue %s%s not found in %s", varPath1, varPath2, iniFilename);
logStr("%s-error: %s", func, _ErrorString.c_str());
return false;
}
return true;
}*/
// ***************************************************************************
void CCamCamAccount::configure(const char *languageCode, bool publishThumbnailFilenames)
{
_LanguageCode.clear();
if (languageCode && *languageCode)
_LanguageCode.appendStr(languageCode, 2);
else
_LanguageCode.appendStr("en", 2);
_PublishThumbnailFilenames = publishThumbnailFilenames;
}
// ***************************************************************************
bool CCamCamAccount::startLogoutPage()
{
SimpleString<2048> url;
makeURL(&url, LogInActionPage, "endsession", WebBaseURL);
openLoginPage(url.Buf);
return true;
}
// ***************************************************************************
bool CCamCamAccount::startAnonymousLogin(RegisterMode registerM, ConnectionMode connection)
{
_ConnectionMode = connection;
_RegisterMode = registerM;
startAsyncLogInSSO("", "anon");
return true;
}
// ***************************************************************************
bool CCamCamAccount::startLoginPage(bool autoLogIn, ConnectionMode connection, RegisterMode registerM)
{
_ConnectionMode = connection;
_RegisterMode = registerM;
SimpleString<2048> url, params;
extern const char *VersionStr;
extern char MacAddress [24];
#ifndef USE_ACCMAN
if (_HasBeenLogged)
{
url = LogOutActionPage;
openLoginPage((char*)url.c_str()); // force disconnection
}
else
#endif
{
#ifdef USE_ACCMAN
char *logOutParam = "";
if (_HasBeenLogged)
logOutParam = "&altUser";
else if (_ConnectionMode == CNT_NORMAL)
logOutParam = "&firstLogin";
else if (_ConnectionMode == CNT_ENDOF_DEMO)
logOutParam = "&endofdemo";
#endif
if (autoLogIn) // first login
params.sprintf("auto&ref=%s&apv=%s&mac=%s%s", YOUUP_ORIGIN, VersionStr, MacAddress, logOutParam);
else
params.sprintf("ref=%s&apv=%s&mac=%s%s", YOUUP_ORIGIN, VersionStr, MacAddress, logOutParam);
makeURL(&url, LogInActionPage, params.c_str(), WebBaseURL);
//if (_HasBeenLogged)
// makeURL(&url, "en/logout/app", "", WebBaseURL);
//else
// makeURL(&url, "site/wlive-login", "auto&forceOld", WebBaseURL);
//
openLoginPage(url.Buf);
}
return true;
}
// ***************************************************************************
void CCamCamAccount::updateEvent(CWebBrowser* webbrowser, UINT message, WPARAM wParam, void* userParam)
{
switch (message)
{
case WM_DESTROY:// ALT + F4
if (getBrowserId(webbrowser) == 1)
{
cancelVideoUploading();
_WebBrowser = NULL; // cancelVideoUploading dont kill windows, but the ALTF4 command have killed it ..
// so we have to create it again next time
}
break;
case BEFORENAVIGATE2:
break;
case DOWNLOADBEGIN:
#ifdef ONLINE_MODE
onBrowserEvent("0", webbrowser);
#endif
break;
case DOWNLOADCOMPLETE:
#ifdef ONLINE_MODE
onBrowserEvent("1", webbrowser);
// Give focus to youup
if(getBrowserId(webbrowser) == 3 && webbrowser->hasFocus())
SetFocus(hWnd);
#endif
break;
case DOCUMENTERROR:
{
char urlStr[2048];
BSTR url;
int code;
url = ((WebEventHandler::DocumentError*) userParam)->URL;
code = ((WebEventHandler::DocumentError*) userParam)->StatusCode;
wcstombs(urlStr, url, 2047);
logStr("CodeError:%d URL: %s", code, urlStr);
// http://www.com.it-berater.org/COM/webbrowser/webbrowser_control.htm
// TRY TO RELOAD ?
if(code == -2146697208) // INET_E_DOWNLOAD_FAILURE
{
if(PageReloaded < 1)
{
Sleep(500);
PageReloaded ++;
webbrowser->navigate(urlStr);
}
}
}
break;
case NAVIGATECOMPLETE2:
{
#ifdef ONLINE_MODE
// Submit url to filter. This is not ideal, because this is the url of a final page, after all redirections.
BSTR url;
webbrowser->GetIWeb()->get_LocationURL(&url);
char urlStr[2048];
wcstombs(urlStr, url, 2047);
#ifdef ENV_UAT
if (urlStr)
logStr("URL: %s", urlStr);
#endif
passInternalWebpageFilter(urlStr, webbrowser);
#endif
}
break;
case DOCUMENTCOMPLETE:
//_IWeb->get_LocationName(&title); // always title
{
#ifdef ONLINE_MODE
// Look for a CamCam Browser Event in the URL
BSTR url;
webbrowser->GetIWeb()->get_LocationURL(&url);
// BSTR to char *
char currentURL[512];
wcstombs(currentURL, url, 511);
std::string cookies;
webbrowser->getAllCookies(&cookies);
wchar_t * Domain;
// Keep cookies to make autoLogin URL
if(getBrowserId(webbrowser) == 0)
{
// Step1: keep UBISOFT cookies first time only
#ifdef ENV_UAT
Domain = L"ubisoft.com";
#else
Domain = L"youup.com";
#endif
if (wcsstr(url, Domain) != NULL)
addDomainCookie("ubisoft.com", cookies, true);
// Step2: keep ACCMAN cookies, pages are differents if we are a Ubisoft account or only a WindowsLive account
Domain = L"ubi.com";
if (wcsstr(url, Domain) != NULL)
addDomainCookie("ubi.com", cookies, true); // keep only last page visited (before redir)
}
const int PrefixSize = 11;
const wchar_t *Prefix = L"ccmbrEvent=";
wchar_t *cbraPos = wcsstr(url, Prefix);
if (cbraPos != NULL)
{
// Convert to char*, extract argument from request string
char ccmbrEvent[2048];
wcstombs(ccmbrEvent, cbraPos, 2047);
char *endCbraPos = strstr(ccmbrEvent, "&");
if (endCbraPos != NULL)
*endCbraPos = '\0';
onBrowserEvent(ccmbrEvent+PrefixSize, webbrowser);
}
else if (getBrowserId(webbrowser) == 0 && !IsLeaving)
{
// Detect Windows Live Delegated Authentication sign-up step
Domain = L"consent.live.com";
if (wcsstr(url, Domain) != NULL)
{
onBrowserEvent("WLconsent", webbrowser);
}
Domain = L"ubi.com";
if (wcsstr(url, Domain) != NULL)
{
onBrowserEvent("AccmanSignUp", webbrowser);
}
Domain = L"login.live.com";
if (wcsstr(url, Domain) != NULL)
{
onBrowserEvent("WLlogin", webbrowser);
}
// check error page
std::string html = "";
webbrowser->getHtmlContent(&html);
if(!html.empty())
{
int bodyPos = html.find("<BODY>");
if(bodyPos != false)
{
html = html.substr(bodyPos+6, html.find("</BODY>") - bodyPos - 6);
int error = atoi(html.substr(0, html.find("|")).c_str());
switch(error)
{
case ERROR_PAGE_DELETED_ACCOUNT:
case ERROR_PAGE_BANNED_ACCOUNT:
//closeLoginPage();
webbrowser->setVisible(false);
webbrowser->setVisibilityForced(true);
MessageBox(NULL, html.substr(html.find("|")+1).c_str(), "YouUp", MB_OK | MB_ICONWARNING);
startLoginPage(false);
break;
}
}
}
}
else if (getBrowserId(webbrowser) == 1)
{
std::string realURL = webbrowser->GetUrl();
if (!realURL.empty() && realURL.find("http://") != std::string::npos)
{
SysReAllocStringLen(&url, NULL, realURL.length());
mbstowcs(url, realURL.c_str(), realURL.length());
}
// -/-/-/-/-/-/-/-/-/-/-/-/-/-/
if (wcsstr(url, L"facebook/youup/connect") != NULL)
{
onBrowserEvent("FBLogin", webbrowser);
}
else if (wcsstr(url, L"facebook.com/login") != NULL) // This URL contains in the next and the cancel arg the success & failure url, so we have to catch it before testing others
// If we dont test the complete URL, its to permit the PHP to change them if needed
{
// Just catch it ..
}
else if (wcsstr(url, L"facebook.com/connect/prompt_permissions") != NULL)
{
const int SessionFieldSize = 8;
wchar_t *wsessionData = wcsstr(url, L"session=");
if (wsessionData)
{
// Convert to char*, extract argument from request string
wsessionData += SessionFieldSize;
const int SessionEventFieldSize = 14;
char sessionEvent[4096] = "FBKeepSession|";
char *sessionData = sessionEvent + SessionEventFieldSize;
wcstombs(sessionData, wsessionData, 4095-SessionEventFieldSize);
char *endSessionData = strstr(sessionData, "&"); // TODO: also get param for granted permissions
if (endSessionData != NULL)
*endSessionData = '\0';
onBrowserEvent(sessionEvent, webbrowser); // todo: instead of reparsing this, call a separate method (same for WL events)
}
}
else if (wcsstr(url, L"facebook/youup/success") != NULL ||
wcsstr(url, L"http://www.facebook.com/connect/login_success") != NULL) // the URL is also in next arg of login URL, so testing against NULL is not sufficient
{
const int SessionFieldSize = 8;
wchar_t *wsessionData = wcsstr(url, L"session=");
if (wsessionData)
{
// Convert to char*, extract argument from request string
wsessionData += SessionFieldSize;
const int SessionEventFieldSize = 12;
char sessionEvent[4096] = "FBConnected|";
char *sessionData = sessionEvent + SessionEventFieldSize;
wcstombs(sessionData, wsessionData, 4095-SessionEventFieldSize);
char *endSessionData = strstr(sessionData, "&"); // TODO: also get param for granted permissions
if (endSessionData != NULL)
*endSessionData = '\0';
onBrowserEvent(sessionEvent, webbrowser); // todo: instead of reparsing this, call a separate method (same for WL events)
}
else
logStr("Facebook session data not found in %s", url);
}
else if (wcsstr(url, L"facebook/youup/failure") != NULL ||
wcsstr(url, L"http://www.facebook.com/connect/login_failure") != NULL) // the URL is also in cancel arg
{
onBrowserEvent("FBFailed", webbrowser);
}
}
// Detect youup pub, if we arrived here its because the ccmbrEvent is not good,
// so we just have to refresh the pub
else if (getBrowserId(webbrowser) == 3)
{
// Hide scrollbar, set margin and padding to 0px
//IDispatch *htmlDispatch;
//HRESULT hr = webbrowser->GetIWeb()->get_Document(&htmlDispatch);
//if (SUCCEEDED(hr) && htmlDispatch)
//{
// IHTMLDocument2 *iHtml;
// hr = htmlDispatch->QueryInterface(IID_IHTMLDocument2, (void**)&iHtml);
// if (SUCCEEDED(hr) && iHtml)
// {
// IHTMLElement *iHtmlElement;
// hr = iHtml->get_body(&iHtmlElement);
// if (SUCCEEDED(hr) && iHtml)
// {
// BSTR body;
// VARIANT varAttribute;
// // Margin // Dont need
// //varAttribute.vt = VT_BSTR;
// //varAttribute.bstrVal = L"0";
// //varAttribute.vt = VT_INT;
// //varAttribute.intVal = 0;
// //iHtmlElement->setAttribute(L"leftmargin", varAttribute);
// //iHtmlElement->setAttribute(L"topmargin", varAttribute);
// //iHtmlElement->setAttribute(L"marginwidth", varAttribute);
// //iHtmlElement->setAttribute(L"marginheight", varAttribute);
// // Scroll
// //varAttribute.vt = VT_BSTR;
// //varAttribute.bstrVal = L"NO";
// //hr = iHtmlElement->setAttribute(L"scroll", varAttribute);
// }
// }
//}
// Give focus to youup if the browser has it
if(webbrowser->hasFocus())
SetFocus(hWnd);
//if(!webbrowser->isFirstLoading())
//{
// // Force refresh if its an internal link
// webbrowser->navigateBack();
// webbrowser->clearHistory();
//}
}
SysFreeString(url);
#endif
}
break;
case COMMANDSTATECHANGE:
break;
case NEWWINDOW3:
if(getBrowserId(webbrowser) == 3 || getBrowserId(webbrowser) == 1)
{
BSTR url;
url = ((WebEventHandler::NewWindowParam*) userParam)->URL;
char currentURL[512];
wcstombs(currentURL, url, 511);
// Cancel the opening of popup
*((WebEventHandler::NewWindowParam*) userParam)->CancelFlagPtr = VARIANT_TRUE;
char *dPos = strstr(currentURL, WebBaseURL);
if (dPos != NULL)
{
char tempURL [512] = "navWithAuth|";
strcat(tempURL, currentURL);
onBrowserEvent(tempURL, webbrowser);
}
else
// Open pub on a new default browser
openExternalWebBrowser(currentURL);
}
break;
default:;
}
}
// ***************************************************************************
bool CCamCamAccount::startAsyncLogInSSO(const char *token, const char *source)
{
if (!_HttpClient.initialized())
return false;
if (_IsLogged)
return false;
performPreLogInTasks();
// Notify Lua (from main thread)
ifPrepareLuaFunction(OnLoggingIn)
{
callPreparedLuaCallback(OnLoggingIn, 0);
}
_LogInTask = new CLogInSSOTask();
static_cast<CLogInSSOTask*>(_LogInTask)->init(token, source);
// Until isLogInComplete() returns true, it's forbidden to use anything from CCamCamAccount!
return _LogInTask->start();
}
// ***************************************************************************
bool CCamCamAccount::startAsyncLogInClassic(const char *login, const char *password)
{
if (!_HttpClient.initialized())
return false;
if (_IsLogged)
return false;
_LogInTask = new CLogInClassicTask();
static_cast<CLogInClassicTask*>(_LogInTask)->init(login, password);
performPreLogInTasks();
// Until isLogInComplete() returns true, it's forbidden to use anything from CCamCamAccount!
return _LogInTask->start();
}
// ***************************************************************************
CCamCamAccount::LogInProgressState CCamCamAccount::getAsyncLogInProgressState()
{
if (_LogInTask)
{
if (_LogInTask->isRunning())
return InProgress;
// _IsLogged is false when the log-in process begins, true on end
LogInProgressState status = _IsLogged ? Success : Failed;
if (status == Success)
performPostLogInTasks();
delete _LogInTask;
_LogInTask = NULL;
return status;
}
return Finished;
}
// ***************************************************************************
// Background thead
void CLogInClassicTask::run()
{
Account.logInClassic(Login.c_str(), Password.c_str());
_IsRunning = false;
}
// ***************************************************************************
// Background thead
void CLogInSSOTask::run()
{
Account.logInSSO(Token.c_str(), Source.c_str());
_IsRunning = false;
}
// ***************************************************************************
// Can be called in a background thread
// During this, _IsLogged is false, so concurrent requests are forbidden
bool CCamCamAccount::logInClassic(const char *login, const char *password)
{
if (!_HttpClient.initialized())
return false;
if (_IsLogged)
return false;
logStr("Logging in using %s on environment %s", login, UserAgent);
// Store login (username or email, at this stage)
_Login.clear();
_Login.appendStr(login, 255);
// Log In
SimpleString<256> startupArgs;
char *referrer = YOUUP_ORIGIN;
extern const char *VersionStr;
startupArgs.sprintf("user=%s&password=%s&lg=%s&ref=%s&apv=%s", login, password, _LanguageCode.c_str(), referrer, VersionStr);
return processLogIn(startupArgs.c_str());
}
// ***************************************************************************
// Can be called in a background thread
// During this, _IsLogged is false, so concurrent requests are forbidden
bool CCamCamAccount::logInSSO(const char *token, const char *source)
{
if (!_HttpClient.initialized())
return false;
if (_IsLogged)
return false;
if (*token)
logStr("Logging in (SSO) on environment %s", UserAgent);
else
logStr("Logging in (anonymous) on environment %s", UserAgent);
_Login.clear();
// Log In
SimpleString<2048> startupArgs;
#if YOUUP_BRANCH_DEMO == 1
unsigned int demo = 1;
#else
unsigned int demo = 0;
#endif
char *referrer = YOUUP_ORIGIN;
extern char MacAddress [24];
extern const char *VersionStr;
startupArgs.sprintf("demo=%u&token=%s&source=%s&lg=%s&ref=%s&apv=%s&connectionmode=%u&registermode=%u", demo, (*token) ? token : MacAddress, source, _LanguageCode.c_str(), referrer, VersionStr, (int)_ConnectionMode, (int)_RegisterMode);
return processLogIn(startupArgs.c_str());
}
// ***************************************************************************
// Can be called in a background thread
// During this, _IsLogged is false, so concurrent requests are forbidden
bool CCamCamAccount::processLogIn(const char *startupArgs)
{
if (!doRequest("login", startupArgs, COULD_NOT_LOG_IN, __FUNCTION__, "", true, false, true))
{
// In case of dual log-in, just retry once, so that this error does not reach the user
if ((_WSErrorCode != ERROR_DUAL_LOGIN) || !doRequest("login", startupArgs, COULD_NOT_LOG_IN, __FUNCTION__, "", true, false, true))
{
_Login.clear();
return false;
}
}
// Get response
HttpPage& buffer = _HttpClient.getAndEditResponsePage();
char *bufPos = &buffer[0] + 2; // skip "0|"
// Store idAccount and username
std::string accountStr = getNextResultField(&bufPos);
_IdAccount.clear();
_IdAccount.appendStr(accountStr.c_str(), 15);
accountStr = getNextResultField(&bufPos);
_Login.clear();
_Login.appendStr(accountStr.c_str(), 255);
// Store credits
_Credits = atoi(getNextResultField(&bufPos).c_str());
// Store asset list
if (bufPos)
{
// Prepare substring for inplace JSON decoding
char *sepAfterHash = strstr(bufPos, "|");
if (sepAfterHash)
{
char *sepAfterJson = strstr(sepAfterHash+1, "|");
if (sepAfterJson)
*sepAfterJson = '\0';
// Decode JSON
clearCards();
if (_CardsToPublishJo)
{
json_object_put(_CardsToPublishJo);
_CardsToPublishJo = NULL;
}
unpackCardsFromBuffer(bufPos);
// Restore original buffer
if (sepAfterJson)
{
*sepAfterJson = '|';
bufPos = sepAfterJson + 1;
}
else
bufPos = NULL;
}
}
else
logStr(__FUNCTION__"-err: could not get asset list from server: %s", buffer.c_str());
// Get server's known hardware md5, keep the hardware snapshot only if should not be (re)sent to the server
std::string serverHardwareMd5;
if (bufPos)
serverHardwareMd5 = getNextResultField(&bufPos);
if (_HardwareSnapshot && _HardwareSnapshot->isDifferent(serverHardwareMd5.c_str()))
_BufferedRequester.setInitialPeriod(3); // expedite sending of snapshot has soon as the buffered requester thread is running
else
clearHardwareSnapshot();
// Initial credits
_CreditsUnspent = false;
if (bufPos)
_CreditsUnspent = (getNextResultField(&bufPos) == "1");
// If we got here, the proxy has been properly set up. Make sure all connection points know it.
const char *proxy = _HttpClient.getProxy();
LaunchUpdater(proxy);
// Store token
std::string cookie = _HttpClient.getResponseHeader("Set-Cookie").c_str();
if (cookie.substr(0, 6) == "Token=")
{
_HttpClient.resetCookie();
setCookie("Token", cookie.substr(6).c_str());
_Token.clear();
_Token.appendStr(cookie.substr(6).c_str(), 255);
DownloadQueueTask.setCookie("Token", cookie.substr(6).c_str());
_BufferedRequester.setCookie("Token", cookie.substr(6).c_str());
}
else
logStr(__FUNCTION__"-err: missing token");
// Start background download task
if (!DownloadQueueTask.isRunning())
{
DownloadQueueTask.setProxy(proxy); // use the proxy that works for account
DownloadQueueTask.start();
}
if (!_BufferedRequester.isRunning())
{
_BufferedRequester.setProxy(proxy);
_BufferedRequester.start(); // must be done after _HardwareSnapshot is dealt with
}
logStr("Logged in as %s", _Login.c_str());
_IsLogged = true; // now it's ok to perform a request from the main thread
return true;
}
// ****************************************************************************
bool CCamCamAccount::getAssetInfo(u32 idAsset)
{
SimpleString<2048> Args;
char *referrer = YOUUP_ORIGIN;
extern const char *VersionStr;
Args.sprintf("lg=%s&ref=%s&apv=%s&idAsset=%u", _LanguageCode.c_str(), referrer, VersionStr, idAsset);
if (!doRequest("get-asset", Args.c_str(), COULD_NOT_GET_ASSET_LIST, __FUNCTION__, "", true, false, true))
{
return false;
}
// Get response
HttpPage& buffer = _HttpClient.getAndEditResponsePage();
char *bufPos = &buffer[0] + 2; // skip "0|"
// Store asset list
if (bufPos)
{
// Prepare substring for inplace JSON decoding
char *sepAfterHash = strstr(bufPos, "|");
if (sepAfterHash)
{
char *sepAfterJson = strstr(sepAfterHash+1, "|");
if (sepAfterJson)
*sepAfterJson = '\0';
// Decode JSON
clearCards();
if (_CardsToPublishJo)
{
json_object_put(_CardsToPublishJo);
_CardsToPublishJo = NULL;
}
unpackCardsFromBuffer(bufPos);
// Restore original buffer
if (sepAfterJson)
{
*sepAfterJson = '|';
bufPos = sepAfterJson + 1;
}
else
bufPos = NULL;
}
return true;
}
else
{
logStr(__FUNCTION__"-err: could not get asset (%u) info from server: %s", idAsset, buffer.c_str());
return false;
}
}
// ****************************************************************************
bool CCamCamAccount::performPreLogInTasks()
{
// Perform first-run tasks (in the main thread)
//static bool storeHardwareSnapshotDone = false;
//if (!storeHardwareSnapshotDone)
//{
// storeHardwareSnapshot();
// storeHardwareSnapshotDone = true;
//}
//extern bool GetFirstRunFlag();
//if (GetFirstRunFlag())
{
SetFirstRunFlag();
}
return true;
}
// ****************************************************************************
bool CCamCamAccount::performPostLogInTasks()
{
if (_HardwareSnapshot)
{
// Url-encode a second time (first time: for correct tracking delimiters; second time: for url)
UEString ue((_HardwareSnapshot->md5() + "," + _HardwareSnapshot->str()).c_str(), true, &_HttpClient);
addBufferedRequest("trk-text", 0, ue.c_str(), true); // send immediately
clearHardwareSnapshot();
}
return true;
}
// ***************************************************************************
int CCamCamAccount::getProtocolNum() const
{
return ProtocolVersionNumber;
}
// ***************************************************************************
bool CCamCamAccount::checkRefreshCards()
{
//TEMP Workaround
//if (_LoginBrowser)
// SetFocus(_LoginBrowser->GetOwnWindow());
if (!_IsLogged)
return false;
// Don't request the server in Demo mode
#if YOUUP_BRANCH_DEMO == 0
// Push asynchronous request
DownloadQueueTask.enqueue(new RefreshCardStatusAction(), true); // check before downloading any pending files
#endif
return true;
}
// ***************************************************************************
bool CCamCamAccount::updateCards(HttpPage *assetsBuffer)
{
if (!_IsLogged)
return false;
if (!assetsBuffer)
{
RefreshCardStatusAction::requestAssets(*this);
assetsBuffer = &_HttpClient.getAndEditResponsePage();
}
HttpPage& buffer = *assetsBuffer;
// Update credits (the fields is after the Json struct, just to avoid a protocol version change)
std::string::size_type lastSepPos = buffer.rfind('|');
const char *bufPos = buffer.c_str() + lastSepPos; // fast-skip Json struct (warning: only work if Credits is the last field)
if (bufPos)
{
++bufPos;
_Credits = atoi(getNextResultField(&bufPos).c_str());
buffer = buffer.substr(0, lastSepPos); // shrink it otherwise unpackCardsFromBuffer() will fail (TODO: see processLogIn())
bufPos = buffer.c_str() + 2; // skip "0|"
_CreditsUnspent = false;
}
// Store (do not clear the cards in place, just update them or add the new ones)
if (_CardsToPublishJo)
{
json_object_put(_CardsToPublishJo);
_CardsToPublishJo = NULL;
}
unpackCardsFromBuffer(bufPos);
logStr("Updated asset list");
ifPrepareLuaFunction(OnCardsChanged)
{
callPreparedLuaCallback(OnCardsChanged, 0);
if (!callbackSuccess)
return false;
}
return true;
}
void samplePrintJson(json_object *jo)
{
if (!jo)
{
logStr("NULL");
return;
}
switch(json_object_get_type(jo))
{
case json_type_boolean:
logStr("Boolean: %u", json_object_get_boolean(jo));
break;
case json_type_double:
logStr("Double: %f", json_object_get_double(jo));
break;
case json_type_int:
logStr("Int: %u", json_object_get_int(jo));
break;
case json_type_object:
logStr("Object");
json_object_object_foreach(jo, key, val)
{
logStr("Key: %s", key);
samplePrintJson(val);
}
break;
case json_type_array:
{
int len = json_object_array_length(jo);
logStr("Array of %u elements", len);
for (int i=0; i!=len; ++i)
{
samplePrintJson(json_object_array_get_idx(jo, i));
}
}
break;
case json_type_string:
logStr("String: %s", json_object_get_string(jo));
break;
}
}
// ***************************************************************************
bool CCamCamAccount::unpackCardsFromBuffer(const char *bufPos)
{
if (_CardsToPublishJo)
return true; // object has not been read yet
// Check server response validity, to prevent usage of simple proxy
std::string serverHash = getNextResultField(&bufPos);
if (!bufPos)
{
logStr(__FUNCTION__"-err: could not get asset list from server");
return false;
}
std::string hashSource = std::string(Hashkey1) + std::string(bufPos) + std::string(Hashkey2);
SimpleString<32> clientHash;
MDString(const_cast<char*>(hashSource.c_str()), clientHash.Buf);
if (strcmp(serverHash.c_str(), clientHash.c_str()) != 0)
{
logStr(__FUNCTION__"-err: invalid asset list from server");
return false;
}
//mc_set_debug(1);
json_object *jo = json_tokener_parse(const_cast<char*>(bufPos));
if (!jo || is_error(jo))
{
logStr(__FUNCTION__"-err: could not parse asset list from server");
return false;
}
//MessageBox(NULL, bufPos, "", MB_OK);
//samplePrintJson(jo);
CardElement::Type errorSource;
if (!_Cards.loadAndPublishCards(jo, _CardsToPublishJo, &errorSource, _PublishThumbnailFilenames))
{
logStr(__FUNCTION__"-err: could not unpack asset list from server (%u)", errorSource);
if (_CardsToPublishJo)
json_object_put(_CardsToPublishJo);
_CardsToPublishJo = NULL;
json_object_put(jo);
return false;
}
//samplePrintJson(_CardsToPublishJo);
json_object_put(jo);
return true;
}
// ***************************************************************************
json_object * CCamCamAccount::getCardJson()
{
json_object *res = _CardsToPublishJo;
if (res)
_CardsToPublishJo = NULL; // as the caller will call json_object_put(), ensure that next time we don't return a deleted object
return res;
}
// ***************************************************************************
/*bool CCamCamAccount::addCredits(int amount)
{
if (!_IsLogged)
return false;
SimpleString<256> args;
args.sprintf("do=addCredits&arg=%d", amount);
if (!doRequest("mission", args.c_str(), USE_MORE_INFO, __FUNCTION__, "Could not add credits"))
return false;
// Update credits
const HttpPage& buffer = _HttpClient.getResponsePage();
const char *bufPos = buffer.c_str() + 2; // skip "0|"
_Credits = atoi(getNextResultField(&bufPos).c_str());
return true;
}*/
// ***************************************************************************
bool CCamCamAccount::logOut(bool forceLogOut)
{
if (!_IsLogged)
{
// Logout for MSN
if(forceLogOut)
{
IsLeaving = true;
startLogoutPage();
}
return false;
}
_HttpClient.resetCookie();
setCookie("Token", _Token.c_str());
// Let the background tasks gently exit, because they need to be logged and to access cards
_BufferedRequester.flushAndExit();
DownloadQueueTask.abortCurrentRequest();
UploadTask.abortUploading();
DownloadQueueTask.waitForExit();
clearCards();
UploadTask.waitForExit();
_BufferedRequester.waitForExit();
closeYouUpAdPage();
if (NeedRelaunching == 0) // if relaunching when dual connection (modified token) found, don't even try to log-out (it would fail anyway)
{
if (!doRequest("logout", "", COULD_NOT_LOG_OUT, __FUNCTION__))
return false;
}
_Login.clear();
_IdAccount.clear();
if (_CardsToPublishJo)
{
json_object_put(_CardsToPublishJo);
_CardsToPublishJo = NULL;
}
logStr("Logged out");
_IsLogged = false;
_HasBeenLogged = true;
// Logout for MSN
if(forceLogOut)
{
IsLeaving = true;
startLogoutPage();
}
return true;
}
// ***************************************************************************
/*bool CCamCamAccount::downloadAsset(TDBIndex index, const char *assetPartCode)
{
if (!_IsLogged)
return false;
const char errorTxt [] = "Could not download asset #%u, %s";
SimpleString<64> args;
#ifdef USER_MODE
args.sprintf("id=%u&t=%s&x=1", index, assetPartCode);
#else
args.sprintf("id=%u&t=%s", index, assetPartCode);
#endif
if (!doRequest("dlfile", args.c_str(), USE_MORE_INFO, __FUNCTION__, printfToStr(errorTxt, index, "failed").c_str(), false))
return false;
// Check if the file was downloaded, or an error was returned
if (_HttpClient.getResponseHeader("Content-Type") != "application/octet-stream")
return onPageError(printfToStr(errorTxt, index, "invalid content").c_str(), __FUNCTION__);
// Get filename
const std::string& contDisp = _HttpClient.getResponseHeader("Content-Disposition");
std::string::size_type p = contDisp.find("filename=");
if (p == std::string::npos)
{
_ErrorString.sprintf(errorTxt, index, "unknown filename");
logStr(__FUNCTION__"-error: %s", _ErrorString.c_str());
return false;
}
char actualFilename[1024];
strncpy(actualFilename, contDisp.substr(p+9).c_str(), 1023);
if (actualFilename[0] == '\0')
{
_ErrorString.sprintf(errorTxt, index, "empty filename");
logStr(__FUNCTION__"-error: %s", _ErrorString.c_str());
return false;
}
// Write buffer to disk
if (!writeDownloadedFile(actualFilename))
{
_ErrorString.sprintf(errorTxt, index, "writing file");
logStr(__FUNCTION__"-error: %s", _ErrorString.c_str());
return false;
}
logStr(__FUNCTION__"-info: wrote %s (%u bytes)", actualFilename, _HttpClient.getResponsePage().size());
return true;
}*/
// ***************************************************************************
/*bool CCamCamAccount::ensureValidZccPresentSynchronous(unsigned int dbIndex, const char *zccFilename, const char *serverHashCode)
{
if (!_IsLogged)
return false;
SimpleString<41> clientHashCode;
CSHA1 sha1;
for (int i=0; i!=5; ++i) // try several attempts, in case the download is fucked up
{
if (sha1.HashFile(zccFilename))
{
sha1.Final();
sha1.ReportHash(clientHashCode.Buf, CSHA1::REPORT_HEX_NOBLANKS);
}
if (strcmp(serverHashCode, clientHashCode.c_str()) == 0)
return true;
// The ZCC is not present or not valid, then download it from the server
downloadAsset(dbIndex, "zcc");
sha1.Reset();
if (i != 0)
Sleep(500);
}
_ErrorString.sprintf("Could not download a valid %s", zccFilename);
logStr(__FUNCTION__"-error: %s", _ErrorString.c_str());
return false;
}*/
// ***************************************************************************
double CCamCamAccount::getDownloadProgress()
{
if (DownloadQueueTask.isRunning() && DownloadQueueTask.getHttpClient().dlTotal() > 0)
{
return DownloadQueueTask.getHttpClient().dlNow() /
DownloadQueueTask.getHttpClient().dlTotal() * 100.00f;
}
return -1.00f;
}
double CCamCamAccount::getDownloadCurrent()
{
if (DownloadQueueTask.isRunning())
return DownloadQueueTask.getHttpClient().dlNow();
else
return 0.00f;
}
double CCamCamAccount::getDownloadTotal()
{
if (DownloadQueueTask.isRunning())
return DownloadQueueTask.getHttpClient().dlTotal();
else
return 0.00f;
}
// ***************************************************************************
bool CCamCamAccount::isDownloading()
{
return DownloadQueueTask.currentDownloadCardElement() != NULL || !DownloadQueueTask.isEmpty();
}
bool CCamCamAccount::cardIsCurrentlyDownloaded(CardElement::Type cardType, u32 id)
{
if (!DownloadQueueTask.isRunning())
return false;
const CardElement *card = _Cards.get(cardType, id);
const CardElement *cardElement = DownloadQueueTask.currentDownloadCardElement();
if (cardElement && card)
return card->Id == cardElement->Id;
return false;
}
// ***************************************************************************
bool CCamCamAccount::ensureThumbnailPresent(CardElement::Type cardType, u32 id, u32 idMedia, lua_State * L)
{
if (!_IsLogged)
return false;
Card *card = _Cards.getCard(cardType, id);
if (!card)
{
logStr(__FUNCTION__"-error: invalid thumbnail %u/%u", cardType, id);
return false;
}
//logStr(__FUNCTION__"-begin %u-%u %s [%u]", cardType, id, card->Thumbnail.c_str(), idMedia);
// If media is not ready, don't ask for a new download
if (card->IsDownloadPending)
{
// If the pending download has no destination media, set its media
DownloadQueueTask.setDestinationMedia(card, idMedia);
return false;
}
// Check if thumbnail files are found on disk, and download if one or them are missing,
// or if the server wants us to refresh them
// At this stage, _ActualPath only contains the filename.
std::string tbPath = std::string(CurrentDir) + std::string(ThumbnailPath) + card->Thumbnail; //TEMP: disguises
if (card->MustRefreshThumbnail || !isFilePresent(tbPath.c_str())) // no integrity check for the thumbnail
{
// We will enqueue the card for background processing (thus the card must not be deleted)
DownloadQueueTask.enqueue(new DownloadThumbnailAction(card, idMedia, std::string()));
return false;
}
/*// Some have an alpha jpg, some not. Now, if the alpha is missing, let it be! (avoid downloading non-alpha thumbnails every time)
std::string tbaPath = tbPath;
std::string::size_type p = tbaPath.rfind(".");
if ((p != std::string::npos) && cardType == CardElement::Asset) //TEMP: theme and roles have no alpha thumb
{
tbaPath.insert(p, "_alpha").c_str();
if (!isFilePresent(tbaPath.c_str()))
{
DownloadQueueTask.enqueue(new DownloadThumbnailAction(card, idMedia, std::string()));
return false;
}
}*/
// Directly load the thumbnail in case file is present (and don't call lua callback, it would crash when called from here)
DownloadThumbnailAction action(card, idMedia, tbPath);
action.onDownloaded(NULL, L);
//logStr(__FUNCTION__"-end %u-%u %s [%u] directly drawn (no download needed)", cardType, id, card->Thumbnail.c_str(), idMedia);
return true;
}
// ***************************************************************************
bool CCamCamAccount::ensureAssetPresent(u32 idZcc, bool immediateUnpacking=false)
{
if (!_IsLogged)
return false;
// Get info
CardElement *card = _Cards.get(CardElement::Zcc, idZcc);
if (!card)
return false;
// If a download has been requested, don't ask for a new download
if (card->IsDownloadPending)
return false;
// Extracting the hash code from the zcc file and unpacking might take too much blocking time, so let the user choose
if (!immediateUnpacking)
{
// We will enqueue the card for background processing (thus the card must not be deleted)
DownloadQueueTask.enqueue(new DownloadZccAction(card));
return false;
}
ZccCard *zccCard = static_cast<ZccCard*>(card);
SimpleString<41> serverHashCode;
if (zccCard->Hash.empty())
{
logStr(__FUNCTION__"-info: not enough information about zcc #%u", idZcc);
return false;
}
// Check if the ZCC is already present, and check its integrity, then download it if not
std::string zccFilename = zccCard->getFilename();
if (!DownloadZccAction::checkFileIntegrity(&zccFilename[0], serverHashCode.Buf))
{
DownloadQueueTask.enqueue(new DownloadZccAction(card));
return false;
}
// Unpack ZCC
if (!TheScene->UNPACK(&zccFilename[0], 0, 1))
{
logStr(__FUNCTION__"-error: could not unpack %s", zccFilename.c_str());
return false;
} else
{
int nbFiles = 0;
char **files = TheScene->GETZCCFILES(&zccFilename[0], &nbFiles);
zccCard->fillClearZCC(files, nbFiles);
}
//logStr(__FUNCTION__"-info: unpacked %s", zccFilename.c_str());
return true;
}
// ***************************************************************************
void CCamCamAccount::getZCCFilename(u32 idZcc, char *filename)
{
ZccCard *zccCard = static_cast<ZccCard*>(_Cards.get(CardElement::Zcc, idZcc));
if (!zccCard)
{
strcpy(filename, "");
return;
}
strncpy(filename, zccCard->getFilename().c_str(), 2047);
}
// ***************************************************************************
bool CCamCamAccount::expediteDownload(CardElement::Type cardType, u32 idZcc)
{
if (!_IsLogged)
return false;
// Get info
CardElement *card = _Cards.get(cardType, idZcc);
if (!card)
return false;
DownloadQueueTask.setPriority(card);
return true;
}
// ***************************************************************************
void CCamCamAccount::checkCompletedDownloads()
{
DownloadAction *downloadAction;
while (downloadAction = DownloadQueueTask.getNextCompletedDownload())
{
downloadAction->onDownloaded(&DownloadQueueTask, TheScene->luaScriptTable[TheScene->currentScript]);
delete downloadAction;
}
}
// ***************************************************************************
// Ex:
// addBufferedRequest("trk_assets.php", 135, "1") H-114
// addBufferedRequest("trk_assets.php", 140, "1") H-114
// addBufferedRequest("trk_assets.php", 135, "0") H-110
// addBufferedRequest("trk_assets.php", 141, "0") H-85s
// addBufferedRequest("trk_assets.php", 140, "1") H-70s
// addBufferedRequest("trk_assets.php", 141, "0") H-12s
// H
// => trk_assets.php?batch=135,1,114;140,1,114;135,0,110...
bool CCamCamAccount::addBufferedRequest(const char *destServerScript, unsigned int objectId, const char *propertyValue, bool expediteSending)
{
if (!_IsLogged)
return false;
// Are we clicking on a card?
//if (!strcmp(destServerScript, "trk-assets") && !strcmp(propertyValue, "1"))
//{
// // TEMPTEST: unpack ZCC now, in main thread!!!
// const std::vector<u32> zccCardOfAsset = _Cards.getChildrenOfCard(CardElement::Asset, objectId);
// if (zccCardOfAsset.empty())
// {
// logStr(__FUNCTION__"-error: could not find zcc for card %u", objectId);
// return false;
// }
// for (std::vector<u32>::const_iterator it=zccCardOfAsset.begin(); it!=zccCardOfAsset.end(); ++it)
// {
// ZccCard *zccCard = static_cast<ZccCard*>(_Cards.get(CardElement::Zcc, *it));
// if (!zccCard)
// {
// logStr(__FUNCTION__"-error: could not find zcc ", *it);
// continue;
// }
// std::string zccFilename = zccCard->getFilename();
// bool noAbort = false;
// if (!TheScene->UNPACK(&zccFilename[0], 0, 1, false, &noAbort))
// {
// logStr(__FUNCTION__"-error: could not unpack %s", zccFilename.c_str());
// return false;
// }
//
// // Bug: the files are not ready ready to be read, even if we sleep here to several seconds
//
// // Note: this should be done even if the same card is clicked, because
// // the script seems to reload the file
// }
//}
return _BufferedRequester.addRequest(destServerScript, objectId, propertyValue, expediteSending);
}
// ***************************************************************************
#ifndef USER_MODE
unsigned int CCamCamAccount::getMemoryUsage() const
{
unsigned int size = 0;
size += sizeof(*this);
size += _BufferedRequester.getMemoryUsage();
size += _Cards.getMemoryUsage();
// ActiveX
if(_YouUpAdBrowser)
size += _YouUpAdBrowser->getMemoryUsage();
if(_ShopBrowser)
size += _ShopBrowser->getMemoryUsage();
if(_LoginBrowser)
size += _LoginBrowser->getMemoryUsage();
if(_WebBrowser)
size += _WebBrowser->getMemoryUsage();
if(_HardwareSnapshot)
size += _HardwareSnapshot->getMemoryUsage();
// CLogInTask = ? sizeof(volatile bool) ?
size += UploadTask.getMemoryUsage();
size += DownloadQueueTask.getMemoryUsage();
//UploadTask.get
/*
json_object *_CardsToPublishJo;
*/
return size;
}
#endif
void CCamCamAccount::sendMessageReceived()
{
MUTEX_LOCK(_FlashMessageMutex);
if (!_FlashMessageToSend.empty())
{
ifPrepareLuaFunction(OnFlashMessageReceived)
{
prepareLuaArg(string, _FlashMessageToSend.c_str());
callPreparedLuaCallback(OnFlashMessageReceived, 1);
}
_FlashMessageToSend.clear();
}
MUTEX_UNLOCK(_FlashMessageMutex);
}
void CCamCamAccount::onFlashMsgReceived(const char *msg)
{
if (_IsLogged && msg)
{
MUTEX_LOCK(_FlashMessageMutex);
// _FlashMessageToSend.clear();
_FlashMessageToSend.appendStr(msg, 2048);
MUTEX_UNLOCK(_FlashMessageMutex);
}
}
// ***************************************************************************
void CCamCamAccount::storeHardwareSnapshot()
{
if (!_HardwareSnapshot)
_HardwareSnapshot = new HardwareSnapshot();
_HardwareSnapshot->fetchData();
}
// ***************************************************************************
void CCamCamAccount::clearHardwareSnapshot()
{
delete _HardwareSnapshot;
_HardwareSnapshot = NULL;
}
// ***************************************************************************
void HardwareSnapshot::fetchData()
{
extern std::string GetHardwareData(bool useUrlFormat=false, CHttpClient *httpClient=NULL);
_Str = GetHardwareData(true, const_cast<CHttpClient*>(&Account.getHttpClient()));
MDString(const_cast<char*>(_Str.c_str()), _Md5);
}
// ***************************************************************************
bool HardwareSnapshot::isDifferent(const char *otherMd5)
{
return (strncmp(_Md5, otherMd5, 64) != 0);
}
// ***************************************************************************
#ifndef USER_MODE
unsigned int HardwareSnapshot::getMemoryUsage() const
{
return _Str.capacity() * sizeof(std::string::value_type) + sizeof(*this);
}
#endif
// ***************************************************************************
//bool HardwareSnapshot::clear()
//{
// _Str.clear();
// _Md5[0] = '\0';
//}
bool CCamCamAccount::cancelArticle()
{
if (!_IsLogged)
return false;
if (!UploadTask.aborted())
return false;
if (_ArticleIsDeleted)
return false;
// ***
// Just Cancel article in DB
if (!doRequest("cancel-article", "", COULD_NOT_CANCEL_ARTICLE, __FUNCTION__))
return false;
_ArticleIsDeleted = true;
return true;
}
// ***************************************************************************
// Now, this function uploads file FIRST
bool CCamCamAccount::selectVideoSite(const char *filename, const char *tbFilename, u32 durationInSec, const char *tempVideo)
{
if (!_IsLogged)
return false;
if (UploadTask.isRunning())
return false;
bool res;
// Open internal browser
SimpleString<2048> url;
SimpleString<2048> args;
// save data
_Filename_tmp = filename;
_tbFilename_tmp = tbFilename;
_DurationTime_tmp = durationInSec;
_TempVideo_tmp = tempVideo;
//TEMP
//makeURL(&url, "site/facebook/youup/index", "", WebBaseURL);
//_UploadingWindowHasForm = true;
//openVideoWebPage(url.Buf);
//TmpFilenameToExport = filename;
if (GetFileNameExtend((char*)filename) == '.JPG')
{
selectVideoSiteAfterUpload (); // Tempory
return true;
}
// Check Login
if (strcmp(_Login.c_str(), "Nouveau") == 0
|| strcmp(_Login.c_str(), "New user") == 0)
{
// ***
args.sprintf("token=%s", _Token.c_str());
makeURL(&url, "site/change-login", args.c_str(), WebBaseURL);
res = openVideoWebPage(url.Buf);
return res;
}
_UploadingWindowHasForm = true;
setNextVideoPublishingState(OpenSelection);
// Directly ...
uploadFileToUbitube(filename, tbFilename, durationInSec, tempVideo);
return true;
//return res;
}
bool CCamCamAccount::selectVideoSiteAfterUpload()
{
SimpleString<2048> url;
SimpleString<2048> args;
// Copy file path to clipboard
unsigned int len = strlen(_Filename_tmp.c_str());
HGLOBAL hBlock = GlobalAlloc(GMEM_MOVEABLE, len+1); // will be owned by the clipboard
if (hBlock)
{
char *text = (char*)GlobalLock(hBlock);
if (text)
{
strncpy(text, _Filename_tmp.c_str(), len+1);
GlobalUnlock(hBlock);
}
}
if (OpenClipboard(NULL))
{
EmptyClipboard();
SetClipboardData(CF_TEXT, hBlock);
CloseClipboard();
}
// Make URL
args.sprintf("filename=%s&tbf=%s&du=%u&new=3", _Filename_tmp.c_str(), _tbFilename_tmp.c_str(), _DurationTime_tmp);
makeURL(&url, "site/select-video-site", args.c_str(), WebBaseURL);
bool res = openVideoWebPage(url.Buf);
return res;
}
// ***************************************************************************
SimpleString<41> CCamCamAccount::getVideoHash(const char *filename)
{
SimpleString<41> fileHash;
CSHA1 sha1;
sha1.HashFile(filename);
sha1.Final();
sha1.ReportHash(fileHash.Buf, CSHA1::REPORT_HEX_NOBLANKS);
return fileHash;
}
// ***************************************************************************
bool CCamCamAccount::isAlreadyUploaded(const char *filename, const char *hash)
{
SimpleString<41> fileHash;
if (!hash)
fileHash = getVideoHash(filename);
else
fileHash.appendStr(hash, 41);
// Check if hash exists
std::string argss = std::string("hash=") + fileHash.c_str();
if (!doRequest("check-article", argss.c_str(), COULD_NOT_CHECK_ARTICLE, __FUNCTION__))
return false;
const HttpPage& bufferCheck = _HttpClient.getResponsePage();
const char *bufPosCheck = bufferCheck.c_str() + 2; // skip "0|"
std::string response = getNextResultField(&bufPosCheck);
return (response.compare("1") == 0);
}
// ***************************************************************************
bool CCamCamAccount::uploadFileToUbitube(const char *filename, const char *tbFilename, u32 durationInSec, const char *tempVideo)
{
if (!_IsLogged)
return false;
if (UploadTask.isRunning())
return false;
SimpleString<41> fileHash = getVideoHash(filename);
if(isAlreadyUploaded(filename, fileHash.c_str()))
{
UploadTask.abortUploading();
selectVideoSiteAfterUpload();
return false;
}
std::string argss = std::string("hash=") + fileHash.c_str();
// Get the Ubitube token from the server
if (!doRequest("create-article", argss.c_str(), COULD_NOT_CREATE_ARTICLE, __FUNCTION__))
{
UploadTask.abortUploading();
return false;
}
_ArticleIsDeleted = false;
// Parse result (expected: 0|articleId|token)
const HttpPage& buffer = _HttpClient.getResponsePage();
const char *bufPos = buffer.c_str() + 2; // skip "0|"
std::string articleId = getNextResultField(&bufPos);
if (!bufPos)
{
_ErrorString.sprintf("Invalid result"); // missing tokenId
logStr(__FUNCTION__"-error: %s", _ErrorString.c_str());
UploadTask.abortUploading();
return false;
}
std::string auth = getNextResultField(&bufPos);
std::string cipherToken = getNextResultField(&bufPos);
std::string videoCreateUrl, videoUploadUrl;
if (bufPos)
{
videoCreateUrl = getNextResultField(&bufPos);
if (bufPos)
videoUploadUrl = getNextResultField(&bufPos);
}
// Initialize task
if (!UploadTask.init(_HttpClient.getProxy()))
{
logStr(__FUNCTION__"-error: %s", UploadTask.errorString().c_str());
return false;
}
CUbitubeUploadTask::Params *params = new CUbitubeUploadTask::Params();
UEString uCipherToken(cipherToken.c_str(), true, &_HttpClient);
strncpy(params->CipherToken, uCipherToken.c_str(), 1023);
strncpy(params->Filename, filename, CUbitubeUploadTask::Params::FilenameLimit-1);
strncpy(params->TbFilename, tbFilename, CUbitubeUploadTask::Params::FilenameLimit-1);
strncpy(params->TempFilename, tempVideo, CUbitubeUploadTask::Params::FilenameLimit-1);
params->VideoCreateUrl = videoCreateUrl;
params->VideoUploadUrl = videoUploadUrl;
params->DurationInSec = durationInSec;
UploadTask.setParams(params);
// Request video id allocation (in the main thread)
unsigned int videoId = UploadTask.getNewVideoId();
if (videoId == ~0)
{
UploadTask.release();
logStr(__FUNCTION__"-error: %s", UploadTask.errorString().c_str());
return false;
}
logStr("Attempting upload of video #%u (length %u s)", videoId, durationInSec);
// Open browser for properties
SimpleString<2048> url;
SimpleString<2048> args;
args.sprintf("auth=%s&aId=%s&vId=%u&new=3%s", auth.c_str(), articleId.c_str(), videoId, (GetFileNameExtend((char*)filename) == '.JPG') ? "&pict" : "");
makeURL(&url, "site/edit-metadata", args.c_str(), WebBaseURL);
_UploadingWindowHasForm = true;
openVideoWebPage(url.Buf);
// Run background task
UploadTask.start();
// TODO: abort upload on exit etc.
setNextVideoPublishingState(OpenEditMetadata);
return true;
}
// ***************************************************************************
void CCamCamAccount::setNextVideoPublishingState(VideoPublishingEvent event)
{
const char *errorTxt = __FUNCTION__"-error: invalid transition st:%u ev:%u";
#define FSM_TRANSITION(trEvent, newState) \
if (event == trEvent) \
{ _VideoPublishingState = newState; }
#define FSM_DEFAULT() \
logStr(errorTxt, _VideoPublishingState, event);
switch (_VideoPublishingState)
{
case Off:
case CancelledSelection:
case CancelledMetadata:
case CancelledUploadError:
case UploadedSubmitted:
case ExternalSiteOpened:
FSM_TRANSITION(OpenSelection, Selection)
else FSM_TRANSITION(OpenEditMetadata, UploadingEditMetadata)
else FSM_TRANSITION(Cancel, CancelledSelection)
else FSM_DEFAULT();
break;
case Selection:
FSM_TRANSITION(OpenEditMetadata, UploadingEditMetadata)
else FSM_TRANSITION(OpenExternalSite, ExternalSiteOpened)
else FSM_TRANSITION(Cancel, CancelledSelection)
else FSM_DEFAULT();
break;
case UploadingEditMetadata:
FSM_TRANSITION(CompleteUploading, UploadedEditMetadata)
else FSM_TRANSITION(SubmitMetadata, UploadingSubmitted)
else FSM_TRANSITION(Cancel, CancellingMetadata)
else FSM_TRANSITION(UploadingError, CancelledUploadError)
else FSM_DEFAULT();
break;
case CancellingMetadata:
FSM_TRANSITION(CancelEnd, CancelledMetadata)
else FSM_TRANSITION(Cancel, CancelledSelection)
else FSM_DEFAULT();
case UploadingSubmitted:
FSM_TRANSITION(CompleteUploading, UploadedSubmitted)
else FSM_TRANSITION(UploadingError, CancelledUploadError)
else FSM_TRANSITION(Cancel, CancelledMetadata)
else FSM_DEFAULT();
break;
case UploadedEditMetadata:
FSM_TRANSITION(SubmitMetadata, UploadedSubmitted)
else FSM_TRANSITION(Cancel, CancelledMetadata)
else FSM_DEFAULT();
break;
default:
FSM_DEFAULT();
}
}
// ***************************************************************************
s32 CCamCamAccount::getUploadProgressPct()
{
if (!_IsLogged)
return 0;
// Get progress percentage from FSM and upload progress ratio
bool uploadEnded = false;
s32 value;
if (_VideoPublishingState >= VPSD_LOW)
value = 100;
else if (_VideoPublishingState >= VPSU_LOW)
{
value = min(99, max(1, (u32)(UploadTask.uploadProgress()*100.0)));
if (!UploadTask.isRunning() && !UploadTask.aborted())
uploadEnded = true;
}
else if (_VideoPublishingState >= VPSC_LOW)
value = -1;
else if (_VideoPublishingState >= VPS1_LOW)
value = 1;
else
value = 0;
if (UploadTask.aborted())
{
setNextVideoPublishingState(Cancel);
cancelArticle();
value = -1;
}
// On upload completion/cancellation, handle event
if (((value == -1) || uploadEnded))// && _WebBrowser)
{
const CUbitubeUploadTask::Params *params = UploadTask.getParams();
if (params)
{
if (uploadEnded)
{
if ((_VideoPublishingState == CancellingMetadata) && UploadTask.aborted())
{
setNextVideoPublishingState(CancelEnd);
}
// Display upload result (success or failure)
else if (UploadTask.errorString().empty())
{
// Obsolete now, we dont wait the end of upload
if (!_UploadingWindowHasForm) // otherwise, it will be closed after setting metadata
{
/*
SimpleString<2048> url;
makeURL(&url, "site/edit-metadata", "success&new=1", WebBaseURL);
_WebBrowser->navigate(url.Buf);
*/
}
logStr("Video %suploaded (pending metadata to submit)", (value == -1) ? "not ": "");
setNextVideoPublishingState(CompleteUploading);
}
else
{
/*
SimpleString<2048> url;
SimpleString<2048> args;
UEString uFile(params->Filename, true, &_HttpClient);
UEString uReason(UploadTask.errorString().c_str(), true, &_HttpClient);
args.sprintf("file=%s&failure=%s&new=1", uFile.c_str(), uReason.c_str());
makeURL(&url, "site/edit-metadata", args.c_str(), WebBaseURL);
_WebBrowser->navigate(url.Buf);
*/
logStr("Error while uploading video: %s", UploadTask.errorString().c_str());
setNextVideoPublishingState(UploadingError);
}
}
UploadTask.freeParams();
}
}
//if (_WebBrowser)
//{
// static s32 prevValue = -1; //TEMP
// if (prevValue != value)
// {
// prevValue = value;
// SimpleString<1024> html;
// //html.sprintf("<script>if (document.getElementById('progress')) document.getElementById('progress').innerHTML = %d;</script>", value);
// html.sprintf("%u", value);
// _WebBrowser->setHTMLContent(html.c_str());
// if (value == 100)
// _WebBrowser->setHTMLContent("<script>if (document.getElementById('OK')) document.getElementById('OK').Show();</script>");
// }
//}
if (value == 1 && !UploadTask.aborted())
{
extern float PourcentConvertion;
if (PourcentConvertion >= 2)
{
return -PourcentConvertion;
}
}
return value;
}
// ***************************************************************************
void setRepaintMode(bool flag)
{
if (flag)
{
TheScene->ulLockMode++;
}
else
{
if (TheScene->ulLockMode > 0)
--TheScene->ulLockMode;
}
}
// ***************************************************************************
bool CCamCamAccount::openTeaserPage(int idArticle)
{
if(!_TeaserBrowser)
_TeaserBrowser = new CWebBrowser();
if (_TeaserBrowser->GetOwnWindow() == NULL)
{
_TeaserBrowser->init(hWnd, /*WS_POPUP | */ WS_CHILD | WS_VISIBLE);
_TeaserBrowser->attachObserver(this);
setRepaintMode(true);
}
std::string URL = std::string(WebBaseURL) + "site/shop-article.php?ref=" + std::string(YOUUP_ORIGIN) + "&lg=" + _LanguageCode.c_str() + "&idArticle=";
std::ostringstream s;
s << idArticle;
URL = URL + std::string(s.str());
_TeaserBrowser->navigate((char*)URL.c_str());
return true;
}
// ***************************************************************************
void CCamCamAccount::closeTeaserPage()
{
if(_TeaserBrowser)
{
if (_TeaserBrowser->initialized())
setRepaintMode(false);
_TeaserBrowser->detachObserver(this);
_TeaserBrowser->setVisible(false);
delete _TeaserBrowser;
_TeaserBrowser = NULL;
}
}
// ***************************************************************************
void CCamCamAccount::setTeaserPage(int x, int y, int w, int h)
{
if(!_TeaserBrowser)
_TeaserBrowser = new CWebBrowser();
_TeaserBrowser->setPosAndSize(x, y, w, h);
}
// ***************************************************************************
void CCamCamAccount::setTeaserVisible(bool visible)
{
if (_TeaserBrowser)
_TeaserBrowser->setVisible(visible);
}
// ***************************************************************************
bool CCamCamAccount::shopHasFocus() const
{
return (_ShopBrowser && _ShopBrowser->hasFocus());
}
// ***************************************************************************
bool CCamCamAccount::createYouUpAdPage()
{
if(!_YouUpAdBrowser)
_YouUpAdBrowser = new CWebBrowser();
if (_YouUpAdBrowser->GetOwnWindow() == NULL)
{
_YouUpAdBrowser->init(hWnd, /*WS_POPUP | */ WS_CHILD | WS_VISIBLE);
_YouUpAdBrowser->attachObserver(this);
//_YouUpAdBrowser->setActive(false);
setRepaintMode(true);
}
reloadYouUpAdPage(0);
return true;
}
// ***************************************************************************
void CCamCamAccount::closeYouUpAdPage()
{
if(_YouUpAdBrowser)
{
if (_YouUpAdBrowser->initialized())
setRepaintMode(false);
_YouUpAdBrowser->detachObserver(this);
//_YouUpAdBrowser->release();
delete _YouUpAdBrowser;
_YouUpAdBrowser = NULL;
}
}
// ***************************************************************************
void CCamCamAccount::youUpSetPosAndSize(int x, int y, int w, int h)
{
if (!_YouUpAdBrowser)
_YouUpAdBrowser = new CWebBrowser();
_YouUpAdBrowser->setPosAndSize(x, y, w, h);
}
// ***************************************************************************
bool CCamCamAccount::youupPugPageHasFocus()
{
// Pub never has to get Focus on main windows ..
if(_YouUpAdBrowser && _YouUpAdBrowser->hasFocus())
{
// SetFocus(hWnd);
return true;
}
else return false;
}
// ***************************************************************************
void CCamCamAccount::setYouUpAdPageVisible(bool visible)
{
if(_YouUpAdBrowser)
{
_YouUpAdBrowser->setVisible(visible);
}
}
// ***************************************************************************
void CCamCamAccount::reloadYouUpAdPage(int page, bool displayJustOneTime)
{
if(_YouUpAdBrowser)
{
std::string URL = std::string(AdUrl) + "?ia=" + _IdAccount.c_str() + "&lg=" + _LanguageCode.c_str() + "&displayonetime=" + (displayJustOneTime ? "1" : "0") + "&type=";
std::ostringstream s;
s << page;
URL = URL + std::string(s.str());
_YouUpAdBrowser->navigate((char*)URL.c_str());
}
}
// ***************************************************************************
const char* CCamCamAccount::getPage(WebPage page)
{
if (page < NbWebPages && WebPageStr[page])
return WebPageStr[page];
return NULL;
}
// ***************************************************************************
bool CCamCamAccount::openGuestPage(char *arg)
{
extern char MacAddress[24];
extern const char *VersionStr;
std::string URL = std::string(WebBaseURL) + "site/app-anon-end.php?apv=" + std::string(VersionStr) + "&ref=" + std::string(YOUUP_ORIGIN) + "&lg=" + std::string(_LanguageCode.c_str()) + "&mac=" + std::string(MacAddress) + "&button=";
if (arg)
URL = URL + std::string(arg);
return openLoginPage((char*)URL.c_str());
}
// ***************************************************************************
bool CCamCamAccount::callGuestPage(const char* page)
{
ifPrepareLuaFunction(callGuestPage)
{
int arg = 0;
if (page != NULL)
{
arg ++;
prepareLuaArg(string, page);
}
callPreparedLuaCallback(callGuestPage, arg);
return true;
}
return false;
}
// ***************************************************************************
bool CCamCamAccount::openLoginPage(char *url)
{
if (!_LoginBrowser)
_LoginBrowser = new CWebBrowser();
if (_LoginBrowser->GetOwnWindow() == NULL)
{
//_LoginBrowser->setPosAndSize(40, 40, 660, 400);
_LoginBrowser->init(hWnd, /*WS_POPUP | */ WS_CHILD | WS_VISIBLE);
_LoginBrowser->attachObserver(this);
setRepaintMode(true);
}
_LoginBrowser->navigate(url);
return true;
}
// ***************************************************************************
void CCamCamAccount::closeLoginPage()
{
if (_LoginBrowser)
{
if (_LoginBrowser->initialized())
setRepaintMode(false);
_LoginBrowser->detachObserver(this);
_LoginBrowser->setVisible(false);
//_LoginBrowser->release();
delete _LoginBrowser;
_LoginBrowser = NULL;
}
}
// ***************************************************************************
void CCamCamAccount::loginSetPosAndSize(int x, int y, int w, int h)
{
if (!_LoginBrowser)
_LoginBrowser = new CWebBrowser();
_LoginBrowser->setPosAndSize(x, y, w, h);
}
// ***************************************************************************
bool CCamCamAccount::openVideoWebPage(char *url)
{
if (!_WebBrowser)
{
_WebBrowser = new CWebBrowser();
_WebBrowser->setPosAndSize(40, 40, 660, 460);
_WebBrowser->init(hWnd, WS_VISIBLE);
}
setRepaintMode(true);
_WebBrowser->attachObserver(this);
_WebBrowser->navigate(url);
return true;
}
// ***************************************************************************
void CCamCamAccount::closeVideoWebPage()
{
setRepaintMode(false);
if (_WebBrowser)
{
_WebBrowser->setVisible(false);
_WebBrowser->detachObserver(this);
}
_UploadingWindowHasForm = false;
if (_FacebookSession &&
_FacebookSession->isRunning && _FacebookSession->getCurrentTask() == FacebookSession::FB_UPLOAD_PHOTOS)
{
// Cancel Uploading
}
}
// ***************************************************************************
void CCamCamAccount::cancelVideoUploading()
{
UploadTask.abortUploading(); // the FLV conversion is interupted now
closeVideoWebPage();
setNextVideoPublishingState(Cancel);
}
// ***************************************************************************
void CCamCamAccount::setShopVisible(bool visible, const char *pageAndParams)
{
if (visible)
{
if (!_ShopBrowser)
_ShopBrowser = new CWebBrowser();
if (_ShopBrowser->GetOwnWindow() == NULL)
{
_ShopBrowser->init(hWnd, WS_CHILD | WS_VISIBLE); // WS_CHILD => transparent :(
setRepaintMode(true);
}
_ShopBrowser->attachObserver(this);
if (pageAndParams && *pageAndParams)
shopNavigate(pageAndParams);
} else
_ShopBrowser->detachObserver(this);
if (_ShopBrowser)
_ShopBrowser->setVisible(visible);
}
// ***************************************************************************
bool CCamCamAccount::shopNavigate(const char *pageAndParams)
{
if (!_ShopBrowser)
return false;
SimpleString<2048> url, paramStr;
extern unsigned int FLASHPORT ;
#ifdef USER_MODE
paramStr.sprintf("&v=%u%s&x=1&ia=%s", ProtocolVersionNumber, /*TEMP*/(ProtocolVersionNumber == 8) ? "b" : "", _IdAccount.c_str());
#else
paramStr.sprintf("&v=%u%s&ia=%s&port=%u", ProtocolVersionNumber, /*TEMP*/(ProtocolVersionNumber == 8) ? "b" : "", _IdAccount.c_str(), FLASHPORT);
#endif
std::string params = std::string("site/shop.php?token=") + std::string(_Token.c_str()) + std::string(paramStr.c_str()) + std::string("&lg=") + std::string(_LanguageCode.c_str());
makeURL2(&url, params.c_str(), WebBaseURL); // no more shop URL
return _ShopBrowser->navigate(url.Buf);
}
// ***************************************************************************
void CCamCamAccount::shopSetPosAndSize(int x, int y, int w, int h)
{
if (!_ShopBrowser)
_ShopBrowser = new CWebBrowser();
_ShopBrowser->setPosAndSize(x, y, w, h);
//SetFocus(hWnd);
}
// ***************************************************************************
std::string CCamCamAccount::getLoggedURL(const char * url)
{
if (!_IsLogged)
return std::string();
//if(_ConnectionMode != CNT_NORMAL)
// return "";
std::string destURL = std::string("destURL=") + std::string(url);
_HttpClient.setWantRedirection(false);
// ubisoft Cookies (camcam)
setDomainCookie("ubisoft.com");
setCookie("Token", _Token.c_str());
doRequest("get-auth-accman", destURL.c_str(), SILENT, __FUNCTION__, "", false);
doRequest("get-auth-accman", destURL.c_str(), SILENT, __FUNCTION__, "", false);
// Accman bridge URL
std::string URLLocation = _HttpClient.getResponseHeader("Location");
_HttpClient.setCredentials("hommk", "zA8p!nst");
// ubisoft Cookies (preprod)
setDomainCookie("ubi.com");
doRequest(URLLocation.c_str(), "", SILENT, __FUNCTION__, "", false, true); //)
// get brige URL from POST FORM
std::string bridgeURL = _HttpClient.getResponsePage();
if(!bridgeURL.empty())
{
bridgeURL = bridgeURL.substr( bridgeURL.find("bridgeURL=") + 10); // skipt bridgeURL="
bridgeURL = bridgeURL.substr(0, bridgeURL.find('"'));
}
// Previous config
_HttpClient.setWantRedirection(true);
_HttpClient.setMaxRedirection(10);
initUserPassword();
setCookie("Token", _Token.c_str());
// PLZ GET FINAL URL HERE :)
UEString ue(bridgeURL.c_str(), false, &_HttpClient);
#ifndef USER_MODE
logStr("Bridge: %s", ue.c_str());
#endif
return ue.c_str();
}
// ***************************************************************************
std::string CCamCamAccount::getLoggedProfileURL(WebPage page)
{
if (page >= NbWebPages)
return std::string();
if (WebPageStr[page] && (WebPageStr[page][0] != '/'))
{
// Plain URL without auto-log-in
return std::string(WebPageStr[page]);
}
else
{
if (!_IsLogged)
return std::string();
std::string URL = std::string(WebBaseURL) + std::string(_LanguageCode.c_str()) + std::string(WebPageStr[page]);
return getLoggedURL(URL.c_str());
}
}
// ***************************************************************************
bool CCamCamAccount::navigateWithAuth(const char *pageAndParams, CWebBrowser *browser)
{
if (!_IsLogged)
return false;
// TODO
// Get the auth token from the server
if (!doRequest("get-auth-accman", (browser==_ShopBrowser) ? "context=shop" : "", COULD_NOT_GET_AUTH_TOKEN, __FUNCTION__))
return false;
// Parse result (expected: 0|token)
const HttpPage& buffer = _HttpClient.getResponsePage();
const char *bufPos = buffer.c_str() + 2; // skip "0|"
std::string pageAndAllParams = std::string(pageAndParams) + std::string("&auth=") + getNextResultField(&bufPos);
// Navigate in specified browser
SimpleString<2048> url;
makeURL2(&url, pageAndAllParams.c_str(), (browser==_ShopBrowser) ? WebBaseURL : WSBaseURL);
return browser->navigate(url.Buf);
}
// ***************************************************************************
bool CCamCamAccount::passInternalWebpageFilter(const char *url, CWebBrowser *srcBrowser)
{
if (srcBrowser != _LoginBrowser)
return true;
// This is an opt-out filter because we are conservative to not break the sign-in (we don't know exhaustively the pages used by the Windows Live sign-in)
// If MSN displays an intermediary page for logging-in, it should have the destination block in argument so that it's still recognized
const char *extBlockList[] =
{
// From Sign-In Page
"accountservices.passport.net",
"www.pointdecontact.net",
"privacy.microsoft.com",
"account.live.com",
"www.microsoft.com",
"feedback.live.com",
"ManageCards.srf",
"g.live.com",
"go.microsoft.com",
"g.msn.com",
"MSPPError",
// From Delegated Consent Page
"help.live.com",
"www.live.com",
"home.live.com",
"calendar.live.com",
"mail.live.com",
"fss.live.com",
"gallery.live.com",
"onecare.live.com",
"skydrive.live.com",
"spaces.live.com",
"office.microsoft.com",
"officelive.com",
"xbox.com",
"msn.com"
};
unsigned int nbBlocked = sizeof(extBlockList) / sizeof(extBlockList[0]);
for (unsigned int i=0; i!=nbBlocked; ++i)
{
if (strstr(url, extBlockList[i]) != NULL)
{
// Launch in external browser
// if _HasBeenLogged = true, dont open URL, its page called by MSN after logout
if (!_HasBeenLogged) openExternalWebBrowser(url);
else
_HasBeenLogged = false;
// Return to home
SimpleString<2048> homeUrl, params;
extern const char *VersionStr;
if(IsLeaving)
{
makeURL(&homeUrl, LogInActionPage, "endsession", WebBaseURL);
} else
{
params.sprintf("ref=%s&apv=%s&altUser", YOUUP_ORIGIN, VersionStr);
makeURL(&homeUrl, LogInActionPage, params.c_str(), WebBaseURL);
}
if (_LoginBrowser)
_LoginBrowser->navigate(homeUrl.Buf);
return false;
}
}
return true;
}
// ***************************************************************************
void CCamCamAccount::callOnBrowserLoadingCallback(int browserId, bool status)
{
ifPrepareLuaFunction(OnBrowserLoading)
{
prepareLuaArg(integer, browserId);
prepareLuaArg(boolean, status);
callPreparedLuaCallback(OnBrowserLoading, 2);
}
}
// ***************************************************************************
void CCamCamAccount::openExternalWebBrowserUrlDecode(const char *uerl)
{
UEString url(uerl, false, &_HttpClient);
openExternalWebBrowser(url.c_str());
}
// ***************************************************************************
bool CCamCamAccount::openExternalWebBrowser(const char *url)
{
// Workaround for 1-minute freeze when a Windows Live conversation is running.
// It's not even sure it works around 100% of cases, because the freeze seems to occur when the peer shows his video feed.
//extern INPUT_IO *MainDriver;
//extern u32 DRVO_ISLINKED(INPUT_IO *pDRO);
//if (MainDriver && DRVO_ISLINKED(MainDriver))
//{
// ::MessageBox(hWnd, getLocErrorMsg(NOT_AVAILABLE_WHILE_DRIVER_USED), "YouUp", MB_OK | MB_ICONEXCLAMATION);
// return true;
//}
if ((strncmp(url, "http://", 7) == 0) || (strncmp(url, "https://", 8) == 0))
{
//HANDLE Handle = CreateFile("dummy.html", GENERIC_READ | GENERIC_WRITE,
// FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
// NULL, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, NULL);
//LPTSTR defaultBrowser = (LPTSTR)malloc(100 * sizeof(TCHAR));
//HINSTANCE hinstance = FindExecutable("dummy.html", NULL, defaultBrowser);
//CloseHandle(Handle);
//FILE* f = fopen("opera.bat", "wt");
//std::string batfile = "\"" + std::string(defaultBrowser) + "\" \"" + url + "\"";
//fprintf(f, batfile.c_str());
//fclose(f);
//ShellExecute(NULL, "open", "opera.bat", NULL, NULL, SW_HIDE);
//if (defaultBrowser)
//{
// logStr("defaultBrowser: %s", commandLine.c_str());
// std::string commandLine = " \"" + url + "\"";
// std::string::size_type p = sActionAndParams.find("?");
// if (p != std::string::npos)
// {
// std::string sAction = sActionAndParams.substr(0, p);
// sAction = sAction.substr(0, sAction.rfind(".php"));
// std::string sParams = sActionAndParams.substr(p+1);
// makeURL(url, sAction.c_str(), sParams.c_str(), baseURL);
// }
//
//
// HINSTANCE r = ShellExecute(NULL, "open",
// std::string(defaultBrowser).c_str(),
// NULL,
// NULL, SW_SHOWNORMAL);
//} else
//{
// HINSTANCE r = ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
// if ((int)r<=32)
// logStr("ShellExecute error: %s", GetLastError());
// else
// logStr("ShellExecute success");
// return ((int)r)>32;
//}
//STARTUPINFO si;
//PROCESS_INFORMATION pi;
//ZeroMemory( &si, sizeof(si) );
//si.cb = sizeof(si);
//ZeroMemory( &pi, sizeof(pi) );
//
//std::string commandLine = std::string(defaultBrowser) + " \"" + url + '"';
////// Start the child process.
//if( !CreateProcess(NULL, // No module name (use command line)
// (LPSTR)commandLine.c_str(), // Command line
// NULL, // Process handle not inheritable
// NULL, // Thread handle not inheritable
// FALSE, // Set handle inheritance to FALSE
// 0, // No creation flags
// NULL, // Use parent's environment block
// NULL, // Use parent's starting directory
// &si, // Pointer to STARTUPINFO structure
// &pi ) // Pointer to PROCESS_INFORMATION structure
//)
//{
// logStr( "CreateProcess failed (%d).\n", GetLastError() );
// return false;
//}
//return true;
// Wait until child process exits.
//WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
//CloseHandle( pi.hProcess );
//CloseHandle( pi.hThread );
/*SHELLEXECUTEINFO execInfo;
execInfo.cbSize = sizeof(execInfo);
execInfo.fMask = SEE_MASK_ASYNCOK;
execInfo.hwnd = hWnd;
execInfo.lpVerb = "open";
execInfo.lpFile = url;
execInfo.lpParameters = NULL;
execInfo.lpDirectory = NULL;
execInfo.nShow = SW_SHOWNORMAL;
execInfo.hInstApp = 0;
execInfo.hProcess = NULL;
bool res = ShellExecuteEx(&execInfo);
*/
//return true;
HINSTANCE r = ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
return ((int)r)>32;
}
else
{
logStr("Invalid URL in openExternalWeb argument: %s", url);
return false;
}
}
// ***************************************************************************
void CCamCamAccount::closeBrowserWindow(CWebBrowser *browser)
{
if (browser == _WebBrowser)
closeVideoWebPage();
else if (browser)
browser->setVisible(false);
}
// ***************************************************************************
inline bool isBrowserEvent(const char *event, const char *eventName, const char **arg)
{
unsigned int len = strlen(eventName);
if (strncmp(event, eventName, len) == 0)
{
*arg = event + len;
if (**arg)
++(*arg);
return true;
}
else
return false;
}
// ***************************************************************************
// Called from main thread (can call lua callbacks)
void CCamCamAccount::onBrowserEvent(const char *event, CWebBrowser *srcBrowser)
{
const char *arg = NULL;
if (isBrowserEvent(event, "0", &arg) || isBrowserEvent(event, "1", &arg))
{
callOnBrowserLoadingCallback(getBrowserId(srcBrowser), (event[0] == '0'));
}
else if (isBrowserEvent(event , "logout", &arg))
{
ifPrepareLuaFunction(OnLoggingOut)
{
callPreparedLuaCallback(OnLoggingOut, 0);
}
}
else if (isBrowserEvent(event, "hasRegister", &arg))
{
_ConnectionMode = CNT_NORMAL;
ifPrepareLuaFunction(OnConnectionModeChanged)
{
prepareLuaArg(number, (int)_ConnectionMode);
callPreparedLuaCallback(OnConnectionModeChanged, 1);
}
if(_IsLogged)
logOut(false);
startAsyncLogInSSO(srcBrowser->getCookieValue("applogtoken").c_str(), arg);
}
else if (isBrowserEvent(event, "log-in2", &arg))
{
ifPrepareLuaFunction(OnSignUpStep)
{
prepareLuaArg(number, 5); // Connection running
callPreparedLuaCallback(OnSignUpStep, 1);
}
startAsyncLogInSSO(srcBrowser->getCookieValue("applogtoken").c_str(), arg);
}
else if (isBrowserEvent(event, "log-in", &arg))
{
ifPrepareLuaFunction(OnSignUpStep)
{
prepareLuaArg(number, 5); // Connection running
callPreparedLuaCallback(OnSignUpStep, 1);
}
std::string value = srcBrowser->getCookieValue("webauthtoken");
if (!value.empty())
startAsyncLogInSSO(value.c_str(), "wl");
else if(*arg)
startAsyncLogInSSO(arg, "wl");
}
else if (isBrowserEvent(event, "anonymous", &arg))
{
//startAsyncLogInSSO("", "anon");
// Lua will close the page
ifPrepareLuaFunction(closeGuestPage)
{
callPreparedLuaCallback(closeGuestPage, 0);
}
}
else if (isBrowserEvent(event, "failedLogIn", &arg))
{
PleaseRelaunchCamCam();
}
else if (isBrowserEvent(event, "navWithAuth", &arg))
{
if (*arg)
{
if(_ConnectionMode != CNT_NORMAL)
{
openExternalWebBrowser(arg);
}
else
{
std::string url = getLoggedURL(arg).c_str();
openExternalWebBrowser(url.c_str());
}
}
}
else if (isBrowserEvent(event, "mustAuth", &arg))
{
if (*arg)
{
UEString pageAndParams(arg, false, &_HttpClient);
navigateWithAuth(pageAndParams.c_str(), srcBrowser);
}
}
else if (isBrowserEvent(event, "login-set", &arg))
{
if(*arg)
{
UEString login(arg, false, &_HttpClient);
_Login.clear();
_Login.appendStr(login.c_str(), 124);
ifPrepareLuaFunction(OnLoginUpdated)
{
callPreparedLuaCallback(OnLoginUpdated, 0);
}
selectVideoSite(_Filename_tmp.c_str(), _tbFilename_tmp.c_str(), _DurationTime_tmp, _TempVideo_tmp.c_str());
}
}
else if (isBrowserEvent(event, "publish", &arg))
{
if (*arg)
{
UEString params(arg, false, &_HttpClient); // urldecode
arg = params.c_str();
std::string filename = getNextResultField(&arg);
if (arg)
{
std::string tbFilename = getNextResultField(&arg);
if (arg)
{
std::string durationStr = getNextResultField(&arg);
if (!durationStr.empty())
{
std::string tempvideoStr = getNextResultField(&arg);
if (arg)
uploadFileToUbitube(filename.c_str(), tbFilename.c_str(), atoi(durationStr.c_str()), tempvideoStr.c_str());
}
}
}
}
}
else if (isBrowserEvent(event, "cancelVideoUploading", &arg))
{
cancelVideoUploading();
}
else if (isBrowserEvent(event, "closeVideoUploading", &arg))
{
closeVideoWebPage();
}
else if (isBrowserEvent(event, "setMetadata", &arg))
{
// Changes: we go now directly on "selectvideosite"
setNextVideoPublishingState(SubmitMetadata);
/*
if (UploadTask.completed() && srcBrowser)
{
// _WebBrowser->setHTMLContent("<script>if (document.getElementById('progress')) document.getElementById('progress').innerHTML = 100;</script>");
// _WebBrowser->setHTMLContent("<script>if (document.getElementById('OK')) document.getElementById('OK').Show();</script>");
// _WebBrowser->setVisible(false);
SimpleString<2048> url;
makeURL(&url, "site/edit-metadata", "success&new=1", WebBaseURL);
//makeURL(&url, "site/select-video-site", "success", WebBaseURL);
srcBrowser->navigate(url.Buf);
}
*/
_UploadingWindowHasForm = false;
selectVideoSiteAfterUpload();
}
else if (isBrowserEvent(event, "videoUploadNextStep", &arg))
{
selectVideoSiteAfterUpload();
}
else if (isBrowserEvent(event, "refresh", &arg))
{
updateCards();
}
else if (isBrowserEvent(event, "giveAsset", &arg)) // can have argument using "giveAsset|argument"
{
//if (srcBrowser)
// srcBrowser->setVisible(false);
updateCards();
}
else if (isBrowserEvent(event, "closeUploadWindow", &arg))
{
// We dont have start upload, but LUA wait cancel event
setNextVideoPublishingState(Cancel);
closeBrowserWindow(srcBrowser);
}
else if (isBrowserEvent(event, "openExternalVideoSite", &arg) || // must be before openExternalWeb
isBrowserEvent(event, "openExternalWebC", &arg)) // must be before openExternalWeb
{
if (*arg)
{
setNextVideoPublishingState(OpenExternalSite);
openExternalWebBrowserUrlDecode(arg);
}
closeBrowserWindow(srcBrowser);
}
else if (isBrowserEvent(event, "openExternalWeb", &arg))
{
if (*arg)
openExternalWebBrowserUrlDecode(arg);
}
else if (isBrowserEvent(event, "openWebProfile", &arg))
{
openExternalWebBrowser(getLoggedProfileURL(Profile).c_str());
}
else if (isBrowserEvent(event, "WLconsent", &arg))
{
ifPrepareLuaFunction(OnSignUpStep)
{
prepareLuaArg(number, 2); // Windows Live Consent = step 2 of 2
callPreparedLuaCallback(OnSignUpStep, 1);
}
}
else if (isBrowserEvent(event, "AccmanSignUp", &arg))
{
ifPrepareLuaFunction(OnSignUpStep)
{
prepareLuaArg(number, -1); // Accman sign up
callPreparedLuaCallback(OnSignUpStep, 1);
}
}
else if (isBrowserEvent(event, "WLlogin", &arg))
{
ifPrepareLuaFunction(OnSignUpStep)
{
prepareLuaArg(number, 1); // Accman sign up
callPreparedLuaCallback(OnSignUpStep, 1);
}
}
else if (isBrowserEvent(event, "FBConnected", &arg))
{
// Decode JSON session
UEString fbSessionStr(arg, false, &_HttpClient);
if (!_FacebookSession)
_FacebookSession = new FacebookSession();
_FacebookSession->setFromJSONSession(const_cast<char *>(fbSessionStr.c_str())); // the buffer will unallocate on destruction of fbSessionStr
_FacebookSession->run(FacebookSession::FB_UPLOAD_PHOTOS);
// Set broswer to loading ..
SimpleString<2048> url;
makeURL(&url, "site/select-video-site", "pict&loading&new=3", WebBaseURL);
_WebBrowser->navigate(url.Buf);
}
else if (isBrowserEvent(event, "FBKeepSession", &arg))
{
// Decode JSON session
UEString fbSessionStr(arg, false, &_HttpClient);
if (!_FacebookSession)
_FacebookSession = new FacebookSession();
_FacebookSession->setFromJSONSession(const_cast<char *>(fbSessionStr.c_str())); // the buffer will unallocate on destruction of fbSessionStr
}
else if (isBrowserEvent(event, "FBFailed", &arg))
{
// Set broswer to loading ..
SimpleString<2048> url;
makeURL(&url, "site/select-video-site", "pict&failure&new=3", WebBaseURL);
_WebBrowser->navigate(url.Buf);
}
else if (isBrowserEvent(event, "FBLogin", &arg))
{
// Try to login a facebook user with registred settings first .
if (!_FacebookSession)
_FacebookSession = new FacebookSession();
if (!_FacebookSession->loadSettings())
{
// Force connect ..
SimpleString<2048> url;
makeURL(&url, "site/select-video-site", "pict&fc&new=3", WebBaseURL); // fc = forceconnect
_WebBrowser->navigate(url.Buf);
} else
{
// AutoLogin ..
_FacebookSession->run(FacebookSession::FB_AUTO_CONNECTION);
}
}
else if (isBrowserEvent(event, "FBUrl", &arg))
{
openExternalWebBrowser("http://www.facebook.com/editapps.php");
// Force connect ..
SimpleString<2048> url;
makeURL(&url, "site/select-video-site", "pict&fc&fburl&new=3", WebBaseURL); // Just tell to user that he has to reconnect
_WebBrowser->navigate(url.Buf);
// Logout Facebook
if (!_FacebookSession) return;
_FacebookSession->run(FacebookSession::FB_CLOSE_SESSION);
}
else if (isBrowserEvent(event, "patch", &arg))
{
LaunchUpdater(_HttpClient.getProxy());
}
else if (isBrowserEvent(event, "runPatchAndExit", &arg))
{
LaunchUpdater(_HttpClient.getProxy());
PleaseRelaunchCamCam(ERROR_MANDATORY_PATCH);
}
}
HDC CCamCamAccount::getBrowserHandle(int browser)
{
CWebBrowser *srcBrowser;
switch (browser)
{
case 0: srcBrowser = _LoginBrowser;
break;
case 1: srcBrowser = _WebBrowser;
break;
case 2: srcBrowser = _ShopBrowser;
break;
case 3: srcBrowser = _YouUpAdBrowser;
break;
default:
return NULL;
}
if (!srcBrowser)
return NULL;
HWND handle = srcBrowser->GetOwnWindow();
return GetDC(handle);
}
bool CCamCamAccount::closeSessionFromFacebook()
{
if (!_FacebookSession)
return false;
std::map<std::string, const char *> mpArgs;
mpArgs["method"] = "auth.expiresession";
// TEMPTEMP. TODO: free it
CHttpClient *_pHttpClient = new CHttpClient();
if (!_pHttpClient->init())
{
_ErrorString.sprintf("Could not auth.expiresession task");
delete _pHttpClient;
return false;
}
_pHttpClient->setProxy(_HttpClient.getProxy()); // use the proxy that works for account
_ErrorString.clear();
if (_FacebookSession->makeUrl(&mpArgs, _pHttpClient))
{
// Send to Facebook API
if (_FacebookSession->sendHttpRequest(_pHttpClient))
{
delete _pHttpClient;
// Ok !
return true;
}
}
delete _pHttpClient;
// Something wrong ...
return false;
}
bool CCamCamAccount::autoConnectToFacebook()
{
if (!_FacebookSession)
return false;
std::map<std::string, const char *> mpArgs;
mpArgs["method"] = "users.getloggedinuser";
// TEMPTEMP. TODO: free it
CHttpClient *_pHttpClient = new CHttpClient();
if (!_pHttpClient->init())
{
_ErrorString.sprintf("Could not users.getloggedinuser task");
delete _pHttpClient;
return false;
}
_pHttpClient->setProxy(_HttpClient.getProxy()); // use the proxy that works for account
_ErrorString.clear();
if (_FacebookSession->makeUrl(&mpArgs, _pHttpClient))
{
// Send to Facebook API
if (_FacebookSession->sendHttpRequest(_pHttpClient))
{
delete _pHttpClient;
// Gets infos from last response, facebook will send us back the Uid
if (atoi(_FacebookSession->lastResponse()) != atoi(_FacebookSession->uid()))
return false;
// Ok !
return true;
}
}
delete _pHttpClient;
// Something wrong ...
return false;
}
// References:
// http://wiki.developers.facebook.com/index.php/Photos.upload
bool CCamCamAccount::uploadPhotoToFacebook()
{
if (!_FacebookSession)
return false;
std::map<std::string, const char *> mpArgs;
mpArgs["method"] = "photos.upload";
mpArgs["caption"] = "Photo par YouUp http://www.youup.com/";
// TEMPTEMP. TODO: free it
CHttpClient *_pHttpClient = new CHttpClient();
if (!_pHttpClient->init())
{
_ErrorString.sprintf("Could not init photos.upload task");
delete _pHttpClient;
return false;
}
_pHttpClient->setProxy(_HttpClient.getProxy()); // use the proxy that works for account
_ErrorString.clear();
if (_FacebookSession->makeUrl(&mpArgs, _pHttpClient))
{
// Add picture
_pHttpClient->addMultipartParam("data", CHttpClient::MultipartParam(_Filename_tmp.c_str(), CHttpClient::ParamLoadFile));
// Send to Facebook API
if (_FacebookSession->sendHttpRequest(_pHttpClient))
{
// Gets infos from last response
json_object *jsonFBSession = json_tokener_parse(const_cast<char *>(_FacebookSession->lastResponse()));
if (!jsonFBSession || is_error(jsonFBSession))
{
_FacebookSession->setLastUrl("");
_FacebookSession->setLastLink("");
delete _pHttpClient;
return false;
}
// Small picture uploaded
json_object *jo = json_object_object_get(jsonFBSession, "src");
if (!jo)
{
_FacebookSession->setLastUrl("");
_FacebookSession->setLastLink("");
delete _pHttpClient;
return false;
}
_FacebookSession->setLastUrl(json_object_get_string(jo));
// Link to the picture page on Facebook
jo = json_object_object_get(jsonFBSession, "link");
if (!jo)
{
_FacebookSession->setLastLink("");
delete _pHttpClient;
return false;
}
// Encode URL
UEString ue(json_object_get_string(jo), true, _pHttpClient);
_FacebookSession->setLastLink((char*)ue.c_str());
// Ok !
delete _pHttpClient;
return true;
}
}
// Something wrong ...
delete _pHttpClient;
return false;
}
void CCamCamAccount::checkFacebookThread()
{
if (!_FacebookSession || _FacebookSession->isRunning)
return;
if (!_FacebookSession->isChecked)
{
_FacebookSession->isChecked = true;
// To manage the application task (with webbrowser)
if (_WebBrowser && _WebBrowser->isVisible())
{
// Execute task
switch (_FacebookSession->getCurrentTask())
{
case FacebookSession::FB_CLOSE_SESSION:
{
// Just reset settings
_FacebookSession->resetSettings();
}
break;
case FacebookSession::FB_UPLOAD_PHOTOS:
{
// Change browser ... && Make URL
SimpleString<2048> url;
SimpleString<2048> args;
args.sprintf("pict&%s&new=3&url=%s&link=%s", _FacebookSession->isSuccess ? "success" : "failure", _FacebookSession->lastUrl(), _FacebookSession->lastLink());
makeURL(&url, "site/select-video-site", args.c_str(), WebBaseURL);
_WebBrowser->navigate(url.Buf);
}
break;
case FacebookSession::FB_AUTO_CONNECTION:
{
if (_FacebookSession->isSuccess)
{
// Action to do ..
// Upload ?
_FacebookSession->run(FacebookSession::FB_UPLOAD_PHOTOS);
// Send notification to webbrowser
SimpleString<2048> url;
makeURL(&url, "site/select-video-site", "pict&loading&new=3", WebBaseURL);
_WebBrowser->navigate(url.Buf);
return; // dont set _CurrentTask ..
} else
{
// Change browser ... force connect
SimpleString<2048> url;
makeURL(&url, "site/select-video-site", "pict&fc&new=3", WebBaseURL);
_WebBrowser->navigate(url.Buf);
}
}
break;
default: // FacebookSession::TaskList::FB_NONE
return;
}
// Set current task to NONE
_FacebookSession->setCurrentTask(FacebookSession::FB_NONE);
}
}
}
// Reference:
// http://wiki.developers.facebook.com/index.php/Authorization_and_Authentication_for_Desktop_Applications
// TODO: save
bool FacebookSession::setFromJSONSession(char *joStr)
{
// Parse
json_object *jsonFBSession = json_tokener_parse(const_cast<char *>(joStr));
if (!jsonFBSession || is_error(jsonFBSession))
{
logStr(__FUNCTION__"-err: could not parse Facebook session");
return false;
}
// Session key
json_object *jo = json_object_object_get(jsonFBSession, "session_key");
if (!jo)
{
logStr(__FUNCTION__"-err: could not get Facebook session key");
return false;
}
_SessionKey = json_object_get_string(jo);
// Secret
jo = json_object_object_get(jsonFBSession, "secret");
if (!jo)
{
logStr(__FUNCTION__"-err: could not get Facebook session secret");
return false;
}
_Secret = json_object_get_string(jo);
// Uid
jo = json_object_object_get(jsonFBSession, "uid");
if (!jo)
{
logStr(__FUNCTION__"-err: could not get Facebook uid");
return false;
}
_Uid = json_object_get_string(jo);
logStr("Logged in on Facebook with user id %s", _Uid.c_str());
// Expiration unixtime or 0
jo = json_object_object_get(jsonFBSession, "expires");
_NoExpire = (jo && (json_object_get_int(jo) == 0));
if (_NoExpire)
{
// Save settings
saveSettings ();
}
return true;
}
bool FacebookSession::loadSettings ()
{
extern char AppDataPath[];
char SettingsFile[2048];
strncpy(SettingsFile, AppDataPath, 2047);
#ifdef USER_MODE
strcat(SettingsFile, "FacebookSettings.cfgx");
#else
strcat(SettingsFile, "FacebookSettings.cfg");
#endif
if (isFilePresent(SettingsFile))
{
#ifdef USER_MODE
SettingsFile[strlen(SettingsFile)-1] = 0; // IniFileManager will readd the x suffix in USER_MODE
#endif
char IniValue [512];
TheScene->GetIniValue(SettingsFile, "Id", IniValue);
std::string IdAccount = std::string(IniValue);
if (Account.getIdAccount() != atoi (IdAccount.c_str()))
{
// Not the right account ...
return false;
}
// Gets other values ..
TheScene->GetIniValue(SettingsFile, "SessionKey", IniValue);
_SessionKey = std::string(IniValue);
if (_SessionKey.empty()) return false;
TheScene->GetIniValue(SettingsFile, "Secret", IniValue);
_Secret = std::string(IniValue);
if (_Secret.empty()) return false;
TheScene->GetIniValue(SettingsFile, "Uid", IniValue);
_Uid = std::string(IniValue);
if (_Uid.empty()) return false;
return true;
}
return false;
}
/*
* Save Settings in a cfg file (located in APPDATA/youup)
*/
bool FacebookSession::saveSettings ()
{
extern char AppDataPath[];
char SettingsFile[2048];
strncpy(SettingsFile, AppDataPath, 2047);
#ifdef USER_MODE
strcat(SettingsFile, "FacebookSettings.cfgx");
#else
strcat(SettingsFile, "FacebookSettings.cfg");
#endif
char IdAccount[10];
itoa(Account.getIdAccount(), IdAccount, 10);
TheScene->SetIniValue(SettingsFile, "Id" , IdAccount);
TheScene->SetIniValue(SettingsFile, "SessionKey", (char*)_SessionKey.c_str());
TheScene->SetIniValue(SettingsFile, "Secret" , (char*)_Secret.c_str());
TheScene->SetIniValue(SettingsFile, "Uid" , (char*)_Uid.c_str());
TheScene->SaveIniFile(SettingsFile);
return true;
}
// Reset all settings
bool FacebookSession::resetSettings()
{
_SessionKey.clear();
_Secret.clear();
_Uid.clear();
return saveSettings ();
}
// References:
// http://wiki.developers.facebook.com/index.php/How_Facebook_Authenticates_Your_Application
// Make the sig param, and add them to CHttpClient
// moreArgs has to have at least :
// - method
bool FacebookSession::makeUrl (std::map<std::string, const char *> * moreArgs, CHttpClient * httpClient)
{
if (moreArgs == NULL || httpClient == NULL)
{
logStr("Error: Could not init FacebookSession::makeUrl, args are NULL");
return false;
}
SimpleString<10> callIdStr;
callIdStr.sprintf("%u", timeGetTime());
std::map<std::string, const char *> mpArgs;
#ifdef ENV_UAT
mpArgs["api_key"] = "d2003020c041b48b7ef5d88f84b64299";
#else
mpArgs["api_key"] = "18bfeaa8cdc5b7c1a12b5301c234f1b0";
#endif
mpArgs["call_id"] = callIdStr.c_str();
mpArgs["v"] = "1.0";
mpArgs["format"] = "JSON";
mpArgs["session_key"] = sessionKey();
// Add the other param
for (std::map<std::string, const char *>::const_iterator it=moreArgs->begin(); it!=moreArgs->end(); ++it)
{
mpArgs[it->first] = it->second;
}
std::string paramsForSig;
for (std::map<std::string, const char *>::const_iterator it=mpArgs.begin(); it!=mpArgs.end(); ++it) // ordered traversal
{
paramsForSig += it->first + "=" + std::string(it->second); // no separator between args
httpClient->addMultipartParam(it->first.c_str(), it->second);
}
paramsForSig += secret();
char sig [33];
MDString(const_cast<char*>(paramsForSig.c_str()), sig);
httpClient->addMultipartParam("sig", sig);
return true;
}
bool FacebookSession::sendHttpRequest(CHttpClient * httpClient)
{
SimpleString<1024> _ErrorString;
//if (!_pHttpClient->sendRequest("http://camcam.ubisoft.com/", "", true, true, true) || (_pHttpClient->getRequestCode() >= 400))
if (!httpClient->sendMultipartRequest("http://api.facebook.com/restserver.php") || (httpClient->getRequestCode() >= 400))
{
if (httpClient->getRequestCode() == CHttpClient::ErrorInvalidFile)
_ErrorString.sprintf("Could not upload file to Facebook, file could not be read");
else
{
_ErrorString.sprintf("Could not upload files, error code %u", httpClient->getRequestCode());
if (httpClient->getRequestCode() >= 400)
_ErrorString.appendStr(httpClient->getResponsePage().c_str(), ~0);
}
}
if (!_ErrorString.empty())
{
//::MessageBox(TheScene->OwnerHwnd, _ErrorString.c_str(), "Error", MB_OK);
logStr("Error: %s: %s", _ErrorString.c_str(), httpClient->getErrorStr());
return false;
}
else
{
// Decode JSON session
UEString fbSessionStr(httpClient->getResponsePage().c_str(), false, httpClient);
_LastHttpResponse = std::string (fbSessionStr.c_str());
return true;
}
}
void FacebookSession::run(TaskList task)
{
if (isRunning)
return;
_CurrentTask = task;
isRunning = true;
isSuccess = false;
_FacebookThread = (HANDLE) _beginthreadex( NULL , 0,
backgroundTask , (void*)this, 0, NULL);
}
unsigned __stdcall
FacebookSession::backgroundTask(void *params)
{
// Execute task
switch (((FacebookSession*) params)->getCurrentTask())
{
case FacebookSession::FB_UPLOAD_PHOTOS:
((FacebookSession*) params)->isSuccess = Account.uploadPhotoToFacebook ();
break;
case FacebookSession::FB_AUTO_CONNECTION:
((FacebookSession*) params)->isSuccess = Account.autoConnectToFacebook ();
break;
case FacebookSession::FB_CLOSE_SESSION:
((FacebookSession*) params)->isSuccess = Account.closeSessionFromFacebook ();
break;
}
// Reset vars ..
((FacebookSession*) params)->isRunning = false;
((FacebookSession*) params)->isChecked = false;
return 1;
}
//_beginthread(BackgroundTaskRun, 0, this);
#endif // ONLINE_MODE