3503 lines
100 KiB
C++
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®istermode=%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
|