Example #1
0
bool LogSilent(const char *szMessage, bool fConsole) {
  if (!Application.AssertMainThread()) return false;
  // security
  if (!szMessage) return false;

  // add timestamp
  time_t timenow;
  time(&timenow);
  StdStrBuf TimeMessage;
  TimeMessage.SetLength(11 + SLen(szMessage) + 1);
  strftime(TimeMessage.getMData(), 11 + 1, "[%H:%M:%S] ", localtime(&timenow));

  // output until all data is written
  const char *pSrc = szMessage;
  do {
    // timestamp will always be that length
    char *pDest = TimeMessage.getMData() + 11;

    // copy rest of message, skip tags
    CMarkup Markup(false);
    while (*pSrc) {
      Markup.SkipTags(&pSrc);
      // break on crlf
      while (*pSrc == '\r') pSrc++;
      if (*pSrc == '\n') {
        pSrc++;
        break;
      }
      // copy otherwise
      if (*pSrc) *pDest++ = *pSrc++;
    }
    *pDest++ = '\n';
    *pDest = '\0';

#ifdef HAVE_ICONV
    StdStrBuf Line = Languages.IconvSystem(TimeMessage.getData());
#else
    StdStrBuf &Line = TimeMessage;
#endif

    // Save into log file
    if (C4LogFile) {
      fputs(Line.getData(), C4LogFile);
      fflush(C4LogFile);
    }

    // Write to console
    if (fConsole || Game.Verbose) {
#if defined(_DEBUG) && defined(_WIN32)
      // debug: output to VC console
      OutputDebugString(Line.getData());
#endif
      fputs(Line.getData(), stdout);
      fflush(stdout);
    }

  } while (*pSrc);

  return true;
}
void C4MusicSystem::LoadMoreMusic()
{
	StdStrBuf MoreMusicFile;
	// load MoreMusic.txt
	if (!MoreMusicFile.LoadFromFile(Config.AtUserDataPath(C4CFN_MoreMusic))) return;
	// read contents
	char *pPos = MoreMusicFile.getMData();
	while (pPos && *pPos)
	{
		// get line
		char szLine[1024 + 1];
		SCopyUntil(pPos, szLine, '\n', 1024);
		pPos = strchr(pPos, '\n'); if (pPos) pPos++;
		// remove leading whitespace
		char *pLine = szLine;
		while (*pLine == ' ' || *pLine == '\t' || *pLine == '\r') pLine++;
		// and whitespace at end
		char *p = pLine + strlen(pLine) - 1;
		while (*p == ' ' || *p == '\t' || *p == '\r') { *p = 0; --p; }
		// comment?
		if (*pLine == '#')
		{
			// might be a "directive"
			if (SEqual(pLine, "#clear"))
				ClearSongs();
			continue;
		}
		// try to load file(s)
		LoadDir(pLine);
	}
}
Example #3
0
BOOL C4UpdatePackageCore::Save(C4Group &hGroup) {
    try {
        // decompile data
        StdStrBuf Core =
            DecompileToBuf<StdCompilerINIWrite>(mkNamingAdapt(*this, "Update"));
        char *stupid_buffer = new char[Core.getLength() + 1];
        memcpy(stupid_buffer, Core.getMData(), Core.getLength() + 1);
        // add to group
        return hGroup.Add(C4CFN_UpdateCore, stupid_buffer, Core.getLength(), FALSE,
                          TRUE);
    } catch (StdCompiler::Exception *pExc) {
        delete pExc;
        return FALSE;
    }
}
Example #4
0
bool GetLogSection(size_t iStart, size_t iLength, StdStrBuf &rsOut)
{
	if (!iLength) { rsOut.Clear(); return true; }
	// read section from log file
	StdStrBuf BufOrig;
	if (!BufOrig.LoadFromFile(sLogFileName.getData())) return false;
	char *szBuf = BufOrig.getMData();
	size_t iSize = BufOrig.getSize(); // size excluding terminator
	// reduce to desired buffer section
	if (iStart > iSize) iStart = iSize;
	if (iStart + iLength > iSize) iLength = iSize - iStart;
	szBuf += iStart; szBuf[iLength] = '\0';
	// strip timestamps; convert linebreaks to Clonk-linebreaks '|'
	char *szPosWrite=szBuf; const char *szPosRead=szBuf;
	while (*szPosRead)
	{
		// skip timestamp
		if (*szPosRead == '[')
			while (*szPosRead && *szPosRead != ']') { --iSize; ++szPosRead; }
		// skip whitespace behind timestamp
		if (!*szPosRead) break;
		szPosRead++;
		// copy data until linebreak
		size_t iLen=0;
		while (*szPosRead && *szPosRead != 0x0d && *szPosRead != 0x0a)
			{ ++szPosRead; ++iLen; }
		if (iLen && szPosRead-iLen != szPosWrite) memmove(szPosWrite, szPosRead-iLen, iLen);
		szPosWrite += iLen;
		// skip additional linebreaks
		while (*szPosRead == 0x0d || *szPosRead == 0x0a) ++szPosRead;
		// write a Clonk-linebreak
		if (*szPosRead) *szPosWrite++ = '|';
	}
	// done; create string buffer from data
	rsOut.Copy(szBuf, szPosWrite - szBuf);
	// done, success
	return true;
}
Example #5
0
bool LogSilent(const char *szMessage, bool fConsole)
{
	if (!Application.AssertMainThread()) return false;
	// security
	if (!szMessage) return false;

	// add timestamp
	time_t timenow; time(&timenow);
	StdStrBuf TimeMessage;
	TimeMessage.SetLength(11 + SLen(szMessage) + 1);
	strftime(TimeMessage.getMData(), 11 + 1, "[%H:%M:%S] ", localtime(&timenow));

	// output until all data is written
	const char *pSrc = szMessage;
	do
	{
		// timestamp will always be that length
		char *pDest = TimeMessage.getMData() + 11;

		// copy rest of message, skip tags
		C4Markup Markup(false);
		while (*pSrc)
		{
			Markup.SkipTags(&pSrc);
			// break on crlf
			while (*pSrc == '\r') pSrc++;
			if (*pSrc == '\n') { pSrc++; break; }
			// copy otherwise
			if (*pSrc) *pDest++ = *pSrc++;
		}
		*pDest++='\n'; *pDest = '\0';

		// Save into log file
		if (C4LogFile)
		{
			fputs(TimeMessage.getData(),C4LogFile);
			fflush(C4LogFile);
		}

		// Save into record log file, if available
		if(Control.GetRecord())
		{
			Control.GetRecord()->GetLogFile()->Write(TimeMessage.getData(), TimeMessage.getLength());
			#ifdef IMMEDIATEREC
				Control.GetRecord()->GetLogFile()->Flush();
			#endif
		}


		// Write to console
		if (fConsole)
		{
#if defined(_WIN32)
			// debug: output to VC console
			OutputDebugString(TimeMessage.GetWideChar());
#endif
#if !defined(_WIN32) || defined(USE_CONSOLE)
			fputs(TimeMessage.getData(),stdout);
			fflush(stdout);
#endif
		}

	}
	while (*pSrc);

	return true;
}
Example #6
0
	bool ValidateString(StdStrBuf &rsString, ValidationOption eOption)
		{
		bool fValid = true;
		// validation depending on option
		// check min length
		if (!rsString.getLength())
			{
			// empty if not allowed?
			if (eOption != VAL_NameAllowEmpty && eOption != VAL_NameExAllowEmpty && eOption != VAL_Comment)
				{
				rsString.Copy("empty");
				fValid = false;
				}
			}
		switch (eOption)
			{
			case VAL_Filename: // regular filenames only
				// absolutely no directory traversal
				if (rsString.ReplaceChar('/', '_')) fValid = false;
				if (rsString.ReplaceChar('\\', '_')) fValid = false;

				// fallthrough to general file name validation
			case VAL_SubPathFilename: // filenames and optional subpath
				// do not traverse upwards in file hierarchy
				if (rsString.Replace("..", "__")) fValid = false;
				if (*rsString.getData() == '/' || *rsString.getData() == '\\') { *rsString.getMData() = '_'; fValid = false; }

				// fallthrough to general file name validation
			case VAL_FullPath:        // full filename paths
				// some characters are prohibited in filenames in general
				if (rsString.ReplaceChar('*', '_')) fValid = false;
				if (rsString.ReplaceChar('?', '_')) fValid = false;
				if (rsString.ReplaceChar('<', '_')) fValid = false;
				if (rsString.ReplaceChar('>', '_')) fValid = false;
				// ';' and '|' is never allowed in filenames, because it would cause problems in many engine internal file lists
				if (rsString.ReplaceChar(';', '_')) fValid = false;
				if (rsString.ReplaceChar('|', '_')) fValid = false;
				// the colon is generally prohibited except at pos 2 (C:\...), because it could lead to creation of (invisible) streams on NTFS
				if (rsString.ReplaceChar(':', '_', 2)) fValid = false;
				if (*rsString.getData() == ':') { *rsString.getMData() = '_'; fValid = false; }
				// validate drive letter
				if (rsString.getLength()>=2 && *rsString.getPtr(1) == ':')
					{
					if (eOption != VAL_FullPath)
						{
						*rsString.getMPtr(1)='_'; fValid = false;
						}
					else if (!isalpha((unsigned char)*rsString.getData()) || (*rsString.getPtr(2)!='\\' && *rsString.getPtr(2)!='/'))
						{
						*rsString.getMData()=*rsString.getMPtr(1)='_'; fValid = false;
						}
					}
				break;

			case VAL_NameNoEmpty:
			case VAL_NameAllowEmpty:
				// no markup
				if (CMarkup::StripMarkup(&rsString)) { fValid = false; }
				// trim spaces
				if (rsString.TrimSpaces()) fValid = false;
				// min length
				if (eOption == VAL_NameNoEmpty) if (!rsString.getLength()) { fValid = false; rsString.Copy("Unknown"); }
				// max length
				if (rsString.getLength() > C4MaxName) { fValid = false; rsString.SetLength(C4MaxName); }
				break;

			case VAL_NameExNoEmpty:
			case VAL_NameExAllowEmpty:
				// trim spaces
				if (rsString.TrimSpaces()) fValid = false;
				// min length
				if (eOption == VAL_NameExNoEmpty) if (!rsString.getLength()) { fValid = false; rsString.Copy("Unknown"); }
				// max length
				if (rsString.getLength() > C4MaxLongName) { fValid = false; rsString.SetLength(C4MaxLongName); }
				break;

			case VAL_IRCName: // nickname for IRC. a-z, A-Z, _^{[]} only; 0-9|- inbetween; max 30 characters
				if (rsString.getLength() > 30) fValid = false;
				if (rsString.getLength() < 2) fValid = false;
				if (!rsString.ValidateChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_^{[]}", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_^{[]}0123456789|-")) { fValid = false; rsString.Copy("Guest"); }
				if (SEqualNoCase(rsString.getData(), "NickServ")
				 || SEqualNoCase(rsString.getData(), "ChanServ")
				 || SEqualNoCase(rsString.getData(), "MemoServ")
				 || SEqualNoCase(rsString.getData(), "OperServ")
				 || SEqualNoCase(rsString.getData(), "HelpServ")) fValid = false;
				if (!fValid) rsString.Copy("Guest");
				break;

			case VAL_IRCPass: // password for IRC; max 31 characters
				// max length; no spaces
				if (rsString.getLength() > 31) { fValid = false; rsString.SetLength(31); }
				if (rsString.getLength() < 2) { fValid = false; rsString.Copy("secret"); }
				if (rsString.ReplaceChar(' ', '_')) fValid = false;
				break;

			case VAL_IRCChannel: // IRC channel name
				if (rsString.getLength() > 32) { fValid = false; rsString.SetLength(32); }
				else if (rsString.getLength() < 2) { fValid = false; rsString.Copy("#clonken"); }
				else if (*rsString.getData() != '#' && *rsString.getData() != '+') { fValid = false; *rsString.getMData() = '#'; }
				if (rsString.ReplaceChar(' ', '_')) fValid = false;
				break;

			case VAL_Comment: // comment - just limit length
				if (rsString.getLength() > C4MaxComment) { fValid = false; rsString.SetLength(C4MaxComment); }
				break;

			default:
				assert(!"not yet implemented");
			}
		// issue warning for invalid adjustments
		if (!fValid)
			{
			const char *szOption = "unknown";
			switch (eOption)
				{
				case VAL_Filename:         szOption = "filename";         break;
				case VAL_SubPathFilename:  szOption = "(sub-)filename";   break;
				case VAL_FullPath:         szOption = "free filename";    break;
				case VAL_NameNoEmpty:      szOption = "strict name";      break;
				case VAL_NameExNoEmpty:    szOption = "name";             break;
				case VAL_NameAllowEmpty:   szOption = "strict name*";     break;
				case VAL_NameExAllowEmpty: szOption = "name*";            break;
				case VAL_IRCName:          szOption = "IRC nick";         break;
				case VAL_IRCPass:          szOption = "IRC password";     break;
				case VAL_IRCChannel:       szOption = "IRC channel";      break;
				case VAL_Comment:          szOption = "Comment";          break;
				}
			//LogF("WARNING: Adjusted invalid user input for \"%s\" to \"%s\"", szOption, rsString.getData());
			}
		return !fValid;
		}
