/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ #include "HeadSpin.h" #include "plPlasmaUpdate.h" #include "resource.h" #include #include #include #include "jvCoreUtil.h" #include "jvDialogResizer.h" #include "hsTypes.h" #include "../plFile/plFileUtils.h" #include "../plUnifiedTime/plUnifiedTime.h" #include "hsStream.h" #include "plManifest.h" #include "hsUtils.h" #include "../plStatusLog/plStatusLog.h" static plPlasmaUpdate* gInst = nil; #define WM_UPDATE_SERVER WM_APP+1 std::string plPlasmaUpdate::fUserName = "dataserver"; std::string plPlasmaUpdate::fPassword = "parabledata"; plPlasmaUpdate::plPlasmaUpdate() : fCanExit(true), fProgressType(kValidating), fResizer(nil), fAutoDownload(false) { INITCOMMONCONTROLSEX icc = {0}; icc.dwSize = sizeof(INITCOMMONCONTROLSEX); icc.dwICC = ICC_PROGRESS_CLASS; InitCommonControlsEx(&icc); gInst = this; _getcwd(fIniPath, sizeof(fIniPath)); char lastChar = fIniPath[strlen(fIniPath)]; if (lastChar != '\\' && lastChar != '/') strcat(fIniPath, "\\"); strcat(fIniPath, "ParableUpdate.ini"); fFileGrabber = new plNetShareFileGrabber; } plPlasmaUpdate::~plPlasmaUpdate() { delete fResizer; if (fFileGrabber) delete fFileGrabber; } bool plPlasmaUpdate::Create() { if (!fServers.GetServerInfo()) return false; ICreateDialog(IDD_UPDATE, NULL); return true; } BOOL CALLBACK plPlasmaUpdate::ILoginWinProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch( msg ) { case WM_INITDIALOG: SetFocus(GetDlgItem(hDlg, IDC_USERNAME)); break; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED && (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)) { bool ok = (LOWORD(wParam) == IDOK); if (ok) { char username[25]; char password[25]; GetDlgItemText(hDlg, IDC_USERNAME, username, 25); GetDlgItemText(hDlg, IDC_PASSWORD, password, 25); fUserName = username; hsAssert(false, "who uses this program?"); // plChallengeResponse::HashPassword(password, fPassword); } EndDialog(hDlg, ok); return TRUE; } break; } return FALSE; } void plPlasmaUpdate::IInit() { char curServerAddress[256]; GetPrivateProfileString("PlasmaUpdate", "ServerAddress", "", curServerAddress, sizeof(curServerAddress), fIniPath); bool external = (GetPrivateProfileInt("PlasmaUpdate", "External", 0, fIniPath) != 0); HWND hCombo = GetDlgItem(fDlg, IDC_BUILD_COMBO); for (int i = 0; i < fServers.GetNumServers(); i++) { std::string& serverAddress = fServers.GetServerAddress(i); std::string& serverName = fServers.GetServerName(i); std::string& currentDir = fServers.GetServerCurrentDir(i); if (!fFileGrabber->IsServerAvailable(serverAddress.c_str(), currentDir.c_str())) continue; bool thisServer = (serverAddress == curServerAddress); int idx = ComboBox_AddString(hCombo, serverName.c_str()); ComboBox_SetItemData(hCombo, idx, MAKELPARAM(i, 0)); if (thisServer && !external) ComboBox_SetCurSel(hCombo, idx); std::string extName = serverName + " (External)"; idx = ComboBox_AddString(hCombo, extName.c_str()); ComboBox_SetItemData(hCombo, idx, MAKELPARAM(i, 1)); if (thisServer && external) ComboBox_SetCurSel(hCombo, idx); } if (ComboBox_GetCurSel(hCombo) == -1) ComboBox_SetCurSel(hCombo, 0); SendMessage(fDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(jvCoreUtil::GetHInstance(), MAKEINTRESOURCE(IDI_ICON))); SendMessage(fDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(jvCoreUtil::GetHInstance(), MAKEINTRESOURCE(IDI_ICON))); fResizer = new jvDialogResizer(fDlg); fResizer->AddControl(IDC_BUILD_COMBO, jvDialogResizer::kResizeX); fResizer->AddControl(IDC_STATUS_LIST, jvDialogResizer::kResizeX | jvDialogResizer::kResizeY); fResizer->AddControl(IDC_PROGRESS, jvDialogResizer::kLockBottom | jvDialogResizer::kResizeX); fResizer->AddControl(IDC_DL_TEXT, jvDialogResizer::kLockBottom | jvDialogResizer::kResizeX); fResizer->AddControl(IDC_DL_BUTTON, jvDialogResizer::kLockBottom | jvDialogResizer::kCenterX); fResizer->SetSize(360, 320); fResizer->LoadPosAndSize("PlasmaUpdate"); bool goTime = true; if (fFileGrabber->NeedsAuth()) { /* if (!DialogBox(NULL, MAKEINTRESOURCE(IDD_PLASMAUPDATE_LOGIN), fDlg, ILoginWinProc)) goTime = false; else */ fFileGrabber->SetUsernamePassword(fUserName, fPassword); } if (goTime) { ShowWindow(fDlg, SW_SHOW); PostMessage(fDlg, WM_UPDATE_SERVER, 0, 0); } else PostQuitMessage(0); } void plPlasmaUpdate::IShutdown() { fResizer->SavePosAndSize("PlasmaUpdate"); delete fResizer; fResizer = NULL; IDeleteManifests(); } void plPlasmaUpdate::IEnableCtrls(bool enable) { fCanExit = enable; EnableWindow(GetDlgItem(fDlg, IDC_BUILD_COMBO), enable); HWND hDlButton = GetDlgItem(fDlg, IDC_DL_BUTTON); if (fManifests.empty()) SetWindowText(hDlButton, "Close"); else SetWindowText(hDlButton, "Download"); EnableWindow(hDlButton, enable); if (enable) SetFocus(hDlButton); } void plPlasmaUpdate::IDeleteManifests() { for (int i = 0; i < fManifests.size(); i++) delete fManifests[i]; fManifests.clear(); } bool plPlasmaUpdate::IGetManifests(const char* serverRoot, bool external) { IDeleteManifests(); char filePath[MAX_PATH]; sprintf(filePath, "%sCurrent.txt", serverRoot); enum Sections { kVersion, kInternal, kExternal, kAll }; int curSection = kVersion; hsRAMStream s; hsRAMStream manifestStream; if (fFileGrabber->FileToStream(filePath, &s)) { char buf[256]; while (s.ReadLn(buf, sizeof(buf))) { if (buf[0] == '[') { if (hsStrEQ(buf, "[Version]")) curSection = kVersion; else if (hsStrEQ(buf, "[Internal]")) curSection = kInternal; else if (hsStrEQ(buf, "[External]")) curSection = kExternal; else if (hsStrEQ(buf, "[All]")) curSection = kAll; } else { if (curSection == kVersion) { int version = atoi(buf); if (version != 1) { hsMessageBox("Your copy of PlasmaUpdate is out of date.\nPlease get the latest version.", "Error", hsMessageBoxNormal, hsMessageBoxIconError); return false; } } else if ((!external && curSection == kInternal) || (external && curSection == kExternal) || curSection == kAll) { //if (curSection == kAll && !(!strcmp(buf, "Data\\Movies.mfs") || !strcmp(buf, "Data\\Sounds.mfs"))) // continue; sprintf(filePath, "%s%s", serverRoot, buf); fFileGrabber->MakeProperPath(filePath); manifestStream.Reset(); fFileGrabber->FileToStream(filePath, &manifestStream); plFileUtils::StripFile(filePath); plManifest* manifest = new plManifest(ILog); manifest->Read(&manifestStream, filePath, buf); fManifests.push_back(manifest); } } } return true; } return false; } void plPlasmaUpdate::IUpdateServer() { char buf[256]; IEnableCtrls(false); SetDlgItemText(fDlg, IDC_DL_TEXT, "Checking for updates..."); // // Figure out what server we're checking // bool external = false; char serverRoot[MAX_PATH]; { HWND hCombo = GetDlgItem(fDlg, IDC_BUILD_COMBO); int idx = ComboBox_GetCurSel(hCombo); LPARAM data = ComboBox_GetItemData(hCombo, idx); int server = LOWORD(data); external = (HIWORD(data) != 0); sprintf(serverRoot, "/%s/", fServers.GetServerCurrentDir(server).c_str()); const char* serverName = fServers.GetServerAddress(server).c_str(); ILog("===== Server set to %s %s =====", serverName, external ? "external" : "internal"); WritePrivateProfileString("PlasmaUpdate", "ServerAddress", serverName, fIniPath); WritePrivateProfileString("PlasmaUpdate", "External", external ? "1" : "0", fIniPath); fFileGrabber->SetServer(serverName); } // // Get the latest publish notes // { HWND hList = GetDlgItem(fDlg, IDC_STATUS_LIST); ListBox_ResetContent(hList); char updateFile[MAX_PATH]; if (external) sprintf(updateFile, "%sUpdates-External.txt", serverRoot); else sprintf(updateFile, "%sUpdates-Internal.txt", serverRoot); hsRAMStream updates; fFileGrabber->MakeProperPath(updateFile); if (fFileGrabber->FileToStream(updateFile, &updates)) { while (updates.ReadLn(buf, sizeof(buf))) ListBox_InsertString(hList, 0, buf); } } // // Get the manifests // bool gotManifests = IGetManifests(serverRoot, external); UInt32 dlSize = 0; fProgressType = kValidating; if (gotManifests) { int i; UInt32 numFiles = 0; for (i = 0; i < fManifests.size(); i++) numFiles += fManifests[i]->NumFiles(); HWND hProgress = GetDlgItem(fDlg, IDC_PROGRESS); SendMessage(hProgress, PBM_SETRANGE32, 0, numFiles); for (i = 0; i < fManifests.size(); i++) { fManifests[i]->ValidateFiles(ProgressFunc); dlSize += fManifests[i]->DownloadSize(); } SendMessage(hProgress, PBM_SETPOS, 0, 0); } // Print how many megs there are to download if (dlSize == 0) { strcpy(buf, "No updates to download"); IDeleteManifests(); } else { float dlMegs = float(dlSize) / (1024.f*1024.f); if (dlMegs < .1) dlMegs = .1; sprintf(buf, "%.1f MB of updates to download", dlMegs); } SetDlgItemText(fDlg, IDC_DL_TEXT, buf); IEnableCtrls(true); if (fAutoDownload) PostMessage(fDlg, WM_COMMAND, MAKEWPARAM(IDC_DL_BUTTON, BN_CLICKED), LPARAM(GetDlgItem(fDlg, IDC_DL_BUTTON))); } void plPlasmaUpdate::IDownloadUpdates() { fProgressType = kDownloading; IEnableCtrls(false); int i; UInt32 dlSize = 0; for (i = 0; i < fManifests.size(); i++) dlSize += fManifests[i]->DownloadSize(); HWND hProgress = GetDlgItem(fDlg, IDC_PROGRESS); SendMessage(hProgress, PBM_SETRANGE32, 0, dlSize); for (i = 0; i < fManifests.size(); i++) fManifests[i]->DownloadUpdates(ProgressFunc, fFileGrabber); SendMessage(hProgress, PBM_SETPOS, 0, 0); EnableWindow(GetDlgItem(fDlg, IDC_DL_BUTTON), false); SetDlgItemText(fDlg, IDC_DL_TEXT, "No updates to download"); IDeleteManifests(); IEnableCtrls(true); if (fAutoDownload) PostMessage(fDlg, WM_COMMAND, MAKEWPARAM(IDC_DL_BUTTON, BN_CLICKED), LPARAM(GetDlgItem(fDlg, IDC_DL_BUTTON))); } void plPlasmaUpdate::ProgressFunc(const char* name, int delta) { static const char* lastName = nil; if (lastName != name) { lastName = name; char buf[256]; if (gInst->fProgressType == kValidating) strcpy(buf, "Checking "); else strcpy(buf, "Downloading "); strcat(buf, name); SetDlgItemText(gInst->fDlg, IDC_DL_TEXT, buf); } SendDlgItemMessage(gInst->fDlg, IDC_PROGRESS, PBM_DELTAPOS, delta, 0); jvBaseDlg::PumpQueue(); } void plPlasmaUpdate::ILog(const char* format, ...) { static plStatusLog* log = nil; if (!log) log = plStatusLogMgr::GetInstance().CreateStatusLog(0, "PlasmaUpdate.log"); va_list args; va_start(args, format); log->AddLineV(format, args); va_end(args); } BOOL plPlasmaUpdate::IDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: IInit(); SetFocus(GetDlgItem(fDlg, IDC_DL_BUTTON)); return FALSE; case WM_CLOSE: if (fCanExit) DestroyWindow(hDlg); return TRUE; case WM_DESTROY: IShutdown(); PostQuitMessage(0); return TRUE; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_DL_BUTTON) { if (fManifests.empty()) SendMessage(fDlg, WM_CLOSE, 0, 0); else IDownloadUpdates(); return TRUE; } else if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_BUILD_COMBO) { IUpdateServer(); return TRUE; } break; case WM_UPDATE_SERVER: IUpdateServer(); return TRUE; } return FALSE; }