fix reading PT6 having signed decimal GUID in log

fix  alternative encoding character converting
allow more paths for game log server
add localization for unknown ips in welcome plugin
add gamelog server uri to support game log server on games that must supply manual log path
misc fixes
This commit is contained in:
RaidMax 2019-02-09 15:35:13 -06:00
parent 7c6419a16a
commit dea5b3f954
15 changed files with 81 additions and 67 deletions

View File

@ -6,7 +6,7 @@
<RuntimeFrameworkVersion>2.1.5</RuntimeFrameworkVersion>
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
<PackageId>RaidMax.IW4MAdmin.Application</PackageId>
<Version>2.2.4.6</Version>
<Version>2.2.4.7</Version>
<Authors>RaidMax</Authors>
<Company>Forever None</Company>
<Product>IW4MAdmin</Product>
@ -31,8 +31,8 @@
<PropertyGroup>
<ServerGarbageCollection>true</ServerGarbageCollection>
<TieredCompilation>true</TieredCompilation>
<AssemblyVersion>2.2.4.6</AssemblyVersion>
<FileVersion>2.2.4.6</FileVersion>
<AssemblyVersion>2.2.4.7</AssemblyVersion>
<FileVersion>2.2.4.7</FileVersion>
</PropertyGroup>
<ItemGroup>

View File

@ -286,6 +286,8 @@ namespace IW4MAdmin.Application
foreach (var serverConfig in config.Servers)
{
Migration.ConfigurationMigration.ModifyLogPath020919(serverConfig);
if (serverConfig.RConParserVersion == null || serverConfig.EventParserVersion == null)
{
foreach (var parser in AdditionalRConParsers)
@ -299,8 +301,8 @@ namespace IW4MAdmin.Application
}
serverConfig.ModifyParsers();
await ConfigHandler.Save();
}
await ConfigHandler.Save();
}
}

View File

@ -17,26 +17,26 @@ namespace IW4MAdmin.Application.EventParsers
GameDirectory = "main",
};
Configuration.Say.Pattern = @"^(say|sayteam);(.{8,32});([0-9]+);(.+);(.*)$";
Configuration.Say.Pattern = @"^(say|sayteam);(-?[A-Fa-f0-9_]{8,32});([0-9]+);(.+);(.*)$";
Configuration.Say.AddMapping(ParserRegex.GroupType.EventType, 1);
Configuration.Say.AddMapping(ParserRegex.GroupType.OriginNetworkId, 2);
Configuration.Say.AddMapping(ParserRegex.GroupType.OriginClientNumber, 3);
Configuration.Say.AddMapping(ParserRegex.GroupType.OriginName, 4);
Configuration.Say.AddMapping(ParserRegex.GroupType.Message, 5);
Configuration.Quit.Pattern = @"^(Q);(.{8,32}|bot[0-9]+);([0-9]+);(.*)$";
Configuration.Quit.Pattern = @"^(Q);(-?[A-Fa-f0-9_]{8,32}|bot[0-9]+);([0-9]+);(.*)$";
Configuration.Quit.AddMapping(ParserRegex.GroupType.EventType, 1);
Configuration.Quit.AddMapping(ParserRegex.GroupType.OriginNetworkId, 2);
Configuration.Quit.AddMapping(ParserRegex.GroupType.OriginClientNumber, 3);
Configuration.Quit.AddMapping(ParserRegex.GroupType.OriginName, 4);
Configuration.Join.Pattern = @"^(J);(.{8,32}|bot[0-9]+);([0-9]+);(.*)$";
Configuration.Join.Pattern = @"^(J);(-?[A-Fa-f0-9_]{8,32}|bot[0-9]+);([0-9]+);(.*)$";
Configuration.Join.AddMapping(ParserRegex.GroupType.EventType, 1);
Configuration.Join.AddMapping(ParserRegex.GroupType.OriginNetworkId, 2);
Configuration.Join.AddMapping(ParserRegex.GroupType.OriginClientNumber, 3);
Configuration.Join.AddMapping(ParserRegex.GroupType.OriginName, 4);
Configuration.Damage.Pattern = @"^(D);([A-Fa-f0-9_]{8,32}|bot[0-9]+);(-?[0-9]+);(axis|allies|world);(.{1,24});([A-Fa-f0-9_]{8,32}|bot[0-9]+)?;-?([0-9]+);(axis|allies|world);(.{1,24})?;((?:[0-9]+|[a-z]+|_)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$";
Configuration.Damage.Pattern = @"^(D);(-?[A-Fa-f0-9_]{8,32}|bot[0-9]+);(-?[0-9]+);(axis|allies|world);(.{1,24});(-?[A-Fa-f0-9_]{8,32}|bot[0-9]+)?;-?([0-9]+);(axis|allies|world);(.{1,24})?;((?:[0-9]+|[a-z]+|_)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$";
Configuration.Damage.AddMapping(ParserRegex.GroupType.EventType, 1);
Configuration.Damage.AddMapping(ParserRegex.GroupType.TargetNetworkId, 2);
Configuration.Damage.AddMapping(ParserRegex.GroupType.TargetClientNumber, 3);
@ -51,7 +51,7 @@ namespace IW4MAdmin.Application.EventParsers
Configuration.Damage.AddMapping(ParserRegex.GroupType.MeansOfDeath, 12);
Configuration.Damage.AddMapping(ParserRegex.GroupType.HitLocation, 13);
Configuration.Kill.Pattern = @"^(K);([A-Fa-f0-9_]{8,32}|bot[0-9]+);(-?[0-9]+);(axis|allies|world);(.{1,24});([A-Fa-f0-9_]{8,32}|bot[0-9]+)?;-?([0-9]+);(axis|allies|world);(.{1,24})?;((?:[0-9]+|[a-z]+|_)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$";
Configuration.Kill.Pattern = @"^(K);(-?[A-Fa-f0-9_]{8,32}|bot[0-9]+);(-?[0-9]+);(axis|allies|world);(.{1,24});(-?[A-Fa-f0-9_]{8,32}|bot[0-9]+)?;-?([0-9]+);(axis|allies|world);(.{1,24})?;((?:[0-9]+|[a-z]+|_)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$";
Configuration.Kill.AddMapping(ParserRegex.GroupType.EventType, 1);
Configuration.Kill.AddMapping(ParserRegex.GroupType.TargetNetworkId, 2);
Configuration.Kill.AddMapping(ParserRegex.GroupType.TargetClientNumber, 3);

