Exemplo n.º 1
0
bool C4PortraitSelDlg::SelectPortrait(C4GUI::Screen *pOnScreen,
                                      StdStrBuf *pSelection, bool *pfSetPicture,
                                      bool *pfSetBigIcon) {
  // copy some default potraits to UserPath (but only try this once, no real
  // error handling)
  if (!Config.General.UserPortraitsWritten) {
    Log("Copying default portraits to user path...");
    C4Group hGroup;
    if (hGroup.Open(Config.AtExePath(C4CFN_Graphics))) {
      hGroup.Extract("Portrait1.png", Config.AtUserPath("Clonk.png"));
      hGroup.Extract("PortraitBandit.png", Config.AtUserPath("Bandit.png"));
      hGroup.Extract("PortraitIndianChief.png",
                     Config.AtUserPath("IndianChief.png"));
      hGroup.Extract("PortraitKing.png", Config.AtUserPath("King.png"));
      hGroup.Extract("PortraitKnight.png", Config.AtUserPath("Knight.png"));
      hGroup.Extract("PortraitMage.png", Config.AtUserPath("Mage.png"));
      hGroup.Extract("PortraitPiranha.png", Config.AtUserPath("Piranha.png"));
      hGroup.Extract("PortraitSheriff.png", Config.AtUserPath("Sheriff.png"));
      hGroup.Extract("PortraitWipf.png", Config.AtUserPath("Wipf.png"));
      hGroup.Close();
    }
    Config.General.UserPortraitsWritten = true;
  }
  // let the user select a portrait by showing a modal selection dialog
  C4PortraitSelDlg *pDlg =
      new C4PortraitSelDlg(NULL, *pfSetPicture, *pfSetBigIcon);
  bool fResult;
  if (fResult = pOnScreen->ShowModalDlg(pDlg, false)) {
    pSelection->Take(pDlg->GetSelection(NULL, false));
    *pfSetPicture = pDlg->IsSetPicture();
    *pfSetBigIcon = pDlg->IsSetBigIcon();
  }
  if (C4GUI::IsGUIValid()) delete pDlg;
  return fResult;
}
Exemplo n.º 2
0
bool C4UpdateDlg::ApplyUpdate(const char *strUpdateFile, bool fDeleteUpdate, C4GUI::Screen *pScreen)
{
	// Apply update: If the update file is a .ocu, it will extract c4group and apply the update.
	// If the update file is an installer, it will just launch that installer.
	StdStrBuf strUpdateProgEx, strUpdateArgs;
	bool fIsGroupUpdate = SEqualNoCase(GetExtension(strUpdateFile), C4CFN_UpdateGroupExtension+1);
	// Is this an update executable or an update group?
	if (fIsGroupUpdate)
	{
		// This is an update group (.ocu). Extract c4group and run it.
		// Find a place to extract the update
		Config.MakeTempUpdateFolder();
		// Determine name of update program
		StdStrBuf strUpdateProg;
		strUpdateProg.Copy(C4CFN_UpdateProgram);
		// Windows: manually append extension because ExtractEntry() cannot properly glob and Extract() doesn't return failure values
#ifdef _WIN32
		strUpdateProg += ".exe";
#endif
		// Determine name of local extract of update program
		strUpdateProgEx.Copy(Config.AtTempUpdatePath(strUpdateProg.getData()));

		// Extract update program (the update should be applied using the new version)
		C4Group UpdateGroup;
		if (!UpdateGroup.Open(strUpdateFile))
		{
			LogF("Error opening \"%s\": %s", strUpdateFile, UpdateGroup.GetError());
			return false;
		}
		// Look for update program at top level
		if (!UpdateGroup.ExtractEntry(strUpdateProg.getData(), strUpdateProgEx.getData()))
		{
			LogF("Error extracting \"%s\": %s", strUpdateProg.getData(), UpdateGroup.GetError());
			return false;
		}
		// Extract any needed library files
		UpdateGroup.Extract(C4CFN_UpdateProgramLibs, Config.AtTempUpdatePath(""), C4CFN_UpdateProgram);
		UpdateGroup.Close();
#ifdef _WIN32
		// Notice: even if the update program and update group are in the temp path, they must be executed in our working directory
		DWORD ProcessID = GetCurrentProcessId();
		//strUpdateArgs.Format("\"%s\" \"%s\" %s %lu", strUpdateProgEx.getData(), strUpdateFile, fDeleteUpdate ? "-yd" : "-y", (unsigned long)ProcessID);
		strUpdateArgs.Format("\"%s\" %s %lu", strUpdateFile, fDeleteUpdate ? "-yd" : "-y", (unsigned long)ProcessID);

#if 0 // debug code to reroute updating via batch file
		CStdFile f; - reroute via vi
		f.Create(Config.AtTempUpdatePath("update.bat"));
		f.WriteString(FormatString("%s %s\npause\n", strUpdateProgEx.getData(), strUpdateArgs.getData()).getData());
		f.Close();
		strUpdateProgEx.Copy(Config.AtTempUpdatePath("update.bat"));
		strUpdateArgs.Copy(strUpdateProgEx);
#endif
#endif
	}
	else
	{
		// This "update" is actually an installer. Just run it.
		strUpdateProgEx = strUpdateFile;
		strUpdateArgs = "";
		// if group was downloaded to temp path, delete it from there
		if (fDeleteUpdate) SCopy(strUpdateProgEx.getData(), Config.General.TempUpdatePath, CFG_MaxString);
	}

	// Execute update program
	Log(LoadResStr("IDS_PRC_LAUNCHINGUPDATE"));
	succeeded = true;

#ifdef _WIN32
	// Notice: even if the update program and update group are in the temp path, they must be executed in our working directory
	// the magic verb "runas" opens the update program in a shell requesting elevation
	int iError = (intptr_t)ShellExecute(NULL, L"runas", strUpdateProgEx.GetWideChar(), strUpdateArgs.GetWideChar(), Config.General.ExePath.GetWideChar(), SW_SHOW);
	if (iError <= 32) return false;

	// must quit ourselves for update program to work
	if (succeeded) Application.Quit();
#else
	if (pipe(c4group_output) == -1)
	{
		Log("Error creating pipe");
		return false;
	}
	switch (pid = fork())
	{
		// Error
	case -1:
		Log("Error creating update child process.");
		return false;
		// Child process
	case 0:
		// Close unused read end
		close(c4group_output[0]);
		// redirect stdout and stderr to the parent
		dup2(c4group_output[1], STDOUT_FILENO);
		dup2(c4group_output[1], STDERR_FILENO);
		if (c4group_output[1] != STDOUT_FILENO && c4group_output[1] != STDERR_FILENO)
			close(c4group_output[1]);
		if (fIsGroupUpdate)
			execl(C4CFN_UpdateProgram, C4CFN_UpdateProgram, "-v", strUpdateFile, (fDeleteUpdate ? "-yd" : "-y"), static_cast<char *>(0));
		else
			execl(strUpdateFile, strUpdateFile, static_cast<char *>(0));
		printf("execl failed: %s\n", strerror(errno));
		exit(1);
		// Parent process
	default:
		// Close unused write end
		close(c4group_output[1]);
		// disable blocking
		fcntl(c4group_output[0], F_SETFL, O_NONBLOCK);
		// Open the update log dialog (this will update itself automatically from c4group_output)
		pScreen->ShowRemoveDlg(new C4UpdateDlg());
		break;
	}
#endif
	// done
	return succeeded;
}
Exemplo n.º 3
0
bool C4Group_ApplyUpdate(C4Group &hGroup) {
    // Process object update group (GRPUP_Entries.txt found)
    C4UpdatePackage Upd;
    if (hGroup.FindEntry(C4CFN_UpdateEntries))
        if (Upd.Load(&hGroup)) {
            // Do update check first (ensure packet has everything it needs in order
            // to perfom the update)
            int iRes = Upd.Check(&hGroup);
            switch (iRes) {
            // Bad version - checks against version of the applying executable
            // (major version must match, minor version must be equal or higher)
            case C4UPD_CHK_BAD_VERSION:
                fprintf(stderr,
                        "This update %s can only be applied using version "
                        "%d.%d.%d.%d or higher.\n",
                        Upd.Name, Upd.RequireVersion[0], Upd.RequireVersion[1],
                        Upd.RequireVersion[2], Upd.RequireVersion[3]);
                return false;
            // Target not found: keep going
            case C4UPD_CHK_NO_SOURCE:
                fprintf(stderr, "Target %s for update %s not found. Ignoring.\n",
                        Upd.DestPath, Upd.Name);
                return true;
            // Target mismatch: abort updating
            case C4UPD_CHK_BAD_SOURCE:
                fprintf(stderr,
                        "Target %s incorrect version for update %s. Ignoring.\n",
                        Upd.DestPath, Upd.Name);
                return true;
            // Target already updated: keep going
            case C4UPD_CHK_ALREADY_UPDATED:
                fprintf(stderr, "Target %s already up-to-date at %s.\n", Upd.DestPath,
                        Upd.Name);
                return true;
            // Ok to perform update
            case C4UPD_CHK_OK:
                printf("Updating %s to %s... ", Upd.DestPath, Upd.Name);
                // Make sure the user sees the message while the work is in progress
                fflush(stdout);
                // Execute update
                if (Upd.Execute(&hGroup)) {
                    printf("Ok\n");
                    return true;
                } else {
                    printf("Failed\n");
                    return false;
                }
            // Unknown return value from update
            default:
                fprintf(stderr, "Unknown error while updating.\n");
                return false;
            }
        }

    // Process binary update group (AutoUpdate.txt found, additional binary files
    // found)
    if (hGroup.EntryCount(C4CFN_UpdateCore))
        if (hGroup.EntryCount() - hGroup.EntryCount(C4CFN_UpdateCore) -
                hGroup.EntryCount("*.c4u") >
                0) {
            // Notice: AutoUpdate.txt is currently not processed...
            char strEntry[_MAX_FNAME + 1] = "";
            StdStrBuf strList;
            printf("Updating binaries...\n");
            hGroup.ResetSearch();
            // Look for binaries
            while (hGroup.FindNextEntry("*", strEntry))
                // Accept everything except *.c4u, AutoUpdate.txt, and c4group.exe
                // (which is assumed not to work under Windows)
                if (!WildcardMatch("*.c4u", strEntry) &&
                        !WildcardMatch(C4CFN_UpdateCore, strEntry) &&
                        !WildcardMatch("c4group.exe", strEntry)) {
                    strList += strEntry;
                    strList += ";";
                }
            // Extract binaries to current working directory
            if (!hGroup.Extract(strList.getData())) return false;
            // If extracted file is a group, explode it (this is meant for Clonk.app
            // on Mac)
            for (int i = 0; SGetModule(strList.getData(), i, strEntry); i++)
                if (C4Group_IsGroup(strEntry)) {
                    printf("Exploding: %s\n", strEntry);
                    if (!C4Group_ExplodeDirectory(strEntry)) return false;
                }
        }

    // Process any child updates (*.c4u)
    if (hGroup.FindEntry("*.c4u")) {
        // Process all children
        char strEntry[_MAX_FNAME + 1] = "";
        C4Group hChild;
        hGroup.ResetSearch();
        while (hGroup.FindNextEntry("*.c4u", strEntry))
            if (hChild.OpenAsChild(&hGroup, strEntry)) {
                bool ok = C4Group_ApplyUpdate(hChild);
                hChild.Close();
                // Failure on child update
                if (!ok) return false;
            }
    }

    // Success
    return true;
}
Exemplo n.º 4
0
bool C4Group_ApplyUpdate(C4Group &hGroup, unsigned long ParentProcessID)
{
	// Wait for parent process to terminate (so we can safely replace the executable)
#ifdef _WIN32
	if(ParentProcessID)
	{
		HANDLE ParentProcess = OpenProcess(SYNCHRONIZE, FALSE, ParentProcessID);
		if(ParentProcess)
		{
			// If we couldn't find a handle then either
			// a) the process terminated already, which is great.
			// b) OpenProcess() failed, which is not so great. But let's still try to do
			//    the update.
			printf("Waiting for parent process to terminate...");
			DWORD res = WaitForSingleObject(ParentProcess, 10000);
			if(res == WAIT_TIMEOUT)
				fprintf(stderr, "Parent process did not terminate after 10 seconds. Continuing...");
		}
	}
#else
	// We could use waitpid on Unix, but we don't need that functionality there anyway...
#endif

	// Process object update group (GRPUP_Entries.txt found)
	C4UpdatePackage Upd;
	if (hGroup.FindEntry(C4CFN_UpdateEntries))
		if (Upd.Load(&hGroup))
		{
			// Do update check first (ensure packet has everything it needs in order to perfom the update)
			int iRes = Upd.Check(&hGroup);
			switch (iRes)
			{
				// Bad version - checks against version of the applying executable (major version must match, minor version must be equal or higher)
			case C4UPD_CHK_BAD_VERSION:
				fprintf(stderr, "This update %s can only be applied using version %d.%d.%d.%d or higher.\n", Upd.Name, Upd.RequireVersion[0], Upd.RequireVersion[1], Upd.RequireVersion[2], Upd.RequireVersion[3]);
				return false;
				// Target not found: keep going
			case C4UPD_CHK_NO_SOURCE:
				fprintf(stderr, "Target %s for update %s not found. Ignoring.\n", Upd.DestPath, Upd.Name);
				return true;
				// Target mismatch: abort updating
			case C4UPD_CHK_BAD_SOURCE:
				fprintf(stderr, "Target %s incorrect version for update %s. Ignoring.\n", Upd.DestPath, Upd.Name);
				return true;
				// Target already updated: keep going
			case C4UPD_CHK_ALREADY_UPDATED:
				fprintf(stderr,"Target %s already up-to-date at %s.\n", Upd.DestPath, Upd.Name);
				return true;
				// Ok to perform update
			case C4UPD_CHK_OK:
				printf("Updating %s to %s... ", Upd.DestPath, Upd.Name);
				// Make sure the user sees the message while the work is in progress
				fflush(stdout);
				// Execute update
				if (Upd.Execute(&hGroup))
				{
					printf("Ok\n");
					return true;
				}
				else
				{
					printf("Failed\n");
					return false;
				}
				// Unknown return value from update
			default:
				fprintf(stderr,"Unknown error while updating.\n");
				return false;
			}
		}

	// Process binary update group (AutoUpdate.txt found, additional binary files found)
	if (hGroup.EntryCount(C4CFN_UpdateCore))
		if (hGroup.EntryCount() - hGroup.EntryCount(C4CFN_UpdateCore) - hGroup.EntryCount("*.ocu") > 0)
		{
			// Notice: AutoUpdate.txt is currently not processed...
			char strEntry[_MAX_FNAME + 1] = "";
			StdStrBuf strList;
			printf("Updating binaries...\n");
			hGroup.ResetSearch();
			// Look for binaries
			while (hGroup.FindNextEntry("*", strEntry))
				// Accept everything except *.ocu, AutoUpdate.txt, and c4group.exe (which is assumed not to work under Windows)
				if (!WildcardMatch("*.ocu", strEntry) && !WildcardMatch(C4CFN_UpdateCore, strEntry) && !WildcardMatch("c4group.exe", strEntry))
					{ strList += strEntry; strList += ";"; }
			// Extract binaries to current working directory
			if (!hGroup.Extract(strList.getData()))
				return false;
			// If extracted file is a group, explode it (this is meant for Clonk.app on Mac)
			for (int i = 0; SGetModule(strList.getData(), i, strEntry); i++)
				if (C4Group_IsGroup(strEntry))
				{
					printf("Exploding: %s\n", strEntry);
					if (!C4Group_ExplodeDirectory(strEntry))
						return false;
				}
		}

	// Process any child updates (*.ocu)
	if (hGroup.FindEntry("*.ocu"))
	{
		// Process all children
		char strEntry[_MAX_FNAME + 1] = "";
		C4Group hChild;
		hGroup.ResetSearch();
		while (hGroup.FindNextEntry("*.ocu", strEntry))
			if (hChild.OpenAsChild(&hGroup, strEntry))
			{
				bool ok = C4Group_ApplyUpdate(hChild, 0);
				hChild.Close();
				// Failure on child update
				if (!ok) return false;
			}
	}

	// Success
	return true;
}