steam_codec 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Build Status](https://travis-ci.org/davispuh/SteamCodec.png?branch=master)](https://travis-ci.org/davispuh/SteamCodec)
|
63
63
|
[![Dependency Status](https://gemnasium.com/davispuh/SteamCodec.png)](https://gemnasium.com/davispuh/SteamCodec)
|
64
64
|
[![Coverage Status](https://coveralls.io/repos/davispuh/SteamCodec/badge.png)](https://coveralls.io/r/davispuh/SteamCodec)
|
65
|
+
[![Code Climate](https://codeclimate.com/github/davispuh/SteamCodec.png)](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
|