Example #7
0
CStdWindow *CStdWindow::Init(CStdApp *pApp, const char *Title,
                             CStdWindow *pParent, bool HideCursor) {
#ifndef USE_X11
  return this;
#else
  Active = true;
  dpy = pApp->dpy;

  if (!FindInfo()) return 0;

  // Various properties
  XSetWindowAttributes attr;
  attr.border_pixel = 0;
  attr.background_pixel = 0;
  // Which events we want to receive
  attr.event_mask =
      // EnterWindowMask |
      // LeaveWindowMask |
      StructureNotifyMask | FocusChangeMask | KeyPressMask | KeyReleaseMask |
      PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
  attr.colormap = XCreateColormap(dpy, DefaultRootWindow(dpy),
                                  ((XVisualInfo *)Info)->visual, AllocNone);
  unsigned long attrmask =
      CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
  Pixmap bitmap;
  if (HideCursor) {
    // Hide the mouse cursor
    XColor cursor_color;
    // We do not care what color the invisible cursor has
    memset(&cursor_color, 0, sizeof(cursor_color));
    bitmap = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), "\000", 1, 1);
    attr.cursor = XCreatePixmapCursor(dpy, bitmap, bitmap, &cursor_color,
                                      &cursor_color, 0, 0);
    attrmask |= CWCursor;
  }

  wnd = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0, 640, 480, 0,
                      ((XVisualInfo *)Info)->depth, InputOutput,
                      ((XVisualInfo *)Info)->visual, attrmask, &attr);
  if (HideCursor) {
    XFreeCursor(dpy, attr.cursor);
    XFreePixmap(dpy, bitmap);
  }
  if (!wnd) {
    Log("Error creating window.");
    return 0;
  }
  // Update the XWindow->CStdWindow-Map
  CStdAppPrivate::SetWindow(wnd, this);
  if (!pApp->Priv->xic && pApp->Priv->xim) {
    pApp->Priv->xic = XCreateIC(
        pApp->Priv->xim, XNClientWindow, wnd, XNFocusWindow, wnd, XNInputStyle,
        XIMPreeditNothing | XIMStatusNothing, XNResourceName, STD_PRODUCT,
        XNResourceClass, STD_PRODUCT, NULL);
    if (!pApp->Priv->xic) {
      Log("Failed to create input context.");
      XCloseIM(pApp->Priv->xim);
      pApp->Priv->xim = 0;
    } else {
      long ic_event_mask;
      if (XGetICValues(pApp->Priv->xic, XNFilterEvents, &ic_event_mask, NULL) ==
          NULL)
        attr.event_mask |= ic_event_mask;
      XSelectInput(dpy, wnd, attr.event_mask);
      XSetICFocus(pApp->Priv->xic);
    }
  }
  // We want notification of closerequests and be killed if we hang
  Atom WMProtocols[2];
  char *WMProtocolnames[] = {"WM_DELETE_WINDOW", "_NET_WM_PING"};
  XInternAtoms(dpy, WMProtocolnames, 2, false, WMProtocols);
  XSetWMProtocols(dpy, wnd, WMProtocols, 2);
  // Let the window manager know our pid so it can kill us
  Atom PID = XInternAtom(pApp->dpy, "_NET_WM_PID", false);
  int32_t pid = getpid();
  if (PID != None)
    XChangeProperty(pApp->dpy, wnd, PID, XA_CARDINAL, 32, PropModeReplace,
                    reinterpret_cast<const unsigned char *>(&pid), 1);
  // Title and stuff
  XTextProperty title_property;
  StdStrBuf tbuf;
  tbuf.Copy(Title ? Title : "");
  char *tbufstr = tbuf.getMData();
  // char * title = "Clonk Endeavour";
  XStringListToTextProperty(&tbufstr, 1, &title_property);
  // State and Icon
  XWMHints *wm_hint = XAllocWMHints();
  wm_hint->flags = StateHint | InputHint | IconPixmapHint | IconMaskHint;
  wm_hint->initial_state = NormalState;
  wm_hint->input = True;
  // Trust XpmCreatePixmapFromData to not modify the xpm...
  XpmCreatePixmapFromData(dpy, wnd, const_cast<char **>(c4x_xpm),
                          &wm_hint->icon_pixmap, &wm_hint->icon_mask, 0);
  // Window class
  XClassHint *class_hint = XAllocClassHint();
  class_hint->res_name = STD_PRODUCT;
  class_hint->res_class = STD_PRODUCT;
  XSetWMProperties(dpy, wnd, &title_property, &title_property, pApp->Priv->argv,
                   pApp->Priv->argc, 0, wm_hint, class_hint);
  // Set "parent". Clonk does not use "real" parent windows, but multiple
  // toplevel windows.
  if (pParent) XSetTransientForHint(dpy, wnd, pParent->wnd);
  // Show window
  XMapWindow(dpy, wnd);
  // Clean up
  // The pixmap has to stay as long as the window exists, so it does not hurt to
  // never free it.
  // XFreePixmap(dpy,xwmh->icon_pixmap);
  // XFreePixmap(dpy,xwmh->icon_mask);
  XFree(title_property.value);
  Hints = wm_hint;
  XFree(class_hint);

  // Render into whole window
  renderwnd = wnd;

  return this;
#endif  // USE_X11
}