DEADSOFTWARE

escape strings in stat files
authorfgsfds <pvt.fgsfds@gmail.com>
Tue, 24 Dec 2019 14:28:52 +0000 (17:28 +0300)
committerfgsfds <pvt.fgsfds@gmail.com>
Tue, 24 Dec 2019 14:28:52 +0000 (17:28 +0300)
src/game/g_game.pas
src/shared/utils.pas

index b34e2ef0c57ad0ff74121bb5cf99997ed7a8230d..ef256d18c597441246b1fd81e115d67b259a1c77 100644 (file)
@@ -660,30 +660,43 @@ begin
     AssignFile(s, fname);
     try
       Rewrite(s);
-      // line 1: stats version, datetime, server name, map name, game mode, time limit, score limit, dmflags, game time, number of players
+      // line 1: stats ver, datetime, server name, map name, game mode, time limit, score limit, dmflags, game time, num players
       if g_Game_IsNet then fname := NetServerName else fname := '';
       map := g_ExtractWadNameNoPath(gMapInfo.Map) + ':/' + g_ExtractFileName(gMapInfo.Map);
       mode := g_Game_ModeToText(Stat.GameMode);
-      etime := Format('%d:%.2d:%.2d', [Stat.GameTime div 1000 div 3600,
-                                       (Stat.GameTime div 1000 div 60) mod 60,
-                                       Stat.GameTime div 1000 mod 60]);
+      etime := Format('%d:%.2d:%.2d', [
+        Stat.GameTime div 1000 div 3600,
+        (Stat.GameTime div 1000 div 60) mod 60,
+        Stat.GameTime div 1000 mod 60
+      ]);
       WriteLn(s, 'stats_ver,datetime,server,map,mode,timelimit,scorelimit,dmflags,time,num_players');
-      WriteLn(s,
-        Format('%d,%s,%s,%s,%s,%u,%u,%u,%s,%d',
-          [STATFILE_VERSION, StatDate, fname, map, mode, gGameSettings.TimeLimit, gGameSettings.GoalLimit, gGameSettings.Options, etime, Length(Stat.PlayerStat)]));
+      WriteLn(s, Format('%d,%s,%s,%s,%s,%u,%u,%u,%s,%d', [
+        STATFILE_VERSION,
+        StatDate,
+        dquoteStr(fname),
+        dquoteStr(map),
+        mode,
+        gGameSettings.TimeLimit,
+        gGameSettings.GoalLimit,
+        gGameSettings.Options,
+        etime,
+        Length(Stat.PlayerStat)
+      ]));
       // line 2: game specific shit
       //   if it's a team game: red score, blue score
       //   if it's a coop game: monsters killed, monsters total, secrets found, secrets total
       //   otherwise nothing
       if Stat.GameMode in [GM_TDM, GM_CTF] then
-        WriteLn(s, Format('red_score,blue_score' + LineEnding + '%d,%d', [Stat.TeamStat[TEAM_RED].Goals, Stat.TeamStat[TEAM_BLUE].Goals]))
+        WriteLn(s, 
+          Format('red_score,blue_score' + LineEnding + '%d,%d', [Stat.TeamStat[TEAM_RED].Goals, Stat.TeamStat[TEAM_BLUE].Goals]))
       else if Stat.GameMode in [GM_COOP, GM_SINGLE] then
-        WriteLn(s, Format('mon_killed,mon_total,secrets_found,secrets_total' + LineEnding + '%d,%d,%d,%d', [gCoopMonstersKilled, gTotalMonsters, gCoopSecretsFound, gSecretsCount]));
+        WriteLn(s,
+          Format('mon_killed,mon_total,secrets_found,secrets_total' + LineEnding + '%d,%d,%d,%d',[gCoopMonstersKilled, gTotalMonsters, gCoopSecretsFound, gSecretsCount]));
       // lines 3-...: team, player name, frags, deaths
       WriteLn(s, 'team,name,frags,deaths');
       for I := Low(Stat.PlayerStat) to High(Stat.PlayerStat) do
         with Stat.PlayerStat[I] do