View File

@ -19,19 +19,10 @@ namespace IW4MAdmin.Application.IO
public string ServerId { get; set; }
}
public GameLogEventDetection(Server server, string gameLogPath, string gameLogName)
public GameLogEventDetection(Server server, string gameLogPath, Uri gameLogServerUri)
{
GameLogFile = gameLogPath;
// todo: abtract this more
if (gameLogPath.StartsWith("http"))
{
Reader = new GameLogReaderHttp(gameLogPath, server.EventParser);
}
else
{
Reader = new GameLogReader(gameLogPath, server.EventParser);
}
Reader = gameLogServerUri != null ? new GameLogReaderHttp(gameLogServerUri, gameLogPath, server.EventParser) : Reader = new GameLogReader(gameLogPath, server.EventParser);
Server = server;
}

View File

@ -17,13 +17,13 @@ namespace IW4MAdmin.Application.IO
{
readonly IEventParser Parser;
readonly IGameLogServer Api;
readonly string LogFile;
readonly string logPath;
public GameLogReaderHttp(string logFile, IEventParser parser)
public GameLogReaderHttp(Uri gameLogServerUri, string logPath, IEventParser parser)
{
LogFile = logFile;
this.logPath = logPath.ToBase64UrlSafeString(); ;
Parser = parser;
Api = RestClient.For<IGameLogServer>(logFile);
Api = RestClient.For<IGameLogServer>(gameLogServerUri);
}
public long Length => -1;
@ -36,12 +36,12 @@ namespace IW4MAdmin.Application.IO
server.Logger.WriteDebug($"Begin reading from http log");
#endif
var events = new List<GameEvent>();
string b64Path = server.LogPath.ToBase64UrlSafeString();
string b64Path = logPath;
var response = await Api.Log(b64Path);
if (!response.Success)
{
server.Logger.WriteError($"Could not get log server info of {LogFile}/{b64Path} ({server.LogPath})");
server.Logger.WriteError($"Could not get log server info of {logPath}/{b64Path} ({server.LogPath})");
return events;
}

View File

@ -750,47 +750,36 @@ namespace IW4MAdmin
}
CustomCallback = await ScriptLoaded();
string mainPath = EventParser.Configuration.GameDirectory;
string logPath = string.Empty;
LogPath = string.IsNullOrEmpty(game) ?
$"{basepath?.Value?.Replace('\\', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{mainPath}{Path.DirectorySeparatorChar}{logfile?.Value}" :
$"{basepath?.Value?.Replace('\\', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{game?.Replace('/', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{logfile?.Value}";
bool remoteLog = false;
if (GameName == Game.IW5 || ServerConfig.ManualLogPath?.Length > 0)
// they've manually specified the log path
if (!string.IsNullOrEmpty(ServerConfig.ManualLogPath))
{
logPath = ServerConfig.ManualLogPath;
remoteLog = logPath.StartsWith("http");
}
else
{
logPath = LogPath;
}
if (remoteLog)
{
LogEvent = new GameLogEventDetection(this, logPath, logfile.Value);
LogPath = ServerConfig.ManualLogPath;
}
else
{
string mainPath = EventParser.Configuration.GameDirectory;
LogPath = string.IsNullOrEmpty(game) ?
$"{basepath?.Value?.Replace('\\', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{mainPath}{Path.DirectorySeparatorChar}{logfile?.Value}" :
$"{basepath?.Value?.Replace('\\', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{game?.Replace('/', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{logfile?.Value}";
// fix wine drive name mangling
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
logPath = Regex.Replace($"{Path.DirectorySeparatorChar}{LogPath}", @"[A-Z]:/", "");
LogPath = Regex.Replace($"{Path.DirectorySeparatorChar}{LogPath}", @"[A-Z]:/", "");
}
if (!File.Exists(logPath))
if (!File.Exists(LogPath))
{
Logger.WriteError($"{logPath} {loc["SERVER_ERROR_DNE"]}");
throw new ServerException($"{loc["SERVER_ERROR_LOG"]} {logPath}");
Logger.WriteError($"{LogPath} {loc["SERVER_ERROR_DNE"]}");
throw new ServerException($"{loc["SERVER_ERROR_LOG"]} {LogPath}");
}
LogEvent = new GameLogEventDetection(this, logPath, logfile.Value);
}
Logger.WriteInfo($"Log file is {logPath}");
LogEvent = new GameLogEventDetection(this, LogPath, ServerConfig.GameLogServerUrl);
Logger.WriteInfo($"Log file is {LogPath}");
_ = Task.Run(() => LogEvent.PollForChanges());
#if !DEBUG

View File

@ -56,5 +56,14 @@ namespace IW4MAdmin.Application.Migration
}
}
}
public static void ModifyLogPath020919(SharedLibraryCore.Configuration.ServerConfiguration config)
{
if (config.ManualLogPath.IsRemoteLog())
{
config.GameLogServerUrl = new Uri(config.ManualLogPath);
config.ManualLogPath = null;
}
}
}
}

View File

@ -100,7 +100,7 @@ namespace IW4MAdmin.Application.RconParsers
public async Task<List<EFClient>> GetStatusAsync(Connection connection)
{
string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, "status");
string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND_STATUS);
return ClientsFromStatus(response);
}

View File

@ -11,13 +11,15 @@
<SearchPath>
</SearchPath>
<WorkingDirectory>.</WorkingDirectory>
<LaunchProvider>Web launcher</LaunchProvider>
<LaunchProvider>Standard Python launcher</LaunchProvider>
<WebBrowserUrl>http://localhost</WebBrowserUrl>
<OutputPath>.</OutputPath>
<SuppressCollectPythonCloudServiceFiles>true</SuppressCollectPythonCloudServiceFiles>
<Name>GameLogServer</Name>
<RootNamespace>GameLogServer</RootNamespace>
<InterpreterId>MSBuild|env|$(MSBuildProjectFullPath)</InterpreterId>
<EnableNativeCodeDebugging>False</EnableNativeCodeDebugging>
<Environment>DEBUG=True</Environment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>

View File

@ -15,7 +15,7 @@ class LogReader(object):
if re.search('r^.+\.\.\\.+$', path):
return False
# must be a valid log path and log file
if not re.search(r'^.+[\\|\/](userraw|mods|main)[\\|\/].+.log$', path):
if not re.search(r'^.+[\\|\/](.+)[\\|\/].+.log$', path):
return False
# set the initialze size to the current file size
file_size = 0

View File

@ -139,13 +139,14 @@ namespace IW4MAdmin.Plugins.Welcome
{
string response = await wc.DownloadStringTaskAsync(new Uri($"http://extreme-ip-lookup.com/json/{ip}"));
var responseObj = JObject.Parse(response);
response = responseObj["country"].ToString();
return responseObj["country"].ToString();
return string.IsNullOrEmpty(response) ? Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_WELCOME_UNKNOWN_COUNTRY"] : response;
}
catch
{
return "a third world country";
return Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_WELCOME_UNKNOWN_IP"];
}
}
}

View File

@ -16,6 +16,7 @@ namespace SharedLibraryCore.Configuration
public string RConParserVersion { get; set; }
public string EventParserVersion { get; set; }
public int ReservedSlotNumber { get; set; }
public Uri GameLogServerUrl { get; set; }
private readonly IList<IRConParser> rconParsers;
private readonly IList<IEventParser> eventParsers;

View File

@ -78,16 +78,14 @@ namespace SharedLibraryCore.RCon
byte[] payload = null;
bool waitForResponse = Config.WaitForResponse;
string converterEncoding(string text)
{
var destinationEncoding = Encoding.GetEncoding("windows-1252");
byte[] originalEncodedBytes = Utilities.EncodingType.GetBytes(text);
byte[] convertedBytes = Encoding.Convert(Utilities.EncodingType, destinationEncoding, originalEncodedBytes);
return destinationEncoding.GetString(convertedBytes);
string convertEncoding(string text)
{
byte[] convertedBytes = Utilities.EncodingType.GetBytes(text);
return Utilities.EncodingType.GetString(convertedBytes);
}
string convertedRConPassword = converterEncoding(RConPassword);
string convertedParameters = converterEncoding(parameters);
string convertedRConPassword = convertEncoding(RConPassword);
string convertedParameters = convertEncoding(parameters);
switch (type)
{
@ -109,6 +107,10 @@ namespace SharedLibraryCore.RCon
waitForResponse |= true;
payload = (Config.CommandPrefixes.RConGetInfo + '\0').Select(Convert.ToByte).ToArray();
break;
case StaticHelpers.QueryType.COMMAND_STATUS:
waitForResponse |= true;
payload = string.Format(Config.CommandPrefixes.RConCommand, convertedRConPassword, "status\0").Select(Convert.ToByte).ToArray();
break;
}
byte[] response = null;

View File

@ -35,6 +35,11 @@ namespace SharedLibraryCore.RCon
/// RCon password is required
/// </summary>
COMMAND,
/// <summary>
/// get the full server command information
/// RCon password is required
/// </summary>
COMMAND_STATUS
}
/// <summary>

View File

@ -266,11 +266,16 @@ namespace SharedLibraryCore
public static long ConvertLong(this string str)
{
str = str.Substring(0, Math.Min(str.Length, 16));
if (Int64.TryParse(str, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out long id))
if (long.TryParse(str, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out long id))
{
return id;
}
if (long.TryParse(str, NumberStyles.Integer, CultureInfo.InvariantCulture, out id))
{
return (uint)id;
}
var bot = Regex.Match(str, @"bot[0-9]+").Value;
if (!string.IsNullOrEmpty(bot))
{
@ -640,6 +645,13 @@ namespace SharedLibraryCore
return cmdLine.Length > 1 ? cmdLine[1] : cmdLine[0];
}
/// <summary>
/// indicates if the given log path is a remote (http) uri
/// </summary>
/// <param name="log"></param>
/// <returns></returns>
public static bool IsRemoteLog(this string log) => (log ?? "").StartsWith("http");
public static string ToBase64UrlSafeString(this string src)
{
return Convert.ToBase64String(src.Select(c => Convert.ToByte(c)).ToArray()).Replace('+', '-').Replace('/', '_');