From 09f369cd33cae1401275b29e161990212e668b94 Mon Sep 17 00:00:00 2001 From: Aldo Fregoso Date: Mon, 21 May 2012 02:29:59 -0500 Subject: [PATCH] Imported the check for updates code from StepMania AMX. --- TODO: Move the code from NSMAN to a new class TODO: HOOKS->GetURL for Linux TODO: Do not run the check every time the game is launched, use: PREFSMAN->m_iUpdateCheckIntervalSeconds - Seconds to wait before running the next check PREFSMAN->m_iUpdateCheckLastCheckedSecond - Timestamp of the last check --- src/NetworkSyncManager.cpp | 135 ++++++++++++++++++++++++++++++++- src/NetworkSyncManager.h | 5 ++ src/PrefsManager.cpp | 17 +++++ src/PrefsManager.h | 11 +++ src/ProductInfo.h | 1 + src/StepMania.cpp | 37 +++++++++ src/update_check/check_sm5.php | 12 +++ 7 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 src/update_check/check_sm5.php diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 2c063eb83e..611dfd2e01 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -6,6 +6,11 @@ NetworkSyncManager *NSMAN; +// Aldo: used by GetCurrentSMVersion() +#if defined(HAVE_VERSION_INFO) +extern unsigned long version_num; +#endif + #if defined(WITHOUT_NETWORKING) NetworkSyncManager::NetworkSyncManager( LoadingWindow *ld ) { useSMserver=false; isSMOnline = false; } NetworkSyncManager::~NetworkSyncManager () { } @@ -25,7 +30,12 @@ void NetworkSyncManager::SendChat( const RString& message ) { } void NetworkSyncManager::SelectUserSong() { } RString NetworkSyncManager::MD5Hex( const RString &sInput ) { return RString(); } int NetworkSyncManager::GetSMOnlineSalt() { return 0; } -void NetworkSyncManager::GetListOfLANServers( vector& AllServers ) { } +void NetworkSyncManager::GetListOfLANServers( vector& AllServers ) { } + #if defined(HAVE_VERSION_INFO) + unsigned long NetworkSyncManager::GetCurrentSMBuild( LoadingWindow* ld ) { return version_num; } + #else + unsigned long NetworkSyncManager::GetCurrentSMBuild( LoadingWindow* ld ) { return 0; } + #endif #else #include "ezsockets.h" #include "ProfileManager.h" @@ -835,6 +845,129 @@ void NetworkSyncManager::GetListOfLANServers( vector& AllServers AllServers = m_vAllLANServers; } +// Aldo: Please move this method to a new class, I didn't want to create new files because I don't know how to properly update the files for each platform. +// I preferred to misplace code rather than cause unneeded headaches to non-windows users, although it would be nice to have in the wiki which files to +// update when adding new files and how (Xcode/stepmania_xcode4.3.xcodeproj has a really crazy structure :/). +#if !defined(HAVE_VERSION_INFO) +unsigned long NetworkSyncManager::GetCurrentSMBuild( LoadingWindow* ld ) { return 0; } +#else +unsigned long NetworkSyncManager::GetCurrentSMBuild( LoadingWindow* ld ) +{ + // Aldo: Using my own host by now, upload update_check/check_sm5.php to an official URL and change the following constants accordingly: + const RString sHost = "aldo.mx"; + const unsigned short uPort = 80; + const RString sResource = "/stepmania/check_sm5.php"; + const RString sUserAgent = "StepMania AMX (+http://aldo.mx/stepmania/)"; + const RString sReferer = "http://aldo.mx/stepmania/"; + + if( ld ) + { + ld->SetIndeterminate( true ); + ld->SetText("Checking for updates..."); + } + + unsigned long uCurrentSMBuild = version_num; + bool bSuccess = false; + EzSockets* socket = new EzSockets(); + socket->create(); + socket->blocking = true; + + if( socket->connect(sHost, uPort) ) + { + RString sHTTPRequest = ssprintf( + "GET %s HTTP/1.1" "\r\n" + "Host: %s" "\r\n" + "User-Agent: %s" "\r\n" + "Cache-Control: no-cache" "\r\n" + "Referer: %s" "\r\n" + "X-SM-Build: %lu" "\r\n" + "\r\n", + sResource.c_str(), sHost.c_str(), + sUserAgent.c_str(), sReferer.c_str(), + version_num + ); + + socket->SendData(sHTTPRequest); + + // Aldo: EzSocket::pReadData() is a lower level function, I used it because I was having issues + // with EzSocket::ReadData() in 3.9, feel free to refactor this function, the low lever character + // manipulation might look scary to people not used to it. + char* cBuffer = new char[NETMAXBUFFERSIZE]; + // Reading the first NETMAXBUFFERSIZE bytes (usually 1024), should be enough to get the HTTP Header only + int iBytes = socket->pReadData(cBuffer); + if( iBytes ) + { + // \r\n\r\n = Separator from HTTP Header and Body + char* cBodyStart = strstr(cBuffer, "\r\n\r\n"); + if( cBodyStart != NULL ) + { + // Get the HTTP Header only + int iHeaderLength = cBodyStart - cBuffer; + char* cHeader = new char[iHeaderLength+1]; + strncpy( cHeader, cBuffer, iHeaderLength ); + cHeader[iHeaderLength] = '\0'; // needed to make it a valid C String + + RString sHTTPHeader( cHeader ); + SAFE_DELETE( cHeader ); + Trim( sHTTPHeader ); + //LOG->Trace( sHTTPHeader.c_str() ); + + vector svResponse; + split( sHTTPHeader, "\r\n", svResponse ); + + // Check for 200 OK + if( svResponse[0].find("200") != RString::npos ) + { + // Iterate through every field until an X-SM-Build field is found + for( unsigned h=1; hconnect(sHost, uPort) ) + + socket->close(); + SAFE_DELETE( socket ); + + if( ld ) + { + ld->SetIndeterminate(false); + ld->SetTotalWork(100); + + if( bSuccess ) + { + ld->SetProgress(100); + ld->SetText("Checking for updates... OK"); + } + else + { + ld->SetProgress(0); + ld->SetText("Checking for updates... ERROR"); + } + } + + return uCurrentSMBuild; +} +#endif + static bool ConnectToServer( const RString &t ) { NSMAN->PostStartUp( t ); diff --git a/src/NetworkSyncManager.h b/src/NetworkSyncManager.h index 3253ffa545..206ac3f408 100644 --- a/src/NetworkSyncManager.h +++ b/src/NetworkSyncManager.h @@ -176,6 +176,11 @@ public: RString MD5Hex( const RString &sInput ); void GetListOfLANServers( vector& AllServers ); + + // Aldo: Please move this method to a new class, I didn't want to create new files because I don't know how to properly update the files for each platform. + // I preferred to misplace code rather than cause unneeded headaches to non-windows users, although it would be nice to have in the wiki which files to + // update when adding new files. + static unsigned long GetCurrentSMBuild( LoadingWindow* ld ); private: #if !defined(WITHOUT_NETWORKING) diff --git a/src/PrefsManager.cpp b/src/PrefsManager.cpp index afdfb5c1aa..1a723fbf84 100644 --- a/src/PrefsManager.cpp +++ b/src/PrefsManager.cpp @@ -143,6 +143,10 @@ bool g_bAutoRestart = false; # define TRUE_IF_DEBUG false #endif +#if !defined(WITHOUT_NETWORKING) && defined(HAVE_VERSION_INFO) +extern unsigned long version_num; +#endif + void ValidateDisplayAspectRatio( float &val ) { if( val < 0 ) @@ -289,6 +293,19 @@ PrefsManager::PrefsManager() : #if !defined(WITHOUT_NETWORKING) , m_bEnableScoreboard ( "EnableScoreboard", true ) + + #if defined(HAVE_VERSION_INFO) + , + m_bUpdateCheckEnable ( "UpdateCheckEnable", true ) + // TODO - Aldo_MX: Use PREFSMAN->m_iUpdateCheckIntervalSeconds & PREFSMAN->m_iUpdateCheckLastCheckedSecond + //, + //m_iUpdateCheckIntervalSeconds ( "UpdateCheckIntervalSeconds", 86400 ), // 24 hours + //m_iUpdateCheckLastCheckedSecond ( "UpdateCheckLastCheckSecond", 0 ) + + // TODO - Aldo_MX: Write helpers in LuaManager.cpp to treat unsigned int/long like LUA Numbers + //, + //m_uUpdateCheckLastCheckedBuild ( "UpdateCheckLastCheckedBuild", version_num ) + #endif #endif { diff --git a/src/PrefsManager.h b/src/PrefsManager.h index fae7808e8a..6efcf29af7 100644 --- a/src/PrefsManager.h +++ b/src/PrefsManager.h @@ -300,6 +300,17 @@ public: #if !defined(WITHOUT_NETWORKING) Preference m_bEnableScoreboard; //Alows disabling of scoreboard in network play + + #if defined(HAVE_VERSION_INFO) + // Check for Updates code + Preference m_bUpdateCheckEnable; + // TODO - Aldo_MX: Use PREFSMAN->m_iUpdateCheckIntervalSeconds & PREFSMAN->m_iUpdateCheckLastCheckedSecond + //Preference m_iUpdateCheckIntervalSeconds; + //Preference m_iUpdateCheckLastCheckedSecond; + + // TODO - Aldo_MX: Write helpers in LuaManager.cpp to treat unsigned int/long like LUA Numbers + //Preference m_uUpdateCheckLastCheckedBuild; + #endif #endif void ReadPrefsFromIni( const IniFile &ini, const RString &sSection, bool bIsStatic ); diff --git a/src/ProductInfo.h b/src/ProductInfo.h index c305722c88..af5c53daa9 100644 --- a/src/ProductInfo.h +++ b/src/ProductInfo.h @@ -52,6 +52,7 @@ #define VIDEO_TROUBLESHOOTING_URL "http://www.stepmania.com/stepmaniawiki.php?title=Video_Driver_Troubleshooting" /** @brief The URL to report bugs on the program. */ #define REPORT_BUG_URL "http://ssc.ajworld.net/sm-ssc/bugtracker/" +#define SM_DOWNLOAD_URL "http://code.google.com/p/sm-ssc/downloads/list" #define CAN_INSTALL_PACKAGES true diff --git a/src/StepMania.cpp b/src/StepMania.cpp index a54534da07..ffb46c476b 100644 --- a/src/StepMania.cpp +++ b/src/StepMania.cpp @@ -1027,6 +1027,43 @@ int main(int argc, char* argv[]) LOG->Info( "TLS is %savailable", RageThread::GetSupportsTLS()? "":"not " ); #endif + // Aldo: Check for updates here! + if( PREFSMAN->m_bUpdateCheckEnable ) + { + // TODO - Aldo_MX: Use PREFSMAN->m_iUpdateCheckIntervalSeconds & PREFSMAN->m_iUpdateCheckLastCheckedSecond + unsigned long current_version = NetworkSyncManager::GetCurrentSMBuild( pLoadingWindow ); + if( current_version ) + { + if( current_version > version_num ) + { + switch( Dialog::YesNo( "A new version of " PRODUCT_ID " is available. Do you want to download it?", "UpdateCheck" ) ) + { + case Dialog::yes: + //PREFSMAN->SavePrefsToDisk(); + // TODO: GoToURL for Linux + if( !HOOKS->GoToURL( SM_DOWNLOAD_URL ) ) + { + Dialog::Error( "Please go to the following URL to download the latest version of " PRODUCT_ID ":\n\n" SM_DOWNLOAD_URL, "UpdateCheckConfirm" ); + } + ShutdownGame(); + return 0; + case Dialog::no: + break; + default: + ASSERT(0); + } + } + else if( version_num < current_version ) + { + LOG->Info( "The current version is more recent than the public one, double check you downloaded it from " SM_DOWNLOAD_URL ); + } + } + else + { + LOG->Info( "Unable to check for updates. The server might be offline." ); + } + } + AdjustForChangedSystemCapabilities(); GAMEMAN = new GameManager; diff --git a/src/update_check/check_sm5.php b/src/update_check/check_sm5.php new file mode 100644 index 0000000000..cc077a0b1a --- /dev/null +++ b/src/update_check/check_sm5.php @@ -0,0 +1,12 @@ +