-          WriteLn(s, Format('%d,%s,%d,%d', [Team, Name, Frags, Deaths]));
+          WriteLn(s, Format('%d,%s,%d,%d', [Team, dquoteStr(Name), Frags, Deaths]));
     except
       g_Console_Add(Format(_lc[I_CONSOLE_ERROR_WRITE], [fname]));
     end;
index f5f762c6e983c96a5dd7c54ad3fb68c82110d058..946e4f5a07c7a31a5422fad1f2f479fb83ffce6a 100644 (file)
@@ -247,6 +247,9 @@ function digitInBase (ch: AnsiChar; base: Integer): Integer;
 // double quotes supports c-style escapes
 // function will select quote mode automatically
 function quoteStr (const s: AnsiString): AnsiString;
+// separate single-quote and double-quote escape functions
+function squoteStr (const s: AnsiString): AnsiString;
+function dquoteStr (const s: AnsiString): AnsiString;
 
 
 type
@@ -720,53 +723,52 @@ end;
 
 
 // ////////////////////////////////////////////////////////////////////////// //
-function quoteStr (const s: AnsiString): AnsiString;
-
-  function squote (const s: AnsiString): AnsiString;
-  var
-    f: Integer;
+function squoteStr (const s: AnsiString): AnsiString;
+var
+  f: Integer;
+begin
+  result := '''';
+  for f := 1 to Length(s) do
   begin
-    result := '''';
-    for f := 1 to Length(s) do
-    begin
-      if (s[f] = '''') then result += '''';
-      result += s[f];
-    end;
-    result += '''';
+    if (s[f] = '''') then result += '''';
+    result += s[f];
   end;
+  result += '''';
+end;
 
-  function dquote (const s: AnsiString): AnsiString;
-  var
-    f: Integer;
-    ch: AnsiChar;
+function dquoteStr (const s: AnsiString): AnsiString;
+var
+  f: Integer;
+  ch: AnsiChar;
+begin
+  result := '"';
+  for f := 1 to Length(s) do
   begin
-    result := '"';
-    for f := 1 to Length(s) do
+    ch := s[f];
+         if (ch = #0) then result += '\z'
+    else if (ch = #9) then result += '\t'
+    else if (ch = #10) then result += '\n'
+    else if (ch = #13) then result += '\r'
+    else if (ch = #27) then result += '\e'
+    else if (ch < ' ') or (ch = #127) then
     begin
-      ch := s[f];
-           if (ch = #0) then result += '\z'
-      else if (ch = #9) then result += '\t'
-      else if (ch = #10) then result += '\n'
-      else if (ch = #13) then result += '\r'
-      else if (ch = #27) then result += '\e'
-      else if (ch < ' ') or (ch = #127) then
-      begin
-        result += '\x';
-        result += LowerCase(IntToHex(Integer(ch), 2));
-      end
-      else if (ch = '"') or (ch = '\') then
-      begin
-        result += '\';
-        result += ch;
-      end
-      else
-      begin
-        result += ch;
-      end;
+      result += '\x';
+      result += LowerCase(IntToHex(Integer(ch), 2));
+    end
+    else if (ch = '"') or (ch = '\') then
+    begin
+      result += '\';
+      result += ch;
+    end
+    else
+    begin
+      result += ch;
     end;
-    result += '"';
   end;
+  result += '"';
+end;
 
+function quoteStr (const s: AnsiString): AnsiString;
 var
   needSingle: Boolean = false;
   f: Integer;
@@ -774,9 +776,9 @@ begin
   for f := 1 to Length(s) do
   begin
     if (s[f] = '''') then begin needSingle := true; continue; end;
-    if (s[f] < ' ') or (s[f] = #127) then begin result := dquote(s); exit; end;
+    if (s[f] < ' ') or (s[f] = #127) then begin result := dquoteStr(s); exit; end;
   end;
-  if needSingle then result := squote(s) else result := ''''+s+'''';
+  if needSingle then result := squoteStr(s) else result := ''''+s+'''';
 end;