Exemplo n.º 1
0
bool C4PlayerList::Save(C4Group &hGroup, bool fStoreTiny, const C4PlayerInfoList &rStoreList)
{
	StdStrBuf sTempFilename;
	bool fSuccess = true;
	// Save to external player files and add to group
	for (C4Player *pPlr=First; pPlr; pPlr=pPlr->Next)
	{
		// save only those in the list, and only those with a filename
		C4PlayerInfo *pNfo = rStoreList.GetPlayerInfoByID(pPlr->ID);
		if (!pNfo) continue;
		if (!pNfo->GetFilename() || !*pNfo->GetFilename()) continue;;
		// save over original file?
		bool fStoreOnOriginal = (!fStoreTiny && pNfo->GetType() == C4PT_User);
		// Create temporary file
		sTempFilename.Copy(Config.AtTempPath(pNfo->GetFilename()));
		if (fStoreOnOriginal)
			if (!C4Group_CopyItem(pPlr->Filename, sTempFilename.getData()))
				return false;
		// Open group
		C4Group PlrGroup;
		if (!PlrGroup.Open(sTempFilename.getData(), !fStoreOnOriginal))
			return false;
		// Save player
		if (!pPlr->Save(PlrGroup, true, fStoreOnOriginal)) return false;
		PlrGroup.Close();
		// Add temp file to group
		if (!hGroup.Move(sTempFilename.getData(), pNfo->GetFilename())) return false;
	}
	return fSuccess;
}
Exemplo n.º 2
0
int C4UpdatePackage::Check(C4Group *pGroup) {
    // Version requirement is set
    if (RequireVersion[0]) {
        // Engine and game version must match (rest ignored)
        if ((C4XVER1 != RequireVersion[0]) || (C4XVER2 != RequireVersion[1]))
            return C4UPD_CHK_BAD_VERSION;
    }

    // only group updates have any special needs
    if (!GrpUpdate) return C4UPD_CHK_OK;

    // check source file
    C4Group TargetGrp;
    if (!TargetGrp.Open(DestPath)) return C4UPD_CHK_NO_SOURCE;
    if (!TargetGrp.IsPacked()) return C4UPD_CHK_BAD_SOURCE;
    TargetGrp.Close();

    // check source crc
    uint32_t iCRC32;
    if (!C4Group_GetFileCRC(DestPath, &iCRC32)) return C4UPD_CHK_BAD_SOURCE;
    // equal to destination group?
    if (iCRC32 == GrpChks2)
        // so there's nothing to do
        return C4UPD_CHK_ALREADY_UPDATED;
    // check if it's one of our registered sources
    int i = 0;
    for (; i < UpGrpCnt; i++)
        if (iCRC32 == GrpChks1[i]) break;
    if (i >= UpGrpCnt) return C4UPD_CHK_BAD_SOURCE;

    // ok
    return C4UPD_CHK_OK;
}
Exemplo n.º 3
0
bool C4Network2Res::OptimizeStandalone(bool fSilent)
{
	CStdLock FileLock(&FileCSec);
	// for now: player files only
	if (Core.getType() == NRT_Player)
	{
		// log - this may take a few seconds
		if (!fSilent) LogF(LoadResStr("IDS_PRC_NETPREPARING"), GetFilename(szFile));
		// copy to temp file, if needed
		if (!fTempFile && SEqual(szFile, szStandalone))
		{
			char szNewStandalone[_MAX_PATH + 1];
			if (!pParent->FindTempResFileName(szStandalone, szNewStandalone))
				{ if (!fSilent) Log("OptimizeStandalone: could not find free name for temporary file!"); return false; }
			if (!C4Group_CopyItem(szStandalone, szNewStandalone))
				{ if (!fSilent) Log("OptimizeStandalone: could not copy to temporary file!"); return false; } /* TODO: Test failure */
			SCopy(szNewStandalone, szStandalone, sizeof(szStandalone) - 1);
		}
		// open as group
		C4Group Grp;
		if (!Grp.Open(szStandalone))
			{ if (!fSilent) Log("OptimizeStandalone: could not open player file!"); return false; }
		// remove bigicon, if the file size is too large
		size_t iBigIconSize=0;
		if (Grp.FindEntry(C4CFN_BigIcon, NULL, &iBigIconSize))
			if (iBigIconSize > C4NetResMaxBigicon*1024)
				Grp.Delete(C4CFN_BigIcon);
		Grp.Close();
	}
	return true;
}
Exemplo n.º 4
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.º 5
0
bool C4MainMenu::ActivateNewPlayer(int32_t iPlayer)
{
	// league or replay game
	if (Game.Parameters.isLeague() || Game.C4S.Head.Replay) return false;
	// Max player limit
	if (::Players.GetCount() >= Game.Parameters.MaxPlayers) return false;

	// Menu symbol/init
	if (GfxR->fctPlayerClr.Surface)
		GfxR->fctPlayerClr.Surface->SetClr(0xff);
	InitRefSym(GfxR->fctPlayerClr, LoadResStr("IDS_MENU_NOPLRFILES"), iPlayer);
	for (DirectoryIterator iter(Config.General.UserDataPath); *iter; ++iter)
		if (WildcardMatch("*.ocp", *iter))
		{
			char szFilename[_MAX_PATH+1], szCommand[_MAX_PATH+30+1];
			SCopy(*iter, szFilename, _MAX_PATH);
			if (DirectoryExists(szFilename)) continue;
			if (::Players.FileInUse(szFilename)) continue;
			// Open group
			C4Group hGroup;
			if (!hGroup.Open(szFilename)) continue;
			// Load player info
			C4PlayerInfoCore C4P;
			if (!C4P.Load(hGroup)) { hGroup.Close(); continue; }
			// Close group
			hGroup.Close();
			// Add player item
			sprintf(szCommand, "JoinPlayer:%s", szFilename);
			StdStrBuf sItemText;
			sItemText.Format(LoadResStr("IDS_MENU_NEWPLAYER"), C4P.PrefName);
			C4FacetSurface fctSymbol;
			// Add menu item
			Add(sItemText.getData(), fctSymbol, szCommand);
			// Reset symbol facet (menu holds on to the surface)
			fctSymbol.Default();
		}

	// Alignment
	SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom);
	// Go back to options menu on close
	SetCloseCommand("ActivateMenu:Main");

	return true;
}
Exemplo n.º 6
0
void C4Language::InitInfos()
{
	C4Group hGroup;
	// First, look in System.ocg
	if (Reloc.Open(hGroup, C4CFN_System))
	{
		LoadInfos(hGroup);
		hGroup.Close();
	}
	// Now look through the registered packs
	C4Group *pPack;
	for (int iPack = 0; (pPack = Packs.GetGroup(iPack)); iPack++)
		// Does it contain a System.ocg child group?
		if (hGroup.OpenAsChild(pPack, C4CFN_System))
		{
			LoadInfos(hGroup);
			hGroup.Close();
		}
}
Exemplo n.º 7
0
bool C4Language::InitStringTable(const char *strCode)
{
	C4Group hGroup;
	// First, look in System.ocg
	if (LoadStringTable(Application.SystemGroup, strCode))
		return true;
	// Now look through the registered packs
	C4Group *pPack;
	for (int iPack = 0; (pPack = Packs.GetGroup(iPack)); iPack++)
		// Does it contain a System.ocg child group?
		if (hGroup.OpenAsChild(pPack, C4CFN_System))
		{
			if (LoadStringTable(hGroup, strCode))
				{ hGroup.Close(); return true; }
			hGroup.Close();
		}
	// No matching string table found
	return false;
}
Exemplo n.º 8
0
bool C4ObjectInfo::Load(C4Group &hMother, const char *szEntryname)
{

	// New version
	if (SEqualNoCase(GetExtension(szEntryname),"oci"))
	{
		C4Group hChild;
		if (hChild.OpenAsChild(&hMother,szEntryname))
		{
			if (!C4ObjectInfo::Load(hChild))
				{ hChild.Close(); return false; }
			// resolve definition, if possible
			// only works in game, but is not needed in frontend or startup editing anyway
			pDef = C4Id2Def(id);
			hChild.Close();
			return true;
		}
	}

	return false;
}
Exemplo n.º 9
0
bool C4Shader::Refresh(const char *szWhat, const char **szUniforms)
{
	// Find a slice where the source file has updated
	ShaderSliceList::iterator pSlice;
	for (pSlice = FragmentSlices.begin(); pSlice != FragmentSlices.end(); pSlice++)
		if (pSlice->Source.getLength() &&
			FileExists(pSlice->Source.getData()) &&
			FileTime(pSlice->Source.getData()) > pSlice->SourceTime)
			break;
	if (pSlice == FragmentSlices.end()) return true;
	StdCopyStrBuf Source = pSlice->Source;

	// Okay, remove all slices that came from this file
	ShaderSliceList::iterator pNext;
	for (; pSlice != FragmentSlices.end(); pSlice = pNext)
	{
		pNext = pSlice; pNext++;
		if (SEqual(pSlice->Source.getData(), Source.getData()))
			FragmentSlices.erase(pSlice);
	}

	// Load new shader
	char szParentPath[_MAX_PATH+1]; C4Group Group;
	StdStrBuf Shader;
	GetParentPath(Source.getData(),szParentPath);
	if(!Group.Open(szParentPath) ||
	   !Group.LoadEntryString(GetFilename(Source.getData()),&Shader) ||
	   !Group.Close())
	{
		ShaderLogF("  gl: Failed to refresh %s shader from %s!", szWhat, Source.getData());
		return Refresh(szWhat, szUniforms);
	}

	// Load slices
	int iSourceTime = FileTime(Source.getData());
	StdStrBuf WhatSrc = FormatString("file %s", Config.AtRelativePath(Source.getData()));
	AddFragmentSlices(WhatSrc.getData(), Shader.getData(), Source.getData(), iSourceTime);

	// Reinitialise
	if (!Init(szWhat, szUniforms))
		return false;

	// Retry
	return Refresh(szWhat, szUniforms);
}
Exemplo n.º 10
0
bool C4ScenarioSection::EnsureTempStore(bool fExtractLandscape,
                                        bool fExtractObjects) {
  // if it's temp store already, don't do anything
  if (szTempFilename) return true;
  // make temp filename
  char *szTmp = const_cast<char *>(
      Config.AtTempPath(szFilename ? GetFilename(szFilename) : szName));
  MakeTempFilename(szTmp);
  // main section: extract section files from main scenario group (create group
  // as open dir)
  if (!szFilename) {
    if (!CreateDirectory(szTmp, NULL)) return false;
    C4Group hGroup;
    if (!hGroup.Open(szTmp, TRUE)) {
      EraseItem(szTmp);
      return false;
    }
    // extract all desired section files
    Game.ScenarioFile.ResetSearch();
    char fn[_MAX_FNAME + 1];
    *fn = 0;
    while (Game.ScenarioFile.FindNextEntry(C4FLS_Section, fn))
      if (fExtractLandscape || !WildcardMatch(C4FLS_SectionLandscape, fn))
        if (fExtractObjects || !WildcardMatch(C4FLS_SectionObjects, fn))
          Game.ScenarioFile.ExtractEntry(fn, szTmp);
    hGroup.Close();
  } else {
    // subsection: simply extract section from main group
    if (!Game.ScenarioFile.ExtractEntry(szFilename, szTmp)) return false;
    // delete undesired landscape/object files
    if (!fExtractLandscape || !fExtractObjects) {
      C4Group hGroup;
      if (hGroup.Open(szFilename)) {
        if (!fExtractLandscape) hGroup.Delete(C4FLS_SectionLandscape);
        if (!fExtractObjects) hGroup.Delete(C4FLS_SectionObjects);
      }
    }
  }
  // copy temp filename
  szTempFilename = new char[strlen(szTmp) + 1];
  SCopy(szTmp, szTempFilename, _MAX_PATH);
  // done, success
  return true;
}
Exemplo n.º 11
0
void C4PortraitSelDlg::ListItem::Load() {
  if (sFilename) {
    // safety
    fLoaded = false;
    // load image file
    C4Group SrcGrp;
    StdStrBuf sParentPath;
    GetParentPath(sFilename.getData(), &sParentPath);
    bool fLoadError = true;
    if (SrcGrp.Open(sParentPath.getData()))
      if (fctLoadedImage.Load(SrcGrp, ::GetFilename(sFilename.getData()))) {
        // image loaded. Can only be put into facet by main thread, because
        // those operations aren't thread safe
        fLoaded = true;
        fLoadError = false;
      }
    SrcGrp.Close();
    fError = fLoadError;
  }
}
Exemplo n.º 12
0
bool C4LoaderScreen::Init(const char *szLoaderSpec)
	{
	// Determine loader specification
	if (!szLoaderSpec || !szLoaderSpec[0]) 
		szLoaderSpec = "Loader*";
	char szLoaderSpecPng[128 + 1 + 4], szLoaderSpecBmp[128 + 1 + 4];
	char szLoaderSpecJpg[128 + 1 + 4], szLoaderSpecJpeg[128 + 1 + 5];
	SCopy(szLoaderSpec, szLoaderSpecPng); DefaultExtension(szLoaderSpecPng, "png");
	SCopy(szLoaderSpec, szLoaderSpecBmp); DefaultExtension(szLoaderSpecBmp, "bmp");
	SCopy(szLoaderSpec, szLoaderSpecJpg); DefaultExtension(szLoaderSpecJpg, "jpg");
	SCopy(szLoaderSpec, szLoaderSpecJpeg); DefaultExtension(szLoaderSpecJpeg, "jpeg");
	int iLoaders=0;
	C4Group *pGroup=NULL,*pChosenGrp=NULL;
	char ChosenFilename[_MAX_PATH+1];
	// query groups of equal priority in set
	while (pGroup=Game.GroupSet.FindGroup(C4GSCnt_Loaders, pGroup, true))
		{
		iLoaders+=SeekLoaderScreens(*pGroup, szLoaderSpecPng, iLoaders, ChosenFilename, &pChosenGrp);
		iLoaders+=SeekLoaderScreens(*pGroup, szLoaderSpecJpeg, iLoaders, ChosenFilename, &pChosenGrp);
		iLoaders+=SeekLoaderScreens(*pGroup, szLoaderSpecJpg, iLoaders, ChosenFilename, &pChosenGrp);
		// lower the chance for any loader other than png
		iLoaders*=2;
		iLoaders+=SeekLoaderScreens(*pGroup, szLoaderSpecBmp, iLoaders, ChosenFilename, &pChosenGrp);
		}
	// nothing found? seek in main gfx grp
	C4Group GfxGrp;
	if (!iLoaders)
		{
		// open it
		GfxGrp.Close();
		if (!GfxGrp.Open(Config.AtExePath(C4CFN_Graphics)))
			{
			LogFatal(FormatString(LoadResStr("IDS_PRC_NOGFXFILE"),C4CFN_Graphics,GfxGrp.GetError()).getData()); 
			return FALSE;
			}
		// seek for png-loaders
		iLoaders=SeekLoaderScreens(GfxGrp, szLoaderSpecPng, iLoaders, ChosenFilename, &pChosenGrp);
		iLoaders+=SeekLoaderScreens(GfxGrp, szLoaderSpecJpg, iLoaders, ChosenFilename, &pChosenGrp);
		iLoaders+=SeekLoaderScreens(GfxGrp, szLoaderSpecJpeg, iLoaders, ChosenFilename, &pChosenGrp);
		iLoaders*=2;
		// seek for bmp-loaders
		iLoaders+=SeekLoaderScreens(GfxGrp, szLoaderSpecBmp, iLoaders, ChosenFilename, &pChosenGrp);
		// Still nothing found: fall back to general loader spec in main graphics group
		if (!iLoaders)
			{
			iLoaders = SeekLoaderScreens(GfxGrp, "Loader*.png", 0, ChosenFilename, &pChosenGrp);
			iLoaders += SeekLoaderScreens(GfxGrp, "Loader*.jpg", iLoaders, ChosenFilename, &pChosenGrp);
			iLoaders += SeekLoaderScreens(GfxGrp, "Loader*.jpeg", iLoaders, ChosenFilename, &pChosenGrp);
			}
		// Not even default loaders available? Fail.
		if (!iLoaders) 
			{
			LogFatal(FormatString("No loaders found for loader specification: %s/%s/%s/%s", szLoaderSpecPng, szLoaderSpecBmp, szLoaderSpecJpg, szLoaderSpecJpeg).getData());
			return FALSE;
			}
		}

	// load loader
	fctBackground.GetFace().SetBackground();
	if (!fctBackground.Load(*pChosenGrp,ChosenFilename, C4FCT_Full,C4FCT_Full,true)) return FALSE;

	// load info
	if (szInfo) { delete [] szInfo; szInfo=NULL; }
	/*size_t iInfoSize;
	if (Game.ScenarioFile.AccessEntry(C4CFN_Info, &iInfoSize))
		{
		szInfo = new char[iInfoSize+1];
		// load info file
		Game.ScenarioFile.Read(szInfo, iInfoSize);
		// terminate buffer
		szInfo[iInfoSize]=0;
		// insert linebreaks
		SReplaceChar(szInfo, 0x0a, '|');
		}*/

	// init fonts
	if (!Game.GraphicsResource.InitFonts())
		return false;

	// initial draw
	C4Facet cgo;
	cgo.Set(Application.DDraw->lpPrimary,0,0,Config.Graphics.ResX,Config.Graphics.ResY); 
	Draw(cgo);

	// done, success!
	return TRUE;
	}
