#include "pch.h" #include // #define NO_CLUB_SERVER_CONNECTION 1 // comment out before checkin ////////////////////////////////////////////////////////////////////////////// // // ZoneClub Screen // ////////////////////////////////////////////////////////////////////////////// bool g_fZoneAuth = #ifdef USEAUTH true; #else false; #endif extern bool g_bDownloadZoneMessage; extern bool g_bDownloadNewConfig; extern bool g_bDisableZoneClub; extern bool g_bSkipAutoUpdate; const char * szValidCfg = "THIS IS A VALID CONFIG FILE"; const char * szValidMotd = "THIS IS A VALID MESSAGE OF THE DAY FILE"; class ZoneClubScreen : public Screen, public LogonSite, public TrekClientEventSink, public IIntegerEventSink, public IAutoUpdateSink, public EventTargetContainer { private: TRef m_pmodeler; TRef m_ppane; TRef m_pbuttonGames; TRef m_pbuttonGamesBig; TRef m_pbuttonZoneEvents; TRef m_pbuttonSquads; TRef m_pbuttonMainMenu; TRef m_pbuttonPlayerProfile; TRef m_pbuttonLeaderboard; TRef m_pbuttonWeb; TRef m_pMDLFileImage; char m_szName[c_cbPassportName]; char m_szPW[c_cbName]; char m_szPWOrig[c_cbName]; char m_szConfig[MAX_PATH]; BOOL m_fRememberPW; bool m_bErrorOccured; bool m_bMessageStage; // if true then we are at the Message of the day stage, if false then we are at the Config download stage bool m_bTriedCurrentLogin; IHTTPSession * m_pSession; bool m_bConnectLobby; // true means lobby server; false means Club server TRef m_pmsgBox; ScreenID m_screenPostConnect; static bool s_bWasAuthenticated; public: ZoneClubScreen(Modeler* pmodeler, Number* ptime) : m_pSession(NULL), m_bErrorOccured(false), m_bMessageStage(false), m_pmsgBox(NULL), m_pmodeler(pmodeler), m_bTriedCurrentLogin(false) { TRef pnsZoneClubData = GetModeler()->CreateNameSpace("zoneclubdata"); pnsZoneClubData->AddMember("timeStart", ptime->MakeConstant()); TRef pns = pmodeler->GetNameSpace( trekClient.GetIsZoneClub() ? "zoneclubscreen" : "zonepublicscreen"); CastTo(m_ppane, pns->FindMember("screen")); CastTo(m_pMDLFileImage, (Value*)pns->FindMember("messageImage")); CastTo(m_pbuttonGames, pns->FindMember("gamesButtonPane")); CastTo(m_pbuttonGamesBig, pns->FindMember("gamesBigButtonPane")); CastTo(m_pbuttonZoneEvents, pns->FindMember("zoneEventsButtonPane")); CastTo(m_pbuttonSquads, pns->FindMember("squadsButtonPane")); CastTo(m_pbuttonMainMenu, pns->FindMember("mainmenuButtonPane")); CastTo(m_pbuttonPlayerProfile, pns->FindMember("playerProfileButtonPane")); CastTo(m_pbuttonLeaderboard, pns->FindMember("leaderboardButtonPane")); CastTo(m_pbuttonWeb, pns->FindMember("webButtonPane")); AddEventTarget(OnButtonGames, m_pbuttonGames->GetEventSource()); AddEventTarget(OnButtonGames, m_pbuttonGamesBig->GetEventSource()); AddEventTarget(OnButtonMainMenu, m_pbuttonMainMenu->GetEventSource()); if (trekClient.GetIsZoneClub()) { AddEventTarget(OnButtonZoneEvents, m_pbuttonZoneEvents->GetEventSource()); AddEventTarget(OnButtonSquads, m_pbuttonSquads->GetEventSource()); AddEventTarget(OnButtonPlayerProfile, m_pbuttonPlayerProfile->GetEventSource()); AddEventTarget(OnButtonZoneWeb, m_pbuttonWeb->GetEventSource()); AddEventTarget(OnButtonLeaderBoard, m_pbuttonLeaderboard->GetEventSource()); } //temporarily disable all buttons m_pbuttonMainMenu->SetEnabled(false); // force download to finish before leaving this screen m_pbuttonGames->SetEnabled(false); m_pbuttonGamesBig->SetEnabled(false); if (trekClient.GetIsZoneClub()) { m_pbuttonSquads->SetEnabled(false); m_pbuttonZoneEvents->SetEnabled(false); m_pbuttonPlayerProfile->SetEnabled(false); m_pbuttonLeaderboard->SetEnabled(false); } pmodeler->UnloadNameSpace(pns); BeginConfigDownload(); if (g_bQuickstart) AddEventTarget(OnButtonGames, GetWindow(), 0.01f); trekClient.FlushSessionLostMessage(); } ~ZoneClubScreen() { //trekClient.m_pzac = NULL; if (m_pSession) { delete m_pSession; m_pSession = NULL; } } // connect to either Zone Lobby server or Zone Club (wrapper to provide appropriate prompt) void ConnectToZone(bool bConnectLobby, ScreenID screenid) { ZString strPrompt; #ifdef USEAUTH if (trekClient.GetCfgInfo().bUsePassport) strPrompt = "Sign in to Microsoft Passport"; else strPrompt = "Sign in to the Microsoft Gaming Zone"; #else strPrompt = "Enter a call sign (player name) to use for this game."; #endif ConnectToZone(bConnectLobby, screenid, strPrompt); } // connect to either Zone Lobby server or Zone Club void ConnectToZone(bool bConnectLobby, ScreenID screenid, const ZString& strPrompt) { if (bConnectLobby) { if (trekClient.GetIsZoneClub()) { if (trekClient.GetCfgInfo().strClubLobby.IsEmpty()) { TRef pmsgBox = CreateMessageBox( "The Allegiance Zone lobby is not available at the moment. " + ZString(trekClient.GetCfgInfo().strPublicLobby.IsEmpty() ? "Please try again later." : "Please try the free lobby instead.") ); GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false); return; } } else { if (trekClient.GetCfgInfo().strPublicLobby.IsEmpty()) { TRef pmsgBox = CreateMessageBox( "The free lobby is not available at the moment. " + ZString(trekClient.GetCfgInfo().strClubLobby.IsEmpty() ? "Please try again later." : "Please try the Allegiance Zone instead.") ); GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false); return; } } } else { if (trekClient.GetCfgInfo().strClub.IsEmpty()) { TRef pmsgBox = CreateMessageBox( "The Club server is not available at the moment. " "Please try again later." ); GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false); return; } } m_bConnectLobby = bConnectLobby; m_screenPostConnect = screenid; assert (!trekClient.LoggedOn() && !trekClient.m_fm.IsConnected()); HRESULT hr = E_FAIL; #ifdef USEAUTH TRef pzac; if (g_fZoneAuth) { pzac = trekClient.GetZoneAuthClient(); if (!pzac) pzac = trekClient.CreateZoneAuthClient(); if (trekClient.GetCfgInfo().bUsePassport && !pzac->HasInterface(trekClient.GetCfgInfo().guidZoneAuth)) { // take them to the web page... GetWindow()->ShowWebPage(trekClient.GetCfgInfo().strPassportUpdateURL); // shut down the client GetWindow()->PostMessage(WM_CLOSE); return; } if (s_bWasAuthenticated) { hr = S_OK; } else { pzac->SetAuthServer(trekClient.GetCfgInfo().strZAuth); if (!m_bTriedCurrentLogin) hr = pzac->IsAuthenticated(5000); } } if (SUCCEEDED(hr)) // must be false if !g_fZoneAuth { BaseClient::ConnectInfo ci; DWORD cbZoneTicket; DWORD cbName = sizeof(ci.szName); ZSucceeded(pzac->GetTicket(&ci.pZoneTicket, &cbZoneTicket, ci.szName, &cbName)); assert(cbName <= sizeof(ci.szName)); ci.cbZoneTicket = cbZoneTicket; if(m_bConnectLobby) trekClient.ConnectToLobby(&ci); else trekClient.ConnectToClub(&ci); m_bTriedCurrentLogin = true; } else #endif { m_szName[0] = '\0'; m_szPWOrig[0] = '\0'; #ifdef USEAUTH if (g_fZoneAuth) pzac->GetDefaultLogonInfo(m_szName, m_szPWOrig, &m_fRememberPW); #else lstrcpy(m_szName, trekClient.GetSavedCharacterName()); #endif TRef plogonPopup = CreateLogonPopup(m_pmodeler, this, (trekClient.GetIsZoneClub() ? LogonAllegianceZone : #ifdef USEAUTH LogonFreeZone #else LogonLAN #endif ), strPrompt, m_szName, m_szPWOrig, m_fRememberPW); Point point(c_PopupX, c_PopupY); Rect rect(point, point); GetWindow()->GetPopupContainer()->OpenPopup(plogonPopup, rect, false); } } bool OnButtonMainMenu() { GetWindow()->screen(ScreenIDIntroScreen); return true; } bool OnButtonSquads() { if (trekClient.LoggedOnToClub()) { GetWindow()->screen(ScreenIDSquadsScreen); } else { ConnectToZone(false, ScreenIDSquadsScreen); } return true; } bool OnButtonGames() { // if (trekClient.LoggedOnToLobby()) // { // GetWindow()->screen(ScreenIDGameScreen); // } // else // { ConnectToZone(true, ScreenIDGameScreen); // } return true; } bool OnButtonZoneEvents() { GetWindow()->screen(ScreenIDZoneEvents); //ConnectToZone(true, ScreenIDZoneEvents); return true; } bool OnButtonPlayerProfile() { #ifdef NO_CLUB_SERVER_CONNECTION GetWindow()->screen(ScreenIDCharInfo); #else if (trekClient.LoggedOnToClub()) { GetWindow()->screen(ScreenIDCharInfo); } else { ConnectToZone(false, ScreenIDCharInfo); } #endif return true; } bool OnButtonZoneWeb() { // note: users can also access web page from the introscreen GetWindow()->ShowWebPage(); return true; } bool OnButtonLeaderBoard() { if (trekClient.LoggedOnToClub()) { GetWindow()->screen(ScreenIDLeaderBoard); } else { ConnectToZone(false, ScreenIDLeaderBoard); } return true; } void BeginConfigDownload() { if (!g_bDownloadNewConfig) { debugf("Skipping download of config file due to command-line switch.\n"); OnConfigDownloadDone(true, false); return; } lstrcpy(m_szConfig, "http://Allegiance.zone.com/Allegiance.cfg"); HKEY hKey; if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, ALLEGIANCE_REGISTRY_KEY_ROOT, 0, KEY_READ, &hKey)) { DWORD cbValue = MAX_PATH; char szConfig[MAX_PATH]; szConfig[0] = '\0'; ::RegQueryValueEx(hKey, "CfgFile", NULL, NULL, (LPBYTE)&szConfig, &cbValue); // if it didn't succeed, we'll just use the default above if (lstrlen(szConfig) > 0) lstrcpy(m_szConfig, szConfig); } if (ZString(m_szConfig).Find("http://") == -1) { debugf("Using local config file due to registry setting for ConfigFile because \"http://\" was missing from it. %s\n", m_szConfig); if (!IsFileValid(m_szConfig)) { #ifndef DEBUG // don't give warning twice for debug users m_pmsgBox = CreateMessageBox("Warning, Local CFG missing validation string"); GetWindow()->GetPopupContainer()->OpenPopup(m_pmsgBox, false); #endif } OnConfigDownloadDone(false, false); return; } if (m_pSession) return; debugf("Beginning Config Download: %s.\n", m_szConfig); m_pSession = CreateHTTPSession(this); const char * szFileList[] = { m_szConfig, "temp.cfg", NULL }; m_pSession->InitiateDownload(szFileList, "."); // . means EXE path return; } void BeginMessageOfDayDownload() { if (!g_bDownloadZoneMessage) { debugf("Skipping download of Message Of the Day due to command-line switch.\n"); OnMessageOfDayDone(false); return; } PCC szMessageOfTheDayFileName = trekClient.GetIsZoneClub() ? "clubmessageoftheday.mdl" : "publicmessageoftheday.mdl"; PathString path(trekClient.GetArtPath()); path = path + szMessageOfTheDayFileName; int crc = FileCRC(PCC(path), NULL); if (crc != 0 && crc == (trekClient.GetIsZoneClub() ? trekClient.GetCfgInfo().crcClubMessageFile : trekClient.GetCfgInfo().crcPublicMessageFile)) { debugf("Existing messageoftheday file has the correct CRC, skipping download.\n"); OnMessageOfDayDone(true); return; } else { debugf("Existing messageoftheday file has the wrong CRC (%X).\n", crc); } if (m_pSession) return; PCC szMessageOfTheDayURL = trekClient.GetIsZoneClub() ? PCC(trekClient.GetCfgInfo().strClubMessageURL) : PCC(trekClient.GetCfgInfo().strPublicMessageURL); debugf("Beginning messageoftheday download: %s.\n", szMessageOfTheDayURL); m_pSession = CreateHTTPSession(this); const char * szFileList[3] = { szMessageOfTheDayURL, szMessageOfTheDayFileName, NULL }; m_pSession->InitiateDownload(szFileList, trekClient.GetArtPath()); return; } void OnError(char * szErrorMessage) // on HTTP download error { // Errors are essentially ignored debugf("Error while downloading file.\n"); debugf("%s\n", szErrorMessage); m_bErrorOccured = true; } bool IsFileValid(char * szFileName) { ZFile file(szFileName); int n = file.GetLength(); // -1 means error if (n != -1 && n != 0) { char * pData = new char[n+1]; memcpy(pData, file.GetPointer(), n); pData[n] = 0; if (m_bMessageStage) { if (strstr(pData, szValidMotd) == NULL) { debugf("File %s is not a valid messageoftheday file.\n", szFileName); #ifdef DEBUG m_pmsgBox = CreateMessageBox("Warning, downloaded Motd file missing validation string"); GetWindow()->GetPopupContainer()->OpenPopup(m_pmsgBox, false); #endif delete[] pData; return false; } } else { if (strstr(pData, szValidCfg) == NULL) { debugf("File %s is not a valid config file.\n", szFileName); #ifdef DEBUG m_pmsgBox = CreateMessageBox("Warning, CFG file missing validation string"); GetWindow()->GetPopupContainer()->OpenPopup(m_pmsgBox, false); #endif delete[] pData; return false; } } delete[] pData; } else { debugf("File %s error while trying to load downloaded config file.\n", szFileName); return false; } return true; } bool OnFileCompleted(char * szFileName) { debugf("Downloaded file: %s\n", szFileName); char szPath[MAX_PATH+20]; strcpy(szPath, m_pSession->GetDownloadPath()); strcat(szPath, szFileName); if (!IsFileValid(szPath)) { m_bErrorOccured = true; debugf("Aborting either cfg or motd because file is invalid."); m_pmsgBox = CreateMessageBox("Unable to connect to Zone. Please try again later."); GetWindow()->GetPopupContainer()->OpenPopup(m_pmsgBox, false); } return true; // true means don't retry download } void OnFrame() { if (m_pSession) { if(m_bErrorOccured || !m_pSession->ContinueDownload()) { if (m_bMessageStage) OnMessageOfDayDone(!m_bErrorOccured); else OnConfigDownloadDone(true, !m_bErrorOccured); } } } void OnConfigDownloadDone(bool bUseEXEFolder, bool bDownloadSuccesful) { m_bMessageStage = true; if (m_pSession) { delete m_pSession; m_pSession = NULL; } if (bUseEXEFolder) { PathString pathEXE(PathString::GetCurrentDirectory()); PathString pathConfig(pathEXE + PathString(PathString(m_szConfig).GetFilename())); if (bDownloadSuccesful) { PathString pathTemp(pathEXE + "temp.cfg"); trekClient.GetCfgInfo().Load(PCC(pathTemp)); debugf("Loaded downloaded config file: %s\n", PCC(pathTemp)); // rename file, so that next time if there is an error, there is // a recent config file to use. debugf("Renaming %s to %s\n", PCC(pathTemp), PCC(pathConfig)); DeleteFile(PCC(pathConfig)); MoveFile(PCC(pathTemp), PCC(pathConfig)); } else { debugf("Error detected, loading existing config file: %s\n", PCC(pathConfig)); trekClient.GetCfgInfo().Load(PCC(pathConfig)); } } else { debugf("Using local config file %s\n", m_szConfig); trekClient.GetCfgInfo().Load(m_szConfig); } if (!m_bErrorOccured) { if(!g_bSkipAutoUpdate) { if (trekClient.GetCfgInfo().crcFileList != 0 && trekClient.GetCfgInfo().nFilelistSize != 0 && trekClient.GetCfgInfo().strFilelistSite != "" && trekClient.GetCfgInfo().strFilelistDirectory != "") { bool bForceFileCheck = trekClient.ShouldCheckFiles(); if (bForceFileCheck || trekClient.GetCfgInfo().crcFileList != FileCRC("Filelist.txt", NULL)) { if (trekClient.m_pAutoDownload == NULL) trekClient.m_pAutoDownload = CreateAutoDownload(); IAutoUpdateSink * pAutoUpdateSink = trekClient.OnBeginAutoUpdate(this, false); assert(pAutoUpdateSink); trekClient.m_pAutoDownload->SetFTPSite(PCC(trekClient.GetCfgInfo().strFilelistSite), PCC(trekClient.GetCfgInfo().strFilelistDirectory), "blah", // account "blah"); // pw trekClient.m_pAutoDownload->SetOfficialFileListAttributes(trekClient.GetCfgInfo().crcFileList, trekClient.GetCfgInfo().nFilelistSize); trekClient.m_pAutoDownload->SetArtPath(trekClient.GetArtPath()); // // Let's do it! // trekClient.m_pAutoDownload->BeginUpdate(pAutoUpdateSink, bForceFileCheck, false); // m_pAutoDownload could be NULL at this point, if the autodownload system decided // not to do a download after all. This can happen if there is an error or if // the client was already up-to-date. } else { // signal successful update/version already up-to-date OnAutoUpdateSystemTermination(false, false); } } else { debugf("Your cfg file is missing one or more of the following:\nFilelistCRC, FilelistSize, FilelistSite, FilelistDirectory\nSkipping AutoUpdate.\n"); // signal successful update/version already up-to-date OnAutoUpdateSystemTermination(false, false); // m_pmsgBox = CreateMessageBox("Unable to connect to Zone. CFG File is missing key components. Please try again later."); // GetWindow()->GetPopupContainer()->OpenPopup(m_pmsgBox, false); } } else { // signal successful update/version already up-to-date OnAutoUpdateSystemTermination(false, false); } BeginMessageOfDayDownload(); } else m_pbuttonMainMenu->SetEnabled(true); // allow users to leave screen even if cfg file failed to download } void OnMessageOfDayDone(bool bSuccessful) { if (m_pSession) { delete m_pSession; m_pSession = NULL; } m_pbuttonMainMenu->SetEnabled(true); // allow users to leave screen even if cfg file failed to download if (bSuccessful) { debugf("Loading messageoftheday file.\n"); m_pMDLFileImage->Load(trekClient.GetIsZoneClub() ? "clubmessageoftheday" : "publicmessageoftheday"); } else { debugf("Errors detected while downloading message of the day. Skipping load.\n"); } } //////////////////////////////////////////////////////////////////// // // Events associated with IAutoDownloadSink // //////////////////////////////////////////////////////////////////// virtual void OnAutoUpdateSystemTermination(bool bErrorOccurred, bool bRestarting) { m_pbuttonMainMenu->SetEnabled(true); // force download to finish before leaving this screen if (!bErrorOccurred && !bRestarting) { m_pbuttonGames->SetEnabled(true); m_pbuttonGamesBig->SetEnabled(true); if (trekClient.GetIsZoneClub()) { m_pbuttonPlayerProfile->SetEnabled(true); m_pbuttonLeaderboard->SetEnabled(true); m_pbuttonSquads->SetEnabled(!g_bDisableZoneClub); m_pbuttonZoneEvents->SetEnabled(!trekClient.GetCfgInfo().strZoneEventsURL.IsEmpty()); } } } //////////////////////////////////////////////////////////////////// // // Events associated with IIntegerEventSink // //////////////////////////////////////////////////////////////////// bool OnEvent(IIntegerEventSource* pevent, int value) { // // User must have pressed Okay button after error // assert(m_pmsgBox); GetWindow()->GetPopupContainer()->ClosePopup(m_pmsgBox); GetWindow()->RestoreCursor(); return false; } ////////////////////////////////////////////////////////////////////////////// // // LogonSite methods // ////////////////////////////////////////////////////////////////////////////// void OnLogon(const ZString& strName, const ZString& strPassword, BOOL fRememberPW) { lstrcpy(m_szName, strName); lstrcpy(m_szPW, strPassword); m_fRememberPW = fRememberPW; #ifdef USEAUTH #else trekClient.SaveCharacterName(strName); #endif GetWindow()->SetWaitCursor(); TRef pmsgBox = CreateMessageBox("Connecting...", NULL, false); Point point(c_PopupX, c_PopupY); Rect rect(point, point); GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, rect, false); // pause to let the "connecting..." box draw itself AddEventTarget(OnUsernameAndPassword, GetWindow(), 0.1f); } bool OnUsernameAndPassword() { HRESULT hr = E_FAIL; #ifdef USEAUTH TRef pzac; if (g_fZoneAuth) { pzac = trekClient.GetZoneAuthClient(); hr = pzac->Authenticate(m_szName, m_szPW, !!lstrcmp(m_szPW, m_szPWOrig), m_fRememberPW, 5000); } if (g_fZoneAuth && FAILED(hr)) { bool bRetry; ZString strReason; if (ZT_E_AUTH_DENIED == hr) { if (trekClient.GetCfgInfo().bUsePassport) strReason = "Either the username or the password you supplied was incorrect. Be sure to sign in with your Microsoft Passport name (not your Zone ID)."; else strReason = "Either the username or the password you supplied was incorrect. Please try again."; bRetry = true; } else { strReason = "Unable to contact the authentication server. Please check your network connection."; bRetry = false; } // if the logon fails, close the connecting dialog box. GetWindow()->GetPopupContainer()->ClosePopup(m_pmsgBox); GetWindow()->RestoreCursor(); if (m_bConnectLobby) OnLogonLobbyFailed(bRetry, strReason); else OnLogonClubFailed(bRetry, strReason); } else #endif { s_bWasAuthenticated = true; BaseClient::ConnectInfo ci; DWORD cbZoneTicket = 0; ci.pZoneTicket = NULL; DWORD cbName = sizeof(ci.szName); #ifdef USEAUTH if (g_fZoneAuth) { ZSucceeded(pzac->GetTicket(&ci.pZoneTicket, &cbZoneTicket, ci.szName, &cbName)); assert(cbName <= sizeof(ci.szName)); ci.cbZoneTicket = cbZoneTicket; } else #endif lstrcpy(ci.szName, m_szName); ZeroMemory(&ci.ftLastArtUpdate, sizeof(ci.ftLastArtUpdate)); if (m_bConnectLobby) trekClient.ConnectToLobby(&ci); else trekClient.ConnectToClub(&ci); } return false; } void OnAbort() { } void OnLogonLobby() { GetWindow()->screen(m_screenPostConnect); } void OnLogonLobbyFailed(bool bRetry, const char* szReason) { if (bRetry) { s_bWasAuthenticated = false; ConnectToZone(true, m_screenPostConnect, szReason); } else { TRef pmsgBox = CreateMessageBox(szReason); GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false); } } void OnLogonClub() { GetWindow()->screen(m_screenPostConnect); } void OnLogonClubFailed(bool bRetry, const char* szReason) { if (bRetry) { s_bWasAuthenticated = false; ConnectToZone(false, m_screenPostConnect, szReason); } else { TRef pmsgBox = CreateMessageBox(szReason); GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false); } } ////////////////////////////////////////////////////////////////////////////// // // Screen Methods // ////////////////////////////////////////////////////////////////////////////// Pane* GetPane() { return m_ppane; } }; bool ZoneClubScreen::s_bWasAuthenticated = false; ////////////////////////////////////////////////////////////////////////////// // // Constructor // ////////////////////////////////////////////////////////////////////////////// TRef CreateZoneClubScreen(Modeler* pmodeler, Number * ptime) { return new ZoneClubScreen(pmodeler, ptime); }