fix: use more robust parsing of large timespans

This commit is contained in:
punchready 2022-05-08 10:01:02 +02:00
parent 07becc3c8f
commit 7e381d61f6
2 changed files with 79 additions and 3 deletions

View file

@ -1512,7 +1512,7 @@ namespace TShockAPI
} }
} }
if (TShock.Utils.TryParseTime(duration, out int seconds)) if (TShock.Utils.TryParseTime(duration, out ulong seconds))
{ {
expiration = DateTime.UtcNow.AddSeconds(seconds); expiration = DateTime.UtcNow.AddSeconds(seconds);
} }
@ -1880,7 +1880,7 @@ namespace TShockAPI
if (args.Parameters.Count > 2) if (args.Parameters.Count > 2)
{ {
int time; ulong time;
if (!TShock.Utils.TryParseTime(args.Parameters[2], out time)) if (!TShock.Utils.TryParseTime(args.Parameters[2], out time))
{ {
args.Player.SendErrorMessage("Invalid time string! Proper format: _d_h_m_s, with at least one time specifier."); args.Player.SendErrorMessage("Invalid time string! Proper format: _d_h_m_s, with at least one time specifier.");
@ -1888,7 +1888,7 @@ namespace TShockAPI
return; return;
} }
ply[0].tempGroupTimer = new System.Timers.Timer(time * 1000); ply[0].tempGroupTimer = new System.Timers.Timer(time * 1000d);
ply[0].tempGroupTimer.Elapsed += ply[0].TempGroupTimerElapsed; ply[0].tempGroupTimer.Elapsed += ply[0].TempGroupTimerElapsed;
ply[0].tempGroupTimer.Start(); ply[0].tempGroupTimer.Start();
} }

View file

@ -607,6 +607,82 @@ namespace TShockAPI
return true; return true;
} }
/// <summary>
/// Attempts to parse a string as a positive timespan (_d_m_h_s).
/// </summary>
/// <param name="str">The time string.</param>
/// <param name="seconds">The seconds.</param>
/// <returns>Whether the string was parsed successfully.</returns>
public bool TryParseTime(string str, out ulong seconds)
{
seconds = 0;
if (string.IsNullOrWhiteSpace(str))
{
return false;
}
var sb = new StringBuilder(3);
for (int i = 0; i < str.Length; i++)
{
if (char.IsDigit(str[i]) || (str[i] == '-' || str[i] == '+' || str[i] == ' '))
sb.Append(str[i]);
else
{
int num;
if (!int.TryParse(sb.ToString().Trim(' '), out num))
return false;
sb.Clear();
if (num == 0)
{
continue;
}
int numSeconds;
switch (str[i])
{
case 's':
numSeconds = num;
break;
case 'm':
numSeconds = num * 60;
break;
case 'h':
numSeconds = num * 60 * 60;
break;
case 'd':
numSeconds = num * 60 * 60 * 24;
break;
default:
return false;
}
if (numSeconds > 0)
{
if (ulong.MaxValue - seconds < (uint)numSeconds)
{
return false;
}
seconds += (uint)numSeconds;
}
else if (seconds >= (uint)Math.Abs(numSeconds))
{
seconds -= (uint)Math.Abs(numSeconds);
}
else
{
return false;
}
}
}
if (sb.Length != 0)
return false;
return true;
}
/// <summary> /// <summary>
/// Searches for a projectile by identity and owner /// Searches for a projectile by identity and owner
/// </summary> /// </summary>