Exemplo n.º 13
0
bool C4Playback::StreamToRecord(const char *szStream, StdStrBuf *pRecordFile) {
  // Load data
  StdBuf CompressedData;
  Log("Reading stream...");
  if (!CompressedData.LoadFromFile(szStream)) return false;

  // Decompress
  unsigned long iStreamSize = CompressedData.getSize() * 5;
  StdBuf StreamData;
  StreamData.New(iStreamSize);
  while (true) {
    // Initialize stream
    z_stream strm;
    ZeroMem(&strm, sizeof strm);
    strm.next_in = getMBufPtr<BYTE>(CompressedData);
    strm.avail_in = CompressedData.getSize();
    strm.next_out = getMBufPtr<BYTE>(StreamData);
    strm.avail_out = StreamData.getSize();

    // Decompress
    if (inflateInit(&strm) != Z_OK) return false;
    int ret = inflate(&strm, Z_FINISH);
    if (ret == Z_STREAM_END) {
      inflateEnd(&strm);
      break;
    }
    if (ret != Z_BUF_ERROR) return false;

    // All input consumed?
    iStreamSize = strm.total_out;
    if (strm.avail_in == 0) {
      Log("Stream data incomplete, using as much data as possible");
      break;
    }

    // Larger buffer needed
    StreamData.Grow(CompressedData.getSize());
    iStreamSize = StreamData.getSize();
  }
  StreamData.SetSize(iStreamSize);

  // Parse
  C4Playback Playback;
  Playback.ReadBinary(StreamData);
  LogF("Got %d chunks from stream", Playback.chunks.size());

  // Get first chunk, which must contain the initial
  chunks_t::iterator chunkIter = Playback.chunks.begin();
  if (chunkIter == Playback.chunks.end() || chunkIter->Type != RCT_File)
    return false;

  // Get initial chunk, go over file name
  StdBuf InitialData = *chunkIter->pFileData;
  const char *szInitialFilename = chunkIter->Filename.getData();

  // Put to temporary file and unpack
  char szInitial[_MAX_PATH + 1] = "~initial.tmp";
  MakeTempFilename(szInitial);
  if (!InitialData.SaveToFile(szInitial) || !C4Group_UnpackDirectory(szInitial))
    return false;

  // Load Scenario.txt from Initial
  C4Group Grp;
  C4Scenario Initial;
  if (!Grp.Open(szInitial) || !Initial.Load(Grp) || !Grp.Close()) return false;

  // Copy original scenario
  const char *szOrigin = Initial.Head.Origin.getData();
  char szRecord[_MAX_PATH + 1];
  SCopy(szStream, szRecord, _MAX_PATH);
  if (GetExtension(szRecord)) *(GetExtension(szRecord) - 1) = 0;
  SAppend(".c4s", szRecord, _MAX_PATH);
  LogF("Original scenario is %s, creating %s.", szOrigin, szRecord);
  if (!C4Group_CopyItem(szOrigin, szRecord, false, false)) return false;

  // Merge initial
  if (!Grp.Open(szRecord) || !Grp.Merge(szInitial)) return false;

  // Process other files in stream
  chunkIter->Delete();
  chunkIter = Playback.chunks.erase(chunkIter);
  while (chunkIter != Playback.chunks.end())
    if (chunkIter->Type == RCT_File) {
      LogF("Inserting %s...", chunkIter->Filename.getData());
      StdStrBuf Temp;
      Temp.Copy(chunkIter->Filename);
      MakeTempFilename(&Temp);
      if (!chunkIter->pFileData->SaveToFile(Temp.getData())) return false;
      if (!Grp.Move(Temp.getData(), chunkIter->Filename.getData()))
        return false;
      chunkIter = Playback.chunks.erase(chunkIter);
    } else
      chunkIter++;

  // Write record data
  StdBuf RecordData = Playback.ReWriteBinary();
  if (!Grp.Add(C4CFN_CtrlRec, RecordData, false, true)) return false;

  // Done
  Log("Writing record file...");
  Grp.Close();
  pRecordFile->Copy(szRecord);
  return true;
}
Exemplo n.º 14
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.º 15
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;
}
Exemplo n.º 16
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.º 17
0
bool C4ObjectInfo::Save(C4Group &hGroup, bool fStoreTiny, C4DefList *pDefs)
{
	// Set group file name; rename if necessary
	char szTempGroup[_MAX_PATH+1];
	SCopy(Name, szTempGroup, _MAX_PATH);
	MakeFilenameFromTitle(szTempGroup);
	SAppend(".oci",szTempGroup, _MAX_PATH);
	if (!SEqualNoCase(Filename, szTempGroup))
	{
		if (!Filename[0])
		{
			// first time creation of file - make sure it's not a duplicate
			SCopy(szTempGroup, Filename, _MAX_PATH);
			while (hGroup.FindEntry(Filename))
			{
				// if a crew info of that name exists already, rename!
				RemoveExtension(Filename);
				int32_t iFinNum = GetTrailingNumber(Filename), iLen = SLen(Filename);
				while (iLen && Inside(Filename[iLen-1], '0', '9')) --iLen;
				if (iLen>_MAX_PATH-22) { LogF("Error generating unique filename for %s(%s): Path overflow", Name, hGroup.GetFullName().getData()); break; }
				snprintf(Filename+iLen, 22, "%d", iFinNum+1);
				EnforceExtension(Filename, "oci");
			}
		}
		else
		{
			// Crew was renamed; file rename necessary, if the name is not blocked by another crew info
			if (!hGroup.FindEntry(szTempGroup))
			{
				if (hGroup.Rename(Filename, szTempGroup))
					SCopy(szTempGroup, Filename, _MAX_PATH);
				else
				{
					// could not rename. Not fatal; just use old file
					LogF("Error adjusting crew info for %s into %s: Rename error from %s to %s!", Name, hGroup.GetFullName().getData(), Filename, szTempGroup);
				}
			}
		}
	}
	// Open group
	C4Group hTemp;
	if (!hTemp.OpenAsChild(&hGroup, Filename, false, true))
		return false;
	// custom rank image present?
	if (pDefs && !fStoreTiny)
	{
		C4Def *pDef = pDefs->ID2Def(id);
		if (pDef)
		{
			if (pDef->pRankSymbols)
			{
				C4FacetSurface fctRankSymbol;
				if (C4RankSystem::DrawRankSymbol(&fctRankSymbol, Rank, pDef->pRankSymbols, pDef->iNumRankSymbols, true))
				{
					fctRankSymbol.GetFace().SavePNG(hTemp, C4CFN_ClonkRank);
				}
			}
			else
			{
				// definition does not have custom rank symbols: Remove any rank image from Clonk
				hTemp.Delete(C4CFN_ClonkRank);
			}
		}
	}

	// Save info to temp group
	if (!C4ObjectInfoCore::Save(hTemp, pDefs))
		{ hTemp.Close(); return false; }
	// Close temp group
	hTemp.Close();
	// Success
	return true;
}
Exemplo n.º 18
0
bool C4LoaderScreen::Init(const char *szLoaderSpec)
{
	// Determine loader specification
	if (!szLoaderSpec || !szLoaderSpec[0])
		szLoaderSpec = "Loader*";
	char szLoaderSpecPng[128 + 1 + 4], szLoaderSpecBmp[128 + 1 + 4];
	char szLoaderSpecJpg[128 + 1 + 4], szLoaderSpecJpeg[128 + 1 + 5];
	SCopy(szLoaderSpec, szLoaderSpecPng); DefaultExtension(szLoaderSpecPng, "png");
	SCopy(szLoaderSpec, szLoaderSpecBmp); DefaultExtension(szLoaderSpecBmp, "bmp");
	SCopy(szLoaderSpec, szLoaderSpecJpg); DefaultExtension(szLoaderSpecJpg, "jpg");
	SCopy(szLoaderSpec, szLoaderSpecJpeg); DefaultExtension(szLoaderSpecJpeg, "jpeg");
	int iLoaders=0;
	C4Group *pGroup=NULL,*pChosenGrp=NULL;
	char ChosenFilename[_MAX_PATH+1];
	// query groups of equal priority in set
	while ((pGroup=Game.GroupSet.FindGroup(C4GSCnt_Loaders, pGroup, true)))
	{
		iLoaders+=SeekLoaderScreens(*pGroup, szLoaderSpecPng, iLoaders, ChosenFilename, &pChosenGrp);
		iLoaders+=SeekLoaderScreens(*pGroup, szLoaderSpecJpeg, iLoaders, ChosenFilename, &pChosenGrp);
		iLoaders+=SeekLoaderScreens(*pGroup, szLoaderSpecJpg, iLoaders, ChosenFilename, &pChosenGrp);
		// lower the chance for any loader other than png
		iLoaders*=2;
		iLoaders+=SeekLoaderScreens(*pGroup, szLoaderSpecBmp, iLoaders, ChosenFilename, &pChosenGrp);
	}
	// nothing found? seek in main gfx grp
	C4Group GfxGrp;
	if (!iLoaders)
	{
		// open it
		GfxGrp.Close();
		if (!Reloc.Open(GfxGrp, C4CFN_Graphics))
		{
			LogFatal(FormatString(LoadResStr("IDS_PRC_NOGFXFILE"),C4CFN_Graphics,GfxGrp.GetError()).getData());
			return false;
		}
		// seek for png-loaders
		iLoaders=SeekLoaderScreens(GfxGrp, szLoaderSpecPng, iLoaders, ChosenFilename, &pChosenGrp);
		iLoaders+=SeekLoaderScreens(GfxGrp, szLoaderSpecJpg, iLoaders, ChosenFilename, &pChosenGrp);
		iLoaders+=SeekLoaderScreens(GfxGrp, szLoaderSpecJpeg, iLoaders, ChosenFilename, &pChosenGrp);
		iLoaders*=2;
		// seek for bmp-loaders
		iLoaders+=SeekLoaderScreens(GfxGrp, szLoaderSpecBmp, iLoaders, ChosenFilename, &pChosenGrp);
		// Still nothing found: fall back to general loader spec in main graphics group
		if (!iLoaders)
		{
			iLoaders = SeekLoaderScreens(GfxGrp, "Loader*.png", 0, ChosenFilename, &pChosenGrp);
			iLoaders += SeekLoaderScreens(GfxGrp, "Loader*.jpg", iLoaders, ChosenFilename, &pChosenGrp);
			iLoaders += SeekLoaderScreens(GfxGrp, "Loader*.jpeg", iLoaders, ChosenFilename, &pChosenGrp);
		}
		// Not even default loaders available? Fail.
		if (!iLoaders)
		{
			LogFatal(FormatString("No loaders found for loader specification: %s/%s/%s/%s", szLoaderSpecPng, szLoaderSpecBmp, szLoaderSpecJpg, szLoaderSpecJpeg).getData());
			return false;
		}
	}

	// load loader
	fctBackground.GetFace().SetBackground();
	if (!fctBackground.Load(*pChosenGrp,ChosenFilename, C4FCT_Full,C4FCT_Full,true,0)) return false;

	// load info
	if (szInfo) { delete [] szInfo; szInfo=NULL; }

	// done, success!
	return true;
}