openrareplay 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,49 @@
1
+ # OpenRA Replay
2
+ > Copyright (C) 2018 Luke Spangler
3
+ >
4
+ > This program is free software: you can redistribute it and/or modify
5
+ > it under the terms of the GNU Affero General Public License as
6
+ > published by the Free Software Foundation, either version 3 of the
7
+ > License, or (at your option) any later version.
8
+ >
9
+ > This program is distributed in the hope that it will be useful,
10
+ > but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ > MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ > GNU Affero General Public License for more details.
13
+
14
+ ## Description
15
+ A library and executable that can parse OpenRA replay files and produce "sanitized" versions, without pings, exact timestamps, or other unnecessary information. The long term goal is to produce a full gem project packaging both a library and an executable for reading and writing to OpenRA replay files. However, the library will never support parsing non-YAML data beyond preserving it as a chunk. Examples of non-YAML data includes unit and building orders.
16
+
17
+ ## Requirements:
18
+ A relatively recent version of Ruby.
19
+
20
+ ## Installation:
21
+ ```
22
+ gem install openrareplay
23
+
24
+ ```
25
+
26
+ ## Usage:
27
+ ```
28
+ Usage: openra-sanitize [options] in_file out_file
29
+ Reads an OpenRA replay file, trims/masks it, and outputs the result as a new file
30
+
31
+ Specific options:
32
+ -p, --ping Trim all ping-related content
33
+ -m, --message Trim all server messages
34
+ -c, --chat Trim all chat messages
35
+ -i, --ip Trim all IP addresses
36
+ -t, --time Mask all dates and times
37
+ -P, --password Trims the server password
38
+ -n, --player-name Masks all player names
39
+ -s, --server-name Trim the server name
40
+ -f, --force Force overwriting out_file
41
+
42
+ Common options:
43
+ -h, --help Show this message
44
+ --version Show version
45
+ ```
46
+ Keep in mind that some options might not make sense without another. For instance, without removing server messages, player names would still be revealed in those messages.
47
+
48
+ ![Logo of the Affero General Public License](https://www.gnu.org/graphics/agplv3-155x51.png)
49
+
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # OpenRA Replay Sanitizer: Program/library to parse and generate
4
+ # OpenRA replay files
5
+ #
6
+ # Copyright (C) 2018 Luke Spangler
7
+ #
8
+ # This program is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU Affero General Public License as
10
+ # published by the Free Software Foundation, either version 3 of the
11
+ # License, or (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU Affero General Public License for more details.
17
+
18
+ # You should have received a copy of the GNU Affero General Public License
19
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
20
+
21
+ require 'bundler/gem_tasks'
22
+ require 'rake/testtask'
23
+
24
+ Rake::TestTask.new(:test) do |t|
25
+ t.libs << 'test'
26
+ t.libs << 'lib'
27
+ t.test_files = FileList['test/**/*_test.rb']
28
+ end
29
+
30
+ task default: :test
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # OpenRA Replay Sanitizer: Program/library to parse and generate
4
+ # OpenRA replay files
5
+ #
6
+ # Copyright (C) 2018 Luke Spangler
7
+ #
8
+ # This program is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU Affero General Public License as
10
+ # published by the Free Software Foundation, either version 3 of the
11
+ # License, or (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU Affero General Public License for more details.
17
+
18
+ # You should have received a copy of the GNU Affero General Public License
19
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
20
+
21
+ require 'openrareplay/sanitize/cli'
22
+
23
+ OpenRAReplay::Sanitize::CLI.new(ARGV).sanitize
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # OpenRA Replay Sanitizer: Program/library to parse and generate
4
+ # OpenRA replay files
5
+ #
6
+ # Copyright (C) 2018 Luke Spangler
7
+ #
8
+ # This program is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU Affero General Public License as
10
+ # published by the Free Software Foundation, either version 3 of the
11
+ # License, or (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU Affero General Public License for more details.
17
+
18
+ # You should have received a copy of the GNU Affero General Public License
19
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
20
+
21
+ require_relative 'openrareplay/version'
22
+ require_relative 'openrareplay/miniyaml'
23
+ require_relative 'openrareplay/binary'
24
+ require_relative 'openrareplay/order'
25
+ require_relative 'openrareplay/packet'
26
+ require_relative 'openrareplay/sanitize'
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # OpenRA Replay Sanitizer: Program/library to parse and generate
4
+ # OpenRA replay files
5
+ #
6
+ # Copyright (C) 2018 Luke Spangler
7
+ #
8
+ # This program is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU Affero General Public License as
10
+ # published by the Free Software Foundation, either version 3 of the
11
+ # License, or (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU Affero General Public License for more details.
17
+
18
+ # You should have received a copy of the GNU Affero General Public License
19
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
20
+
21
+ module OpenRAReplay
22
+ module Binary
23
+ def encode_uleb128(val)
24
+ bytes = ''.force_encoding('ASCII-8BIT')
25
+ loop do
26
+ byte = val & 0x7F
27
+ val >>= 7
28
+ byte |= 0x80 unless val.zero?
29
+ bytes += byte.chr
30
+ break if val.zero?
31
+ end
32
+ bytes
33
+ end
34
+
35
+ def decode_uleb128_io(input, hash = {})
36
+ val = 0
37
+ shift = 0
38
+ read_bytes = ''.force_encoding('ASCII-8BIT')
39
+ loop do
40
+ byte = input.read 1
41
+ read_bytes += byte if hash[:output_read]
42
+ byte = byte.ord
43
+ val |= (byte & 0x7F) << shift
44
+ break if (byte >> 7).zero?
45
+ shift += 7
46
+ end
47
+ return [val, read_bytes] if hash[:output_read]
48
+ val
49
+ end
50
+
51
+ def encode_u32(integer)
52
+ [integer].pack('_L')
53
+ end
54
+
55
+ def decode_u32(string)
56
+ string.unpack('_L').first
57
+ end
58
+
59
+ def decode_u8(string)
60
+ string.unpack('C').first
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # OpenRA Replay Sanitizer: Program/library to parse and generate
4
+ # OpenRA replay files
5
+ #
6
+ # Copyright (C) 2018 Luke Spangler
7
+ #
8
+ # This program is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU Affero General Public License as
10
+ # published by the Free Software Foundation, either version 3 of the
11
+ # License, or (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU Affero General Public License for more details.
17
+
18
+ # You should have received a copy of the GNU Affero General Public License
19
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
20
+
21
+ require 'psych'
22
+ require 'time'
23
+
24
+ module OpenRAReplay
25
+ module MiniYaml
26
+ def self.load(str)
27
+ thing = str.gsub("\t", ' ')
28
+ searches = []
29
+ thing.scan(/MapTitle: (.+?)\n/m).each do |match|
30
+ match = match.first
31
+ searches.append [
32
+ "MapTitle: #{match}\n",
33
+ "MapTitle: '#{match.gsub("'", "''")}'\n"
34
+ ]
35
+ end
36
+ thing.scan(/Name: (.+?)\n/m).each do |match|
37
+ match = match.first
38
+ searches.append ["Name: #{match}\n", "Name: '#{match.gsub("'", "''")}'\n"]
39
+ end
40
+ searches.each do |pair|
41
+ thing.gsub!(pair.first, pair.last)
42
+ end
43
+ (Psych.safe_load thing)
44
+ end
45
+
46
+ def self.dump(object)
47
+ thing = (Psych.dump object, indentation: 1)
48
+ .force_encoding('ASCII-8BIT').gsub(/^---\n/m, '')
49
+ .gsub(' ', "\t").gsub(': false', ': False')
50
+ .gsub(': true', ': True').gsub(": \n", ":\n")
51
+ searches = []
52
+ thing.scan(/: '(.+?)'\n/m).each do |match|
53
+ match = match.first
54
+ searches.append [
55
+ ": '#{match}'\n",
56
+ ": #{match.gsub("''", "'")}\n"
57
+ ]
58
+ end
59
+ thing.scan(/: "(.+?)"\n/m).each do |match|
60
+ match = match.first
61
+ searches.append [
62
+ ": \"#{match}\"\n",
63
+ ": #{match.gsub('\"', '"').gsub('\\\\', '\\')}\n"
64
+ ]
65
+ end
66
+ searches.each do |pair|
67
+ thing.gsub!(pair.first, pair.last)
68
+ end
69
+ thing
70
+ end
71
+
72
+ def self.load_time(str)
73
+ Time.strptime(str + ' UTC', '%Y-%m-%d %H-%M-%S %Z')
74
+ end
75
+
76
+ def self.dump_time(time)
77
+ time.utc.strftime('%Y-%m-%d %H-%M-%S')
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # OpenRA Replay Sanitizer: Program/library to parse and generate
4
+ # OpenRA replay files
5
+ #
6
+ # Copyright (C) 2018 Luke Spangler
7
+ #
8
+ # This program is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU Affero General Public License as
10
+ # published by the Free Software Foundation, either version 3 of the
11
+ # License, or (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU Affero General Public License for more details.
17
+
18
+ # You should have received a copy of the GNU Affero General Public License
19
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
20
+
21
+ require_relative 'order/order'
22
+ require_relative 'order/server'
23
+ require_relative 'order/client'
24
+ require_relative 'order/notanorder'
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # OpenRA Replay Sanitizer: Program/library to parse and generate
4
+ # OpenRA replay files
5
+ #
6
+ # Copyright (C) 2018 Luke Spangler
7
+ #
8
+ # This program is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU Affero General Public License as
10
+ # published by the Free Software Foundation, either version 3 of the
11
+ # License, or (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU Affero General Public License for more details.
17
+
18
+ # You should have received a copy of the GNU Affero General Public License
19
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
20
+
21
+ require_relative 'order'
22
+
23
+ module OpenRAReplay
24
+ class ClientOrder < Order
25
+ def self.construct(input)
26
+ command_length = decode_uleb128_io input
27
+ command = input.read(command_length)
28
+
29
+ # Credit to AMHOL for figuring out the structure
30
+ # of these orders
31
+ data = input.read(5) # subject id + flag
32
+ flags = decode_u8(data[-1])
33
+ if (flags & 1) == 1 # if the order has a target
34
+ data += input.read(1)
35
+ target_type = decode_u8(data[-1])
36
+ case target_type
37
+ when 1 # target is an actor
38
+ data += input.read(4) # actor_id
39
+ when 2 # target is the terrain
40
+ data += if (flags & 64) == 64 # target is a cell
41
+ input.read(13) # target x, y, layer,
42
+ # and subcell
43
+ else # target is not a cell
44
+ input.read(12) # pos x, y, and z
45
+ end
46
+ when 3 # target is a frozen actor
47
+ data += input.read(8) # player actor id + frozen actor id
48
+ end
49
+ end
50
+ if (flags & 4) == 4 # has target string
51
+ strlen, out = decode_uleb128_io input, output_read: true
52
+ data += out + input.read(strlen)
53
+ end
54
+ if (flags & 16) == 16 # has extra location data
55
+ data += input.read(9) # extra x, y, and layer
56
+ end
57
+ if (flags & 32) == 32 # has extra data
58
+ data += input.read(4) # has extra data
59
+ end
60
+ new(command: command, data: data)
61
+ end
62
+
63
+ def serialize
64
+ (Order::CLIENT_COMMAND + encode_uleb128(command.length) +
65
+ command + data)
66
+ end
67
+
68
+ def client_order?
69
+ true
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # OpenRA Replay Sanitizer: Program/library to parse and generate
4
+ # OpenRA replay files
5
+ #
6
+ # Copyright (C) 2018 Luke Spangler
7
+ #
8
+ # This program is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU Affero General Public License as
10
+ # published by the Free Software Foundation, either version 3 of the
11
+ # License, or (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU Affero General Public License for more details.
17
+
18
+ # You should have received a copy of the GNU Affero General Public License
19
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
20
+
21
+ require_relative 'order'
22
+
23
+ module OpenRAReplay
24
+ class NotAnOrder < Order
25
+ attr_reader :special_command
26
+
27
+ def initialize(*args)
28
+ @unknown = !!args.last[:special_command]
29
+ super(*args)
30
+ end
31
+
32
+ def self.construct(input, char, special_command)
33
+ new(
34
+ command: char,
35
+ data: input.read,
36
+ special_command: special_command
37
+ )
38
+ end
39
+
40
+ def serialize
41
+ (command + data)
42
+ end
43
+
44
+ def special_command?
45
+ special_command
46
+ end
47
+
48
+ def order?
49
+ false
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # OpenRA Replay Sanitizer: Program/library to parse and generate
4
+ # OpenRA replay files
5
+ #
6
+ # Copyright (C) 2018 Luke Spangler
7
+ #
8
+ # This program is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU Affero General Public License as
10
+ # published by the Free Software Foundation, either version 3 of the
11
+ # License, or (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU Affero General Public License for more details.
17
+
18
+ # You should have received a copy of the GNU Affero General Public License
19
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
20
+
21
+ require_relative '../binary'
22
+
23
+ module OpenRAReplay
24
+ class Order
25
+ extend Binary
26
+ include Binary
27
+
28
+ attr_reader :command, :data
29
+
30
+ SERVER_COMMAND = 254.chr.freeze
31
+ CLIENT_COMMAND = 255.chr.freeze
32
+ SPECIAL_COMMAND = 191.chr.freeze
33
+
34
+ def initialize(hash = {})
35
+ @command = hash[:command] || ''
36
+ @data = hash[:data] || ''
37
+ end
38
+
39
+ def self.construct(input)
40
+ char = input.read(1)
41
+ case char
42
+ when SERVER_COMMAND
43
+ return ServerOrder.construct(input)
44
+ when CLIENT_COMMAND
45
+ return ClientOrder.construct(input)
46
+ else
47
+ return NotAnOrder.construct(input, char, char == SPECIAL_COMMAND)
48
+ end
49
+ end
50
+
51
+ def serialize
52
+ ''
53
+ end
54
+
55
+ def to_s
56
+ "<#{self.class.name} command: #{command} data: #{data}>"
57
+ end
58
+
59
+ def server_order?
60
+ false
61
+ end
62
+
63
+ def client_order?
64
+ false
65
+ end
66
+
67
+ def unknown?
68
+ false
69
+ end
70
+
71
+ def special_command?
72
+ false
73
+ end
74
+
75
+ def order?
76
+ true
77
+ end
78
+
79
+ alias is_fe? server_order?
80
+ alias is_ff? client_order?
81
+ end
82
+ end
83
+
84
+ require_relative 'client'
85
+ require_relative 'server'
86
+ require_relative 'notanorder'