steam_codec 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +1 -0
- data/Rakefile +1 -0
- data/lib/steam_codec.rb +1 -0
- data/lib/steam_codec/acf.rb +2 -1
- data/lib/steam_codec/key_values.rb +26 -0
- data/lib/steam_codec/value_array.rb +1 -0
- data/lib/steam_codec/vdf.rb +1 -0
- data/lib/steam_codec/version.rb +2 -1
- data/spec/acf_spec.rb +138 -137
- data/spec/key_values_spec.rb +215 -178
- data/spec/spec_helper.rb +5 -4
- data/spec/vdf_spec.rb +137 -136
- data/steam_codec.gemspec +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93fd1b633432abfc06e6bb11aec0df481b4e366e
|
4
|
+
data.tar.gz: 89a9ca4cb5975b3abcbf0c6e818f61cf333bdbfe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b28226526d56a91911f058ed1be3a397825851cf41cef6700f212891dd2fa033896d6c8a52eeb84d910dcfff83a62995e345317528ca7b7e5edfb4e295c5cbb3
|
7
|
+
data.tar.gz: fb81d45dc2484c102e704024fad68014aed5115ada853d8fb9da4c632657c9e82431e0ff87db9c3d59bb615e2c3a2c9d4347fbf10623e25dff5992851d1230ce
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -62,6 +62,7 @@ code coverage will also be generated
|
|
62
62
|
[](https://travis-ci.org/davispuh/SteamCodec)
|
63
63
|
[](https://gemnasium.com/davispuh/SteamCodec)
|
64
64
|
[](https://coveralls.io/r/davispuh/SteamCodec)
|
65
|
+
[](https://codeclimate.com/github/davispuh/SteamCodec)
|
65
66
|
|
66
67
|
## Unlicense
|
67
68
|
|
data/Rakefile
CHANGED
data/lib/steam_codec.rb
CHANGED
data/lib/steam_codec/acf.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
module SteamCodec
|
2
3
|
class ACF
|
3
4
|
|
@@ -82,7 +83,7 @@ module SteamCodec
|
|
82
83
|
@UserConfig = userConfig
|
83
84
|
@Name = @UserConfig.name if @UserConfig.key?(:name)
|
84
85
|
@GameID = @UserConfig.gameid.to_i if @UserConfig.key?(:gameid)
|
85
|
-
@Installed = !@UserConfig.
|
86
|
+
@Installed = !@UserConfig.installed.to_i.zero? if @UserConfig.key?(:installed)
|
86
87
|
@AppInstallDir = @UserConfig.appinstalldir if @UserConfig.key?(:appinstalldir)
|
87
88
|
@Language = @UserConfig.language if @UserConfig.key?(:language)
|
88
89
|
@BetaKey = @UserConfig.BetaKey if @UserConfig.key?(:BetaKey)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
require 'json'
|
2
3
|
require 'insensitive_hash/minimal'
|
3
4
|
|
@@ -103,6 +104,31 @@ module SteamCodec
|
|
103
104
|
self.loadFromJSON(json)
|
104
105
|
end
|
105
106
|
|
107
|
+
def get(path = '')
|
108
|
+
fields = path.gsub(/^\/|\/$/, '').split('/')
|
109
|
+
current = self
|
110
|
+
fields.each do |name|
|
111
|
+
return nil if not current.key?(name)
|
112
|
+
current = current[name]
|
113
|
+
end
|
114
|
+
current
|
115
|
+
end
|
116
|
+
|
117
|
+
def asArray(name, seperator = '_')
|
118
|
+
data = []
|
119
|
+
counter = 0
|
120
|
+
cname = name+seperator+counter.to_s
|
121
|
+
data << self[cname] if key?(cname)
|
122
|
+
counter += 1
|
123
|
+
cname = name+seperator+counter.to_s
|
124
|
+
while key?(cname) do
|
125
|
+
data << self[cname]
|
126
|
+
counter += 1
|
127
|
+
cname = name+seperator+counter.to_s
|
128
|
+
end
|
129
|
+
data
|
130
|
+
end
|
131
|
+
|
106
132
|
def method_missing(name, *args, &block) # :nodoc:
|
107
133
|
return self[name] if args.empty? and block.nil? and key?(name)
|
108
134
|
super
|
data/lib/steam_codec/vdf.rb
CHANGED
data/lib/steam_codec/version.rb
CHANGED
data/spec/acf_spec.rb
CHANGED
@@ -1,137 +1,138 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
"
|
10
|
-
"
|
11
|
-
"
|
12
|
-
"
|
13
|
-
"
|
14
|
-
"
|
15
|
-
"
|
16
|
-
"
|
17
|
-
"
|
18
|
-
"
|
19
|
-
"
|
20
|
-
"
|
21
|
-
|
22
|
-
|
23
|
-
"
|
24
|
-
"
|
25
|
-
"
|
26
|
-
"
|
27
|
-
"
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
"
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
"
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
"
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
SteamCodec::ACF::MountedDepots.new.
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
SteamCodec::ACF::MountedDepots.new(depots).
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
SteamCodec::ACF::SharedDepots.new(depots).
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe SteamCodec::ACF do
|
5
|
+
|
6
|
+
let(:appCacheFile) { <<-EOS
|
7
|
+
"AppState"
|
8
|
+
{
|
9
|
+
"appid" "207930"
|
10
|
+
"Universe" "1"
|
11
|
+
"StateFlags" "4"
|
12
|
+
"installdir" "sacred_citadel"
|
13
|
+
"LastUpdated" "1377100000"
|
14
|
+
"UpdateResult" "0"
|
15
|
+
"SizeOnDisk" "1193761500"
|
16
|
+
"buildid" "60250"
|
17
|
+
"LastOwner" "0"
|
18
|
+
"BytesToDownload" "0"
|
19
|
+
"BytesDownloaded" "0"
|
20
|
+
"FullValidateOnNextUpdate" "1"
|
21
|
+
"UserConfig"
|
22
|
+
{
|
23
|
+
"name" "Sacred Citadel"
|
24
|
+
"gameid" "207930"
|
25
|
+
"installed" "1"
|
26
|
+
"appinstalldir" "C:\\Steam\\steamapps\\common\\sacred_citadel"
|
27
|
+
"language" "english"
|
28
|
+
"BetaKey" "public"
|
29
|
+
}
|
30
|
+
"MountedDepots"
|
31
|
+
{
|
32
|
+
"228982" "6039653574073929574"
|
33
|
+
"228983" "4721092052804263356"
|
34
|
+
}
|
35
|
+
"SharedDepots"
|
36
|
+
{
|
37
|
+
"228984" "228980"
|
38
|
+
}
|
39
|
+
"checkguid"
|
40
|
+
{
|
41
|
+
"0" "Bin\\some.exe"
|
42
|
+
"1" "Bin\\another.exe"
|
43
|
+
}
|
44
|
+
"InstallScripts"
|
45
|
+
{
|
46
|
+
"0" "_CommonRedist\\vcredist\\2008\\installscript.vdf"
|
47
|
+
"1" "_CommonRedist\\vcredist\\2010\\installscript.vdf"
|
48
|
+
}
|
49
|
+
}
|
50
|
+
EOS
|
51
|
+
}
|
52
|
+
|
53
|
+
describe '.loadFromFile' do
|
54
|
+
it 'should successfully load from file' do
|
55
|
+
StringIO.open(appCacheFile) do |file|
|
56
|
+
SteamCodec::ACF::loadFromFile(file).should be_an_instance_of SteamCodec::ACF
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '.load' do
|
62
|
+
it 'should successfully load' do
|
63
|
+
SteamCodec::ACF::load(appCacheFile).should be_an_instance_of SteamCodec::ACF
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '.new' do
|
68
|
+
it 'should initialize new instance with empty fields' do
|
69
|
+
SteamCodec::ACF.new.AppID.should be_nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe '#InstallDir' do
|
74
|
+
it 'should return value' do
|
75
|
+
SteamCodec::ACF::load(appCacheFile).InstallDir.should eq("sacred_citadel")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe SteamCodec::ACF::UserConfig do
|
80
|
+
describe '.new' do
|
81
|
+
it 'should initialize new instance with empty fields' do
|
82
|
+
SteamCodec::ACF::UserConfig.new.Name.should be_nil
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should initialize new instance with provided fields' do
|
86
|
+
SteamCodec::ACF::UserConfig.new(SteamCodec::KeyValues[{"Name" => "Game"}]).Name.should eq("Game")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe SteamCodec::ACF::MountedDepots do
|
92
|
+
let(:depots) { {"228982" => "6039653574073929574"} }
|
93
|
+
describe '.new' do
|
94
|
+
it 'should initialize new instance with empty fields' do
|
95
|
+
SteamCodec::ACF::MountedDepots.new.depots.should eq([])
|
96
|
+
SteamCodec::ACF::MountedDepots.new.manifests.should eq([])
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should initialize new instance with provided fields' do
|
100
|
+
SteamCodec::ACF::MountedDepots.new(depots).depots.should eq([228982])
|
101
|
+
SteamCodec::ACF::MountedDepots.new(depots).manifests.should eq(["6039653574073929574"])
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe '#getManifest' do
|
106
|
+
it 'should return manifest' do
|
107
|
+
SteamCodec::ACF::MountedDepots.new(depots).getManifest(228982).should eq("6039653574073929574")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe '#getDepot' do
|
112
|
+
it 'should return depot' do
|
113
|
+
SteamCodec::ACF::MountedDepots.new(depots).getDepot("6039653574073929574").should eq(228982)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe SteamCodec::ACF::SharedDepots do
|
119
|
+
let(:depots) { {"228984" => "228980"} }
|
120
|
+
describe '.new' do
|
121
|
+
it 'should initialize new instance with empty fields' do
|
122
|
+
SteamCodec::ACF::SharedDepots.new.depots.should eq([])
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should initialize new instance with provided fields' do
|
126
|
+
SteamCodec::ACF::SharedDepots.new(depots).depots.should eq([228984])
|
127
|
+
SteamCodec::ACF::SharedDepots.new(depots).getDepot(228984).should eq(228980)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe '#getDepot' do
|
132
|
+
it 'should return depot' do
|
133
|
+
SteamCodec::ACF::SharedDepots.new(depots).getDepot(228984).should eq(228980)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
data/spec/key_values_spec.rb
CHANGED
@@ -1,179 +1,216 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
let(:
|
7
|
-
let(:
|
8
|
-
let(:
|
9
|
-
|
10
|
-
|
11
|
-
let(:
|
12
|
-
|
13
|
-
|
14
|
-
let(:
|
15
|
-
|
16
|
-
|
17
|
-
let(:
|
18
|
-
|
19
|
-
|
20
|
-
let(:
|
21
|
-
|
22
|
-
|
23
|
-
let(:
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
let(:
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
"
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
SteamCodec::KeyValues::Parser::isEscaped('
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
|
60
|
-
describe '.toJSON' do
|
61
|
-
it 'should convert correctly empty data' do
|
62
|
-
SteamCodec::KeyValues::Parser::toJSON('').should eq('{}')
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'should raise exception on invalid data' do
|
66
|
-
expect { SteamCodec::KeyValues::Parser::toJSON(nil) }.to raise_error(ArgumentError)
|
67
|
-
expect { SteamCodec::KeyValues::Parser::toJSON({}) }.to raise_error(ArgumentError)
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'should add colon after tokens' do
|
71
|
-
SteamCodec::KeyValues::Parser::toJSON(jsonSample1a).should eq("{#{tokenKeyQuoted}: #{tokenValueQuoted}}")
|
72
|
-
SteamCodec::KeyValues::Parser::toJSON(jsonSample1b).should eq("{#{tokenKeyQuoted}:\n{\t#{tokenKeyQuoted}:\t#{tokenValueQuoted}\n}}")
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'should add comma after entries' do
|
76
|
-
SteamCodec::KeyValues::Parser::toJSON(jsonSample2a).should eq("{#{tokenKeyQuoted}: #{tokenValueQuoted},\n#{tokenKeyQuoted}:\t#{tokenValueQuoted}}")
|
77
|
-
SteamCodec::KeyValues::Parser::toJSON(jsonSample2b).should eq("{#{tokenKeyQuoted}:\t{},\n#{tokenKeyQuoted}: #{tokenValueQuoted}}")
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'should regard slashes' do
|
81
|
-
SteamCodec::KeyValues::Parser::toJSON(jsonSample3a).should eq('{"Ke\\ty\\\\is": "Val\\nue\\\\\\""}')
|
82
|
-
SteamCodec::KeyValues::Parser::toJSON(jsonSample3b).should eq('{"Ke\\\\ty\\is\\\\": "te\\\\s\\\\n\\\\v\\"\\\\"}')
|
83
|
-
end
|
84
|
-
|
85
|
-
it 'should parse keys and values without quotes' do
|
86
|
-
SteamCodec::KeyValues::Parser::toJSON(jsonSample4a).should eq("{#{tokenKeyQuoted}: #{tokenValueQuoted}}")
|
87
|
-
SteamCodec::KeyValues::Parser::toJSON(jsonSample4b).should eq("{#{tokenKeyQuoted}:\n{\t#{tokenKeyQuoted}:\t#{tokenValueQuoted}\n}}")
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'should parse special cases' do
|
91
|
-
SteamCodec::KeyValues::Parser::toJSON(jsonSample5a).should eq("{\"abc\": \"lol this {weird string}\"}")
|
92
|
-
SteamCodec::KeyValues::Parser::toJSON(jsonSample5b).should eq("{\"\\\"really weird\\\"\\n{\\n\\\"string\\\" \\\"this is\\\"\\n}\":\n{\n\"string\": \"this is\"\n}}")
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'should ignore comments' do
|
96
|
-
SteamCodec::KeyValues::Parser::toJSON(jsonSample6a).should eq("{#{tokenKeyQuoted}:\n{\t#{tokenKeyQuoted}:\t#{tokenValueQuoted}\n}}")
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'should ignore #include and #base' do
|
100
|
-
SteamCodec::KeyValues::Parser::toJSON(jsonSample7a).should eq("{\n#{tokenKeyQuoted}:\n{\t#{tokenKeyQuoted}:\t#{tokenValueQuoted}\n}}")
|
101
|
-
SteamCodec::KeyValues::Parser::toJSON(jsonSample7b).should eq("{\n#{tokenKeyQuoted}:\n{\t#{tokenKeyQuoted}:\t#{tokenValueQuoted}\n}}")
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe SteamCodec::KeyValues do
|
5
|
+
|
6
|
+
let(:tokenKey) { 'ToknKey123' }
|
7
|
+
let(:tokenValue) { 'Tokén+Value4567' }
|
8
|
+
let(:tokenKeyQuoted) { "\"#{tokenKey}\"" }
|
9
|
+
let(:tokenValueQuoted) { "\"#{tokenValue}\"" }
|
10
|
+
|
11
|
+
let(:jsonSample1a) { "#{tokenKeyQuoted} #{tokenValueQuoted}" }
|
12
|
+
let(:jsonSample1b) { "#{tokenKeyQuoted}\n{\t#{tokenKeyQuoted}\t#{tokenValueQuoted}\n}" }
|
13
|
+
|
14
|
+
let(:jsonSample2a) { "#{tokenKeyQuoted} #{tokenValueQuoted}\n#{tokenKeyQuoted}\t#{tokenValueQuoted}" }
|
15
|
+
let(:jsonSample2b) { "#{tokenKeyQuoted}\t{}\n#{tokenKeyQuoted} #{tokenValueQuoted}" }
|
16
|
+
|
17
|
+
let(:jsonSample3a) { '"Ke\\ty\\\\is" "Val\\nue\\\\\\""' }
|
18
|
+
let(:jsonSample3b) { '"Ke\\\\ty\\is\\\\" "te\\\\s\\\\n\\\\v\\"\\\\"' }
|
19
|
+
|
20
|
+
let(:jsonSample4a) { "#{tokenKey} #{tokenValue}" }
|
21
|
+
let(:jsonSample4b) { "#{tokenKey}\n{\t#{tokenKey}\t#{tokenValue}\n}" }
|
22
|
+
|
23
|
+
let(:jsonSample5a) { 'abc "lol this {weird string}"' }
|
24
|
+
let(:jsonSample5b) { "\"\\\"really weird\\\"\n{\n\\\"string\\\" \\\"this is\\\"\n}\"\n{\n\"string\" \"this is\"\n}" }
|
25
|
+
|
26
|
+
let(:jsonSample6a) { "#{tokenKeyQuoted}\\\\this should be ignored\n{\t#{tokenKeyQuoted}\t#{tokenValueQuoted}\n}" }
|
27
|
+
|
28
|
+
let(:jsonSample7a) { "#base <blah.vdf>\n#{tokenKey}\n{\t#{tokenKey}\t#{tokenValue}\n}" }
|
29
|
+
let(:jsonSample7b) { "#include <blah.vdf>\n#{tokenKey}\n{\t#{tokenKey}\t#{tokenValue}\n}" }
|
30
|
+
|
31
|
+
let(:keyValueData) { <<-EOS
|
32
|
+
"AppState"
|
33
|
+
{
|
34
|
+
"appid" "320"
|
35
|
+
"Universe" "1"
|
36
|
+
"SomeArrayValue_1" "4"
|
37
|
+
"SomeArrayValue_2" "3"
|
38
|
+
"SomeArrayValue_3" "2"
|
39
|
+
"UserConfig"
|
40
|
+
{
|
41
|
+
"name" "Brütal Legend"
|
42
|
+
}
|
43
|
+
}
|
44
|
+
EOS
|
45
|
+
}
|
46
|
+
|
47
|
+
let(:keyValueResult) {
|
48
|
+
{ 'appid' => '320', 'Universe' => '1', 'SomeArrayValue_1' => '4', 'SomeArrayValue_2' => '3', 'SomeArrayValue_3' => '2', 'UserConfig' => {'name' => 'Brütal Legend'} }
|
49
|
+
}
|
50
|
+
|
51
|
+
describe SteamCodec::KeyValues::Parser do
|
52
|
+
|
53
|
+
describe '.isEscaped' do
|
54
|
+
it 'empty string should not be escaped' do
|
55
|
+
SteamCodec::KeyValues::Parser::isEscaped('', 0).should be_false
|
102
56
|
end
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
end
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
57
|
+
|
58
|
+
it 'should be escaped' do
|
59
|
+
SteamCodec::KeyValues::Parser::isEscaped('\\"', 1).should be_true
|
60
|
+
SteamCodec::KeyValues::Parser::isEscaped('\\\\\\"', 3).should be_true
|
61
|
+
SteamCodec::KeyValues::Parser::isEscaped('trol\\lol\\lol\\"trrr', 13).should be_true
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should not be escaped' do
|
65
|
+
SteamCodec::KeyValues::Parser::isEscaped('\\\\"', 2).should be_false
|
66
|
+
SteamCodec::KeyValues::Parser::isEscaped('\\\\\\\\"', 4).should be_false
|
67
|
+
SteamCodec::KeyValues::Parser::isEscaped('trol\\lol\\lol\\\\"trrr', 14).should be_false
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '.toJSON' do
|
73
|
+
it 'should convert correctly empty data' do
|
74
|
+
SteamCodec::KeyValues::Parser::toJSON('').should eq('{}')
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should raise exception on invalid data' do
|
78
|
+
expect { SteamCodec::KeyValues::Parser::toJSON(nil) }.to raise_error(ArgumentError)
|
79
|
+
expect { SteamCodec::KeyValues::Parser::toJSON({}) }.to raise_error(ArgumentError)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should add colon after tokens' do
|
83
|
+
SteamCodec::KeyValues::Parser::toJSON(jsonSample1a).should eq("{#{tokenKeyQuoted}: #{tokenValueQuoted}}")
|
84
|
+
SteamCodec::KeyValues::Parser::toJSON(jsonSample1b).should eq("{#{tokenKeyQuoted}:\n{\t#{tokenKeyQuoted}:\t#{tokenValueQuoted}\n}}")
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should add comma after entries' do
|
88
|
+
SteamCodec::KeyValues::Parser::toJSON(jsonSample2a).should eq("{#{tokenKeyQuoted}: #{tokenValueQuoted},\n#{tokenKeyQuoted}:\t#{tokenValueQuoted}}")
|
89
|
+
SteamCodec::KeyValues::Parser::toJSON(jsonSample2b).should eq("{#{tokenKeyQuoted}:\t{},\n#{tokenKeyQuoted}: #{tokenValueQuoted}}")
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should regard slashes' do
|
93
|
+
SteamCodec::KeyValues::Parser::toJSON(jsonSample3a).should eq('{"Ke\\ty\\\\is": "Val\\nue\\\\\\""}')
|
94
|
+
SteamCodec::KeyValues::Parser::toJSON(jsonSample3b).should eq('{"Ke\\\\ty\\is\\\\": "te\\\\s\\\\n\\\\v\\"\\\\"}')
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should parse keys and values without quotes' do
|
98
|
+
SteamCodec::KeyValues::Parser::toJSON(jsonSample4a).should eq("{#{tokenKeyQuoted}: #{tokenValueQuoted}}")
|
99
|
+
SteamCodec::KeyValues::Parser::toJSON(jsonSample4b).should eq("{#{tokenKeyQuoted}:\n{\t#{tokenKeyQuoted}:\t#{tokenValueQuoted}\n}}")
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should parse special cases' do
|
103
|
+
SteamCodec::KeyValues::Parser::toJSON(jsonSample5a).should eq("{\"abc\": \"lol this {weird string}\"}")
|
104
|
+
SteamCodec::KeyValues::Parser::toJSON(jsonSample5b).should eq("{\"\\\"really weird\\\"\\n{\\n\\\"string\\\" \\\"this is\\\"\\n}\":\n{\n\"string\": \"this is\"\n}}")
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should ignore comments' do
|
108
|
+
SteamCodec::KeyValues::Parser::toJSON(jsonSample6a).should eq("{#{tokenKeyQuoted}:\n{\t#{tokenKeyQuoted}:\t#{tokenValueQuoted}\n}}")
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'should ignore #include and #base' do
|
112
|
+
SteamCodec::KeyValues::Parser::toJSON(jsonSample7a).should eq("{\n#{tokenKeyQuoted}:\n{\t#{tokenKeyQuoted}:\t#{tokenValueQuoted}\n}}")
|
113
|
+
SteamCodec::KeyValues::Parser::toJSON(jsonSample7b).should eq("{\n#{tokenKeyQuoted}:\n{\t#{tokenKeyQuoted}:\t#{tokenValueQuoted}\n}}")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe '.loadFromJSON' do
|
119
|
+
it 'should return nil for invalid json' do
|
120
|
+
SteamCodec::KeyValues::loadFromJSON('invalid :P').should be_nil
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe '.load' do
|
125
|
+
it 'should load correctly empty data' do
|
126
|
+
SteamCodec::KeyValues::load('').should eq({})
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should raise exception on invalid data' do
|
130
|
+
expect { SteamCodec::KeyValues::load(nil) }.to raise_error(ArgumentError)
|
131
|
+
expect { SteamCodec::KeyValues::load({}) }.to raise_error(ArgumentError)
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should load correctly various representations' do
|
135
|
+
SteamCodec::KeyValues::load(jsonSample1a).should eq({ tokenKey => tokenValue })
|
136
|
+
SteamCodec::KeyValues::load(jsonSample1b).should eq({ tokenKey => { tokenKey => tokenValue } })
|
137
|
+
SteamCodec::KeyValues::load(jsonSample2a).should eq({ tokenKey => tokenValue })
|
138
|
+
SteamCodec::KeyValues::load(jsonSample2b).should eq({ tokenKey => tokenValue })
|
139
|
+
SteamCodec::KeyValues::load(jsonSample3a).should eq({"Ke\ty\\is" => "Val\nue\\\""})
|
140
|
+
SteamCodec::KeyValues::load(jsonSample3b).should eq({'Ke\\tyis\\' => "te\\s\\n\\v\"\\"})
|
141
|
+
SteamCodec::KeyValues::load(jsonSample4a).should eq({ tokenKey => tokenValue })
|
142
|
+
SteamCodec::KeyValues::load(jsonSample4b).should eq({ tokenKey => { tokenKey => tokenValue } })
|
143
|
+
SteamCodec::KeyValues::load(jsonSample5a).should eq({"abc" => "lol this {weird string}"})
|
144
|
+
SteamCodec::KeyValues::load(jsonSample5b).should eq({"\"really weird\"\n{\n\"string\" \"this is\"\n}" => {"string" => "this is"}})
|
145
|
+
SteamCodec::KeyValues::load(jsonSample6a).should eq({ tokenKey => { tokenKey => tokenValue } })
|
146
|
+
SteamCodec::KeyValues::load(jsonSample7a).should eq({ tokenKey => { tokenKey => tokenValue } })
|
147
|
+
SteamCodec::KeyValues::load(jsonSample7b).should eq({ tokenKey => { tokenKey => tokenValue } })
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '.loadFromFile' do
|
152
|
+
it 'should raise exception if not file' do
|
153
|
+
expect { SteamCodec::KeyValues::loadFromFile("blah") }.to raise_error(ArgumentError)
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'should succesfully load from file' do
|
157
|
+
StringIO.open(keyValueData) do |file|
|
158
|
+
SteamCodec::KeyValues::loadFromFile(file).should eq({ "AppState" => keyValueResult })
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should be KeyValues instance' do
|
163
|
+
StringIO.open(keyValueData) do |file|
|
164
|
+
SteamCodec::KeyValues::loadFromFile(file).should be_an_instance_of SteamCodec::KeyValues
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe '#get' do
|
170
|
+
let(:keyValues) { SteamCodec::KeyValues::load(keyValueData) }
|
171
|
+
|
172
|
+
it 'should get field value' do
|
173
|
+
keyValues.get('AppState/AppID').should eq("320")
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'should get field value even with slashes at start and end' do
|
177
|
+
keyValues.get('/AppState/AppID/').should eq("320")
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should be nil if field doesn\'t exist' do
|
181
|
+
keyValues.get('AppState/Something').should be_nil
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe '#asArray' do
|
186
|
+
let(:keyValues) { SteamCodec::KeyValues::load(keyValueData) }
|
187
|
+
|
188
|
+
it 'should load fields as array' do
|
189
|
+
keyValues.AppState.asArray('SomeArrayValue').should eq(['4','3','2'])
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe 'access any field' do
|
194
|
+
let(:keyValues) { SteamCodec::KeyValues::load(keyValueData) }
|
195
|
+
|
196
|
+
it 'should be able to access AppState' do
|
197
|
+
keyValues.AppState.should eq(keyValueResult)
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'should be able to read AppID' do
|
201
|
+
keyValues.AppState.AppID.should eq("320")
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'should check if field exists' do
|
205
|
+
keyValues.AppState.has_key?(:AppID).should be_true
|
206
|
+
keyValues.AppState.has_key?(:StateFlags).should be_false
|
207
|
+
keyValues.respond_to?(:appstate).should be_true
|
208
|
+
keyValues.respond_to?(:nope).should be_false
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'should raise exception for non-existent field' do
|
212
|
+
expect { keyValues.AppState.StateFlags }.to raise_error(NoMethodError)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'simplecov'
|
3
|
+
|
4
|
+
SimpleCov.start
|
5
|
+
require_relative '../lib/steam_codec'
|
data/spec/vdf_spec.rb
CHANGED
@@ -1,136 +1,137 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
"
|
16
|
-
"
|
17
|
-
"
|
18
|
-
"
|
19
|
-
|
20
|
-
|
21
|
-
"
|
22
|
-
"
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
"
|
28
|
-
"
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
"
|
34
|
-
"
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
"
|
40
|
-
"
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
"
|
46
|
-
"
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
"
|
80
|
-
"
|
81
|
-
"
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
"
|
87
|
-
"
|
88
|
-
"
|
89
|
-
"
|
90
|
-
"
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
"
|
96
|
-
"
|
97
|
-
"
|
98
|
-
"
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
SteamCodec::VDF
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe SteamCodec::VDF do
|
5
|
+
|
6
|
+
let(:valveDataFile) { <<-EOS
|
7
|
+
"InstallScript"
|
8
|
+
{
|
9
|
+
"Registry"
|
10
|
+
{
|
11
|
+
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Activision\\Singularity"
|
12
|
+
{
|
13
|
+
"string"
|
14
|
+
{
|
15
|
+
"EXEString" "%INSTALLDIR%\\Binaries\\Singularity.exe"
|
16
|
+
"InstallPath" "%INSTALLDIR%"
|
17
|
+
"IntVersion" "35.0"
|
18
|
+
"Version" "1.0"
|
19
|
+
"english"
|
20
|
+
{
|
21
|
+
"Language" "1033"
|
22
|
+
"LanguageCode" "ENU"
|
23
|
+
"Localization" "ENU"
|
24
|
+
}
|
25
|
+
"french"
|
26
|
+
{
|
27
|
+
"Language" "1036"
|
28
|
+
"LanguageCode" "FRA"
|
29
|
+
"Localization" "FRA"
|
30
|
+
}
|
31
|
+
"german"
|
32
|
+
{
|
33
|
+
"Language" "1031"
|
34
|
+
"LanguageCode" "DEU"
|
35
|
+
"Localization" "DEU"
|
36
|
+
}
|
37
|
+
"italian"
|
38
|
+
{
|
39
|
+
"Language" "1040"
|
40
|
+
"LanguageCode" "ITA"
|
41
|
+
"Localization" "ITA"
|
42
|
+
}
|
43
|
+
"spanish"
|
44
|
+
{
|
45
|
+
"Language" "1034"
|
46
|
+
"LanguageCode" "ESP"
|
47
|
+
"Localization" "ESP"
|
48
|
+
}
|
49
|
+
}
|
50
|
+
"dword"
|
51
|
+
{
|
52
|
+
"english"
|
53
|
+
{
|
54
|
+
"GameLanguage" "0"
|
55
|
+
}
|
56
|
+
"french"
|
57
|
+
{
|
58
|
+
"GameLanguage" "1"
|
59
|
+
}
|
60
|
+
"german"
|
61
|
+
{
|
62
|
+
"GameLanguage" "0"
|
63
|
+
}
|
64
|
+
"italian"
|
65
|
+
{
|
66
|
+
"GameLanguage" "2"
|
67
|
+
}
|
68
|
+
"spanish"
|
69
|
+
{
|
70
|
+
"GameLanguage" "4"
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
}
|
75
|
+
"Run Process"
|
76
|
+
{
|
77
|
+
"DirectX"
|
78
|
+
{
|
79
|
+
"process 1" "%INSTALLDIR%\\redist\\DirectX\\DXSETUP.exe"
|
80
|
+
"command 1" "/silent"
|
81
|
+
"Description" "DirectX Installation"
|
82
|
+
"NoCleanUp" "1"
|
83
|
+
}
|
84
|
+
"VC++"
|
85
|
+
{
|
86
|
+
"process 1" "%INSTALLDIR%\\redist\\vcredist_x86.exe"
|
87
|
+
"command 1" "/q:a"
|
88
|
+
"process 2" "%INSTALLDIR%\\redist\\vcredist_x86_2005.exe"
|
89
|
+
"command 2" "/q:a"
|
90
|
+
"Description" "VC++ Redist Installation"
|
91
|
+
"NoCleanUp" "1"
|
92
|
+
}
|
93
|
+
"PhysX Version"
|
94
|
+
{
|
95
|
+
"HasRunKey" "HKEY_LOCAL_MACHINE\\SOFTWARE\\AGEIA Technologies"
|
96
|
+
"process 1" "%INSTALLDIR%\\redist\\PhysX_9.09.1112_SystemSoftware.exe"
|
97
|
+
"command 1" "/quiet"
|
98
|
+
"NoCleanUp" "1"
|
99
|
+
"MinimumHasRunValue" "9091112"
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
"kvsignatures"
|
104
|
+
{
|
105
|
+
"InstallScript" "973f7d89125ad1fc782a970deb175cf84d48c49581ba3a76fedfefa8116a6d500459fd8df99285850ef99d767a83c2de009de5951607930557c937439908fbc1cc8156e963320c54080e7a1a634ccbf2e5f58883bd11bb2ed10c07be5af8e482d9a17d22a6fe40980124e5fced1c241f158b460941984c41432eeeb2aeaa01b1"
|
106
|
+
}
|
107
|
+
EOS
|
108
|
+
}
|
109
|
+
|
110
|
+
describe '.loadFromFile' do
|
111
|
+
it 'should successfully load from file' do
|
112
|
+
StringIO.open(valveDataFile) do |file|
|
113
|
+
SteamCodec::VDF::loadFromFile(file).should be_an_instance_of SteamCodec::VDF
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe '.load' do
|
119
|
+
it 'should successfully load' do
|
120
|
+
SteamCodec::VDF::load(valveDataFile).should be_an_instance_of SteamCodec::VDF
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe 'key field' do
|
125
|
+
it 'should return value' do
|
126
|
+
SteamCodec::VDF::load(valveDataFile).InstallScript.Registry.should be_an_instance_of SteamCodec::KeyValues
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe '#isSignaturesValid?' do
|
131
|
+
it 'should check if signature is valid' do
|
132
|
+
SteamCodec::VDF.new.isSignaturesValid?(nil).should be_true
|
133
|
+
SteamCodec::VDF::load(valveDataFile).isSignaturesValid?(nil).should be_false
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
data/steam_codec.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: steam_codec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dāvis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-09-
|
11
|
+
date: 2013-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: insensitive_hash
|