steam_codec 0.0.1
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 +7 -0
 - data/.gitignore +17 -0
 - data/.travis.yml +21 -0
 - data/.yardopts +1 -0
 - data/Gemfile +9 -0
 - data/README.md +90 -0
 - data/Rakefile +13 -0
 - data/UNLICENSE +24 -0
 - data/lib/steam_codec.rb +5 -0
 - data/lib/steam_codec/ACF.rb +176 -0
 - data/lib/steam_codec/key_values.rb +116 -0
 - data/lib/steam_codec/value_array.rb +45 -0
 - data/lib/steam_codec/vdf.rb +26 -0
 - data/lib/steam_codec/version.rb +3 -0
 - data/spec/acf_spec.rb +137 -0
 - data/spec/key_values_spec.rb +179 -0
 - data/spec/spec_helper.rb +4 -0
 - data/spec/vdf_spec.rb +136 -0
 - data/steam_codec.gemspec +27 -0
 - metadata +159 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: a20d0abedea3bf35bc7450fb8574604122eb1eb0
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 49112685b3c267451119b966912abe90fafd0e5f
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 04de7885b1804cd714e7e4e662b47628593f2b32af300d863f05856d6dbb24049cb7f0ced3c60e534a1c900c6bcae024dafa834f8dc8ac1e1518418c29fdb489
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: b0057fcefcf85748fe4d3fa4767eb3d44b05407727206b8a70e9e88c31dcd343179d1bf48d0ad595b9a75791211405ba73c3733255aa7302732d81132a142a14
         
     | 
    
        data/.gitignore
    ADDED
    
    
    
        data/.travis.yml
    ADDED
    
    | 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            language: ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            rvm:
         
     | 
| 
      
 3 
     | 
    
         
            +
              - 2.0.0
         
     | 
| 
      
 4 
     | 
    
         
            +
              - 1.9.3
         
     | 
| 
      
 5 
     | 
    
         
            +
              - jruby-19mode
         
     | 
| 
      
 6 
     | 
    
         
            +
              - rbx-19mode
         
     | 
| 
      
 7 
     | 
    
         
            +
              - ruby-head
         
     | 
| 
      
 8 
     | 
    
         
            +
              - jruby-head
         
     | 
| 
      
 9 
     | 
    
         
            +
            jdk:
         
     | 
| 
      
 10 
     | 
    
         
            +
              - oraclejdk7
         
     | 
| 
      
 11 
     | 
    
         
            +
              - openjdk7
         
     | 
| 
      
 12 
     | 
    
         
            +
            matrix:
         
     | 
| 
      
 13 
     | 
    
         
            +
              exclude:
         
     | 
| 
      
 14 
     | 
    
         
            +
                - rvm: 2.0.0
         
     | 
| 
      
 15 
     | 
    
         
            +
                  jdk: openjdk7
         
     | 
| 
      
 16 
     | 
    
         
            +
                - rvm: 1.9.3
         
     | 
| 
      
 17 
     | 
    
         
            +
                  jdk: openjdk7
         
     | 
| 
      
 18 
     | 
    
         
            +
                - rvm: rbx-19mode
         
     | 
| 
      
 19 
     | 
    
         
            +
                  jdk: openjdk7
         
     | 
| 
      
 20 
     | 
    
         
            +
                - rvm: ruby-head
         
     | 
| 
      
 21 
     | 
    
         
            +
                  jdk: openjdk7
         
     | 
    
        data/.yardopts
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --markup markdown
         
     | 
    
        data/Gemfile
    ADDED
    
    
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,90 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # SteamCodec
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            SteamCodec is a library for working with different [Steam client](http://store.steampowered.com/about/) (and [Source engine](http://source.valvesoftware.com/)) file formats.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Currently supported formats:
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            * [KeyValues](https://developer.valvesoftware.com/wiki/KeyValues)
         
     | 
| 
      
 8 
     | 
    
         
            +
            * VDF (Valve Data Format)
         
     | 
| 
      
 9 
     | 
    
         
            +
            * ACF (ApplicationCacheFile)
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            PKV (packed KeyValues) isn't supported yet.
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            ## Installation
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            Add this line to your application's Gemfile:
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 20 
     | 
    
         
            +
            gem 'steam_codec'
         
     | 
| 
      
 21 
     | 
    
         
            +
            ```
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            And then execute:
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            ```shell
         
     | 
| 
      
 26 
     | 
    
         
            +
            bundle
         
     | 
| 
      
 27 
     | 
    
         
            +
            ```
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            Or install it yourself as:
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            ```shell
         
     | 
| 
      
 32 
     | 
    
         
            +
            gem install SteamCodec
         
     | 
| 
      
 33 
     | 
    
         
            +
            ```
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            ### Dependencies
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            gem `insensitive_hash`
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            ## Usage
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 42 
     | 
    
         
            +
            require 'steam_codec'
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            File.open("appmanifest_220.acf") do |file|
         
     | 
| 
      
 45 
     | 
    
         
            +
                acf = SteamCodec::ACF::loadFromFile(file)
         
     | 
| 
      
 46 
     | 
    
         
            +
                puts acf.UserConfig.Name
         
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
| 
      
 48 
     | 
    
         
            +
            ```
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            ## Documentation
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            YARD with markdown is used for documentation (`redcarpet` required)
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            ## Specs
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            RSpec and simplecov are required, to run tests just `rake spec`
         
     | 
| 
      
 57 
     | 
    
         
            +
            code coverage will also be generated
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            ## Code status
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            [](https://travis-ci.org/davispuh/SteamCodec)
         
     | 
| 
      
 62 
     | 
    
         
            +
            [](https://gemnasium.com/davispuh/SteamCodec)
         
     | 
| 
      
 63 
     | 
    
         
            +
            [](https://coveralls.io/r/davispuh/SteamCodec)
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
            ## Unlicense
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            All text, documentation, code and files in this repository are in public domain (including this text, README).
         
     | 
| 
      
 70 
     | 
    
         
            +
            It means you can copy, modify, distribute and include in your own work/code, even for commercial purposes, all without asking permission.
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
            [About Unlicense](http://unlicense.org/)
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            ## Contributing
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
            Feel free to improve anything.
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
            1. Fork it
         
     | 
| 
      
 79 
     | 
    
         
            +
            2. Create your feature branch (`git checkout -b my-new-feature`)
         
     | 
| 
      
 80 
     | 
    
         
            +
            3. Commit your changes (`git commit -am 'Add some feature'`)
         
     | 
| 
      
 81 
     | 
    
         
            +
            4. Push to the branch (`git push origin my-new-feature`)
         
     | 
| 
      
 82 
     | 
    
         
            +
            5. Create new Pull Request
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            **Warning**: By sending pull request to this repository you dedicate any and all copyright interest in pull request (code files and all other) to the public domain. (files will be in public domain even if pull request doesn't get merged)
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
            Also before sending pull request you acknowledge that you own all copyrights or have authorization to dedicate them to public domain.
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
            If you don't want to dedicate code to public domain or if you're not allowed to (eg. you don't own required copyrights) then DON'T send pull request.
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "bundler/gem_tasks"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'rspec/core/rake_task'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'yard'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            desc 'Default: run specs.'
         
     | 
| 
      
 6 
     | 
    
         
            +
            task :default => :spec
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            desc 'Run specs'
         
     | 
| 
      
 9 
     | 
    
         
            +
            RSpec::Core::RakeTask.new(:spec) do |t|
         
     | 
| 
      
 10 
     | 
    
         
            +
            end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            YARD::Rake::YardocTask.new(:doc) do |t|
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
    
        data/UNLICENSE
    ADDED
    
    | 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            This is free and unencumbered software released into the public domain.
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Anyone is free to copy, modify, publish, use, compile, sell, or
         
     | 
| 
      
 4 
     | 
    
         
            +
            distribute this software, either in source code form or as a compiled
         
     | 
| 
      
 5 
     | 
    
         
            +
            binary, for any purpose, commercial or non-commercial, and by any
         
     | 
| 
      
 6 
     | 
    
         
            +
            means.
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            In jurisdictions that recognize copyright laws, the author or authors
         
     | 
| 
      
 9 
     | 
    
         
            +
            of this software dedicate any and all copyright interest in the
         
     | 
| 
      
 10 
     | 
    
         
            +
            software to the public domain. We make this dedication for the benefit
         
     | 
| 
      
 11 
     | 
    
         
            +
            of the public at large and to the detriment of our heirs and
         
     | 
| 
      
 12 
     | 
    
         
            +
            successors. We intend this dedication to be an overt act of
         
     | 
| 
      
 13 
     | 
    
         
            +
            relinquishment in perpetuity of all present and future rights to this
         
     | 
| 
      
 14 
     | 
    
         
            +
            software under copyright law.
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         
     | 
| 
      
 17 
     | 
    
         
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         
     | 
| 
      
 18 
     | 
    
         
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
         
     | 
| 
      
 19 
     | 
    
         
            +
            IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
         
     | 
| 
      
 20 
     | 
    
         
            +
            OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
         
     | 
| 
      
 21 
     | 
    
         
            +
            ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
         
     | 
| 
      
 22 
     | 
    
         
            +
            OTHER DEALINGS IN THE SOFTWARE.
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            For more information, please refer to <http://unlicense.org/>
         
     | 
    
        data/lib/steam_codec.rb
    ADDED
    
    
| 
         @@ -0,0 +1,176 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SteamCodec
         
     | 
| 
      
 2 
     | 
    
         
            +
                class ACF
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                    # More about AppID => https://developer.valvesoftware.com/wiki/Steam_Application_IDs
         
     | 
| 
      
 5 
     | 
    
         
            +
                    attr_accessor :AppID
         
     | 
| 
      
 6 
     | 
    
         
            +
                    attr_accessor :Universe
         
     | 
| 
      
 7 
     | 
    
         
            +
                    attr_accessor :StateFlags
         
     | 
| 
      
 8 
     | 
    
         
            +
                    attr_accessor :InstallDir
         
     | 
| 
      
 9 
     | 
    
         
            +
                    attr_accessor :LastUpdated
         
     | 
| 
      
 10 
     | 
    
         
            +
                    attr_accessor :UpdateResult
         
     | 
| 
      
 11 
     | 
    
         
            +
                    attr_accessor :SizeOnDisk
         
     | 
| 
      
 12 
     | 
    
         
            +
                    attr_accessor :BuildID
         
     | 
| 
      
 13 
     | 
    
         
            +
                    attr_accessor :LastOwner
         
     | 
| 
      
 14 
     | 
    
         
            +
                    attr_accessor :BytesToDownload
         
     | 
| 
      
 15 
     | 
    
         
            +
                    attr_accessor :BytesDownloaded
         
     | 
| 
      
 16 
     | 
    
         
            +
                    attr_accessor :FullValidateOnNextUpdate
         
     | 
| 
      
 17 
     | 
    
         
            +
                    attr_reader :UserConfig
         
     | 
| 
      
 18 
     | 
    
         
            +
                    attr_reader :MountedDepots
         
     | 
| 
      
 19 
     | 
    
         
            +
                    attr_reader :SharedDepots
         
     | 
| 
      
 20 
     | 
    
         
            +
                    attr_reader :CheckGuid
         
     | 
| 
      
 21 
     | 
    
         
            +
                    attr_reader :InstallScripts
         
     | 
| 
      
 22 
     | 
    
         
            +
                    def self.loadFromFile(file)
         
     | 
| 
      
 23 
     | 
    
         
            +
                        acf = KeyValues::loadFromFile(file)
         
     | 
| 
      
 24 
     | 
    
         
            +
                        return self.new(acf.AppState) if acf and acf.key?(:AppState)
         
     | 
| 
      
 25 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 26 
     | 
    
         
            +
                    end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    def self.load(data)
         
     | 
| 
      
 29 
     | 
    
         
            +
                        acf = KeyValues::load(data)
         
     | 
| 
      
 30 
     | 
    
         
            +
                        return self.new(acf.AppState) if acf and acf.key?(:AppState)
         
     | 
| 
      
 31 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    def initialize(appState = nil)
         
     | 
| 
      
 35 
     | 
    
         
            +
                        load(appState || KeyValues.new)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                    def load(appState)
         
     | 
| 
      
 39 
     | 
    
         
            +
                        raise ArgumentError, "AppState must be instance of KeyValues" unless appState.is_a?(KeyValues)
         
     | 
| 
      
 40 
     | 
    
         
            +
                        @AppState = appState
         
     | 
| 
      
 41 
     | 
    
         
            +
                        @AppID = @AppState.AppID.to_i if @AppState.key?(:AppID)
         
     | 
| 
      
 42 
     | 
    
         
            +
                        @Universe = @AppState.Universe.to_i if @AppState.key?(:Universe)
         
     | 
| 
      
 43 
     | 
    
         
            +
                        @StateFlags = @AppState.StateFlags.to_i if @AppState.key?(:StateFlags)
         
     | 
| 
      
 44 
     | 
    
         
            +
                        @InstallDir = @AppState.InstallDir if @AppState.key?(:InstallDir)
         
     | 
| 
      
 45 
     | 
    
         
            +
                        @LastUpdated = @AppState.LastUpdated.to_i if @AppState.key?(:LastUpdated)
         
     | 
| 
      
 46 
     | 
    
         
            +
                        @UpdateResult = @AppState.UpdateResult.to_i if @AppState.key?(:UpdateResult)
         
     | 
| 
      
 47 
     | 
    
         
            +
                        @SizeOnDisk = @AppState.SizeOnDisk.to_i if @AppState.key?(:SizeOnDisk)
         
     | 
| 
      
 48 
     | 
    
         
            +
                        @BuildID = @AppState.BuildID.to_i if @AppState.key?(:BuildID)
         
     | 
| 
      
 49 
     | 
    
         
            +
                        @LastOwner = @AppState.LastOwner if @AppState.key?(:LastOwner)
         
     | 
| 
      
 50 
     | 
    
         
            +
                        @BytesToDownload = @AppState.BytesToDownload.to_i if @AppState.key?(:BytesToDownload)
         
     | 
| 
      
 51 
     | 
    
         
            +
                        @BytesDownloaded = @AppState.BytesDownloaded.to_i if @AppState.key?(:BytesDownloaded)
         
     | 
| 
      
 52 
     | 
    
         
            +
                        @FullValidateOnNextUpdate = !@AppState.FullValidateOnNextUpdate.to_i.zero? if @AppState.key?(:FullValidateOnNextUpdate)
         
     | 
| 
      
 53 
     | 
    
         
            +
                        userConfig = nil
         
     | 
| 
      
 54 
     | 
    
         
            +
                        mountedDepots = {}
         
     | 
| 
      
 55 
     | 
    
         
            +
                        sharedDepots = {}
         
     | 
| 
      
 56 
     | 
    
         
            +
                        checkGuid = {}
         
     | 
| 
      
 57 
     | 
    
         
            +
                        installScripts = {}
         
     | 
| 
      
 58 
     | 
    
         
            +
                        userConfig = @AppState.UserConfig if @AppState.key?(:UserConfig)
         
     | 
| 
      
 59 
     | 
    
         
            +
                        mountedDepots = @AppState.MountedDepots if @AppState.key?(:MountedDepots)
         
     | 
| 
      
 60 
     | 
    
         
            +
                        sharedDepots = @AppState.SharedDepots if @AppState.key?(:sharedDepots)
         
     | 
| 
      
 61 
     | 
    
         
            +
                        checkGuid = @AppState.CheckGuid if @AppState.key?(:CheckGuid)
         
     | 
| 
      
 62 
     | 
    
         
            +
                        installScripts = @AppState.InstallScripts if @AppState.key?(:InstallScripts)
         
     | 
| 
      
 63 
     | 
    
         
            +
                        @UserConfig = UserConfig.new(userConfig)
         
     | 
| 
      
 64 
     | 
    
         
            +
                        @MountedDepots = MountedDepots.new(mountedDepots)
         
     | 
| 
      
 65 
     | 
    
         
            +
                        @SharedDepots = SharedDepots.new(sharedDepots)
         
     | 
| 
      
 66 
     | 
    
         
            +
                        @InstallScripts = InstallScripts.new(installScripts)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                    class UserConfig
         
     | 
| 
      
 70 
     | 
    
         
            +
                        attr_accessor :Name
         
     | 
| 
      
 71 
     | 
    
         
            +
                        attr_accessor :GameID
         
     | 
| 
      
 72 
     | 
    
         
            +
                        attr_accessor :Installed
         
     | 
| 
      
 73 
     | 
    
         
            +
                        attr_accessor :AppInstallDir
         
     | 
| 
      
 74 
     | 
    
         
            +
                        attr_accessor :Language
         
     | 
| 
      
 75 
     | 
    
         
            +
                        attr_accessor :BetaKey
         
     | 
| 
      
 76 
     | 
    
         
            +
                        def initialize(userConfig = nil)
         
     | 
| 
      
 77 
     | 
    
         
            +
                            load(userConfig || KeyValues.new)
         
     | 
| 
      
 78 
     | 
    
         
            +
                        end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                        def load(userConfig)
         
     | 
| 
      
 81 
     | 
    
         
            +
                            raise ArgumentError, "UserConfig must be instance of KeyValues" unless userConfig.is_a?(KeyValues)
         
     | 
| 
      
 82 
     | 
    
         
            +
                            @UserConfig = userConfig
         
     | 
| 
      
 83 
     | 
    
         
            +
                            @Name = @UserConfig.name if @UserConfig.key?(:name)
         
     | 
| 
      
 84 
     | 
    
         
            +
                            @GameID = @UserConfig.gameid.to_i if @UserConfig.key?(:gameid)
         
     | 
| 
      
 85 
     | 
    
         
            +
                            @Installed = !@UserConfig.installdir.to_i.zero? if @UserConfig.key?(:installdir)
         
     | 
| 
      
 86 
     | 
    
         
            +
                            @AppInstallDir = @UserConfig.appinstalldir if @UserConfig.key?(:appinstalldir)
         
     | 
| 
      
 87 
     | 
    
         
            +
                            @Language = @UserConfig.language if @UserConfig.key?(:language)
         
     | 
| 
      
 88 
     | 
    
         
            +
                            @BetaKey = @UserConfig.BetaKey if @UserConfig.key?(:BetaKey)
         
     | 
| 
      
 89 
     | 
    
         
            +
                        end
         
     | 
| 
      
 90 
     | 
    
         
            +
                    end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                    class MountedDepots
         
     | 
| 
      
 93 
     | 
    
         
            +
                        def initialize(mountedDepots = {})
         
     | 
| 
      
 94 
     | 
    
         
            +
                            load(mountedDepots)
         
     | 
| 
      
 95 
     | 
    
         
            +
                        end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                        def load(mountedDepots)
         
     | 
| 
      
 98 
     | 
    
         
            +
                            raise ArgumentError, "MountedDepots must be instance of Hash" unless mountedDepots.is_a?(Hash)
         
     | 
| 
      
 99 
     | 
    
         
            +
                            @MountedDepots = {}
         
     | 
| 
      
 100 
     | 
    
         
            +
                            mountedDepots.each do |depot, manifest|
         
     | 
| 
      
 101 
     | 
    
         
            +
                                @MountedDepots[depot.to_i] = manifest
         
     | 
| 
      
 102 
     | 
    
         
            +
                            end
         
     | 
| 
      
 103 
     | 
    
         
            +
                        end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                        def depots
         
     | 
| 
      
 106 
     | 
    
         
            +
                            @MountedDepots.keys
         
     | 
| 
      
 107 
     | 
    
         
            +
                        end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                        def manifests
         
     | 
| 
      
 110 
     | 
    
         
            +
                            @MountedDepots.values
         
     | 
| 
      
 111 
     | 
    
         
            +
                        end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                        def getManifest(depotID)
         
     | 
| 
      
 114 
     | 
    
         
            +
                            @MountedDepots.each do |depot, manifest|
         
     | 
| 
      
 115 
     | 
    
         
            +
                                return manifest if depot == depotID
         
     | 
| 
      
 116 
     | 
    
         
            +
                            end
         
     | 
| 
      
 117 
     | 
    
         
            +
                            nil
         
     | 
| 
      
 118 
     | 
    
         
            +
                        end
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                        def getDepot(manifestID)
         
     | 
| 
      
 121 
     | 
    
         
            +
                            @MountedDepots.each do |depot, manifest|
         
     | 
| 
      
 122 
     | 
    
         
            +
                                return depot if manifest == manifestID
         
     | 
| 
      
 123 
     | 
    
         
            +
                            end
         
     | 
| 
      
 124 
     | 
    
         
            +
                            nil
         
     | 
| 
      
 125 
     | 
    
         
            +
                        end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                        def set(depot, manifest)
         
     | 
| 
      
 128 
     | 
    
         
            +
                            @MountedDepots[depot] = manifest
         
     | 
| 
      
 129 
     | 
    
         
            +
                        end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                        def remove(depot)
         
     | 
| 
      
 132 
     | 
    
         
            +
                            @MountedDepots.delete(depot)
         
     | 
| 
      
 133 
     | 
    
         
            +
                        end
         
     | 
| 
      
 134 
     | 
    
         
            +
                    end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                    class SharedDepots
         
     | 
| 
      
 137 
     | 
    
         
            +
                        attr_reader :Depots
         
     | 
| 
      
 138 
     | 
    
         
            +
                        def initialize(sharedDepots = {})
         
     | 
| 
      
 139 
     | 
    
         
            +
                            load(sharedDepots)
         
     | 
| 
      
 140 
     | 
    
         
            +
                        end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                        def load(sharedDepots)
         
     | 
| 
      
 143 
     | 
    
         
            +
                            raise ArgumentError, "SharedDepots must be instance of Hash" unless sharedDepots.is_a?(Hash)
         
     | 
| 
      
 144 
     | 
    
         
            +
                            @SharedDepots = {}
         
     | 
| 
      
 145 
     | 
    
         
            +
                            sharedDepots.each do |depot, baseDepot|
         
     | 
| 
      
 146 
     | 
    
         
            +
                                @SharedDepots[depot.to_i] = baseDepot.to_i
         
     | 
| 
      
 147 
     | 
    
         
            +
                            end
         
     | 
| 
      
 148 
     | 
    
         
            +
                        end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                        def depots
         
     | 
| 
      
 151 
     | 
    
         
            +
                            @SharedDepots.keys
         
     | 
| 
      
 152 
     | 
    
         
            +
                        end
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
                        def getDepot(depotID)
         
     | 
| 
      
 155 
     | 
    
         
            +
                            @SharedDepots.each do |depot, baseDepot|
         
     | 
| 
      
 156 
     | 
    
         
            +
                                return baseDepot if depot == depotID
         
     | 
| 
      
 157 
     | 
    
         
            +
                            end
         
     | 
| 
      
 158 
     | 
    
         
            +
                            nil
         
     | 
| 
      
 159 
     | 
    
         
            +
                        end
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                        def set(depot, baseDepot)
         
     | 
| 
      
 162 
     | 
    
         
            +
                            @SharedDepots[depot] = baseDepot
         
     | 
| 
      
 163 
     | 
    
         
            +
                        end
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
                        def remove(depot)
         
     | 
| 
      
 166 
     | 
    
         
            +
                            @SharedDepots.delete(depot)
         
     | 
| 
      
 167 
     | 
    
         
            +
                        end
         
     | 
| 
      
 168 
     | 
    
         
            +
                    end
         
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
      
 170 
     | 
    
         
            +
                    class CheckGuid < ValueArray
         
     | 
| 
      
 171 
     | 
    
         
            +
                    end
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
                    class InstallScripts < ValueArray
         
     | 
| 
      
 174 
     | 
    
         
            +
                    end
         
     | 
| 
      
 175 
     | 
    
         
            +
                end
         
     | 
| 
      
 176 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,116 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'insensitive_hash/minimal'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module SteamCodec
         
     | 
| 
      
 5 
     | 
    
         
            +
                # About KeyValues => https://developer.valvesoftware.com/wiki/KeyValues
         
     | 
| 
      
 6 
     | 
    
         
            +
                # Valve's implementation => https://github.com/ValveSoftware/source-sdk-2013/blob/master/mp/src/tier1/KeyValues.cpp
         
     | 
| 
      
 7 
     | 
    
         
            +
                # SteamKit's implementation => https://github.com/SteamRE/SteamKit/blob/master/SteamKit2/SteamKit2/Types/KeyValue.cs
         
     | 
| 
      
 8 
     | 
    
         
            +
                class KeyValues < InsensitiveHash
         
     | 
| 
      
 9 
     | 
    
         
            +
                    class Parser
         
     | 
| 
      
 10 
     | 
    
         
            +
                        def self.proccess(data, last = true)
         
     | 
| 
      
 11 
     | 
    
         
            +
                            token = /"[^"]*"/
         
     | 
| 
      
 12 
     | 
    
         
            +
                            data = data.gsub(/(?<=^|[\s{}])(\s*)([^"{}\s\n\r]+)(\s*)(?=[\s{}]|\z)/, '\1"\2"\3')
         
     | 
| 
      
 13 
     | 
    
         
            +
                            if last
         
     | 
| 
      
 14 
     | 
    
         
            +
                                data.gsub!(/(#{token}:\s*#{token}|})(?=\s*")/, '\1,')
         
     | 
| 
      
 15 
     | 
    
         
            +
                                data.gsub!(/(#{token})(?=\s*{|[ \t\f]+")/, '\1:')
         
     | 
| 
      
 16 
     | 
    
         
            +
                            else
         
     | 
| 
      
 17 
     | 
    
         
            +
                                data.gsub!(/(#{token}:\s*#{token}|})(?=\s*"|\s*\z)/, '\1,')
         
     | 
| 
      
 18 
     | 
    
         
            +
                                data.gsub!(/(#{token})(?=\s*{|[ \t\f]+"|\s*\z)/, '\1:')
         
     | 
| 
      
 19 
     | 
    
         
            +
                            end
         
     | 
| 
      
 20 
     | 
    
         
            +
                            data
         
     | 
| 
      
 21 
     | 
    
         
            +
                        end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                        def self.isEscaped(data, index, char = '\\')
         
     | 
| 
      
 24 
     | 
    
         
            +
                            return false if index == 0
         
     | 
| 
      
 25 
     | 
    
         
            +
                            escaped = false
         
     | 
| 
      
 26 
     | 
    
         
            +
                            (index - 1).downto(0) do |num|
         
     | 
| 
      
 27 
     | 
    
         
            +
                                if data[num] == char
         
     | 
| 
      
 28 
     | 
    
         
            +
                                    escaped = !escaped
         
     | 
| 
      
 29 
     | 
    
         
            +
                                else
         
     | 
| 
      
 30 
     | 
    
         
            +
                                    break
         
     | 
| 
      
 31 
     | 
    
         
            +
                                end
         
     | 
| 
      
 32 
     | 
    
         
            +
                            end
         
     | 
| 
      
 33 
     | 
    
         
            +
                            escaped
         
     | 
| 
      
 34 
     | 
    
         
            +
                        end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                        def self.getQuoteList(data)
         
     | 
| 
      
 37 
     | 
    
         
            +
                            indexes = []
         
     | 
| 
      
 38 
     | 
    
         
            +
                            quoted = false
         
     | 
| 
      
 39 
     | 
    
         
            +
                            length = data.length
         
     | 
| 
      
 40 
     | 
    
         
            +
                            length.times do |index|
         
     | 
| 
      
 41 
     | 
    
         
            +
                                if data[index] == '"'
         
     | 
| 
      
 42 
     | 
    
         
            +
                                    escaped = false
         
     | 
| 
      
 43 
     | 
    
         
            +
                                    escaped = self.isEscaped(data, index) if quoted
         
     | 
| 
      
 44 
     | 
    
         
            +
                                    if not escaped
         
     | 
| 
      
 45 
     | 
    
         
            +
                                        indexes << index
         
     | 
| 
      
 46 
     | 
    
         
            +
                                        quoted = !quoted
         
     | 
| 
      
 47 
     | 
    
         
            +
                                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                                end
         
     | 
| 
      
 49 
     | 
    
         
            +
                            end
         
     | 
| 
      
 50 
     | 
    
         
            +
                            raise RuntimeError, "Unmatched quotes" if quoted
         
     | 
| 
      
 51 
     | 
    
         
            +
                            indexes
         
     | 
| 
      
 52 
     | 
    
         
            +
                        end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                        def self.toJSON(data)
         
     | 
| 
      
 55 
     | 
    
         
            +
                            raise ArgumentError, "data must be String" unless data.is_a?(String)
         
     | 
| 
      
 56 
     | 
    
         
            +
                            str = ''
         
     | 
| 
      
 57 
     | 
    
         
            +
                            previous = 0
         
     | 
| 
      
 58 
     | 
    
         
            +
                            data.gsub!(/^#(include|base).*$/, '') # include and base not supported so just ignore
         
     | 
| 
      
 59 
     | 
    
         
            +
                            quoteList = self.getQuoteList(data)
         
     | 
| 
      
 60 
     | 
    
         
            +
                            quoteList.each_index  do |index|
         
     | 
| 
      
 61 
     | 
    
         
            +
                                quoted = index % 2 == 1
         
     | 
| 
      
 62 
     | 
    
         
            +
                                part = data[previous...quoteList[index]]
         
     | 
| 
      
 63 
     | 
    
         
            +
                                previous = quoteList[index] + 1
         
     | 
| 
      
 64 
     | 
    
         
            +
                                next if part.empty? and not quoted
         
     | 
| 
      
 65 
     | 
    
         
            +
                                if quoted
         
     | 
| 
      
 66 
     | 
    
         
            +
                                    str += '"' + part.gsub(/\n/,'\n') + '"'
         
     | 
| 
      
 67 
     | 
    
         
            +
                                    lastIndex = data.length
         
     | 
| 
      
 68 
     | 
    
         
            +
                                    lastIndex = quoteList[index + 1] if index + 1 < quoteList.length
         
     | 
| 
      
 69 
     | 
    
         
            +
                                    nextPart = data[previous...lastIndex].gsub(/\\\\.*$/,'') # remove comments
         
     | 
| 
      
 70 
     | 
    
         
            +
                                    nextPart = self.proccess(nextPart, true)
         
     | 
| 
      
 71 
     | 
    
         
            +
                                    case nextPart
         
     | 
| 
      
 72 
     | 
    
         
            +
                                    when /\A(\s*{|[ \t]+\z)/
         
     | 
| 
      
 73 
     | 
    
         
            +
                                        str += ':'
         
     | 
| 
      
 74 
     | 
    
         
            +
                                    when /\A\s+\z/
         
     | 
| 
      
 75 
     | 
    
         
            +
                                        str += ','
         
     | 
| 
      
 76 
     | 
    
         
            +
                                    end
         
     | 
| 
      
 77 
     | 
    
         
            +
                                else
         
     | 
| 
      
 78 
     | 
    
         
            +
                                    part = part.gsub(/\\\\[^\n]*$/,'') # remove comments
         
     | 
| 
      
 79 
     | 
    
         
            +
                                    str += self.proccess(part, index + 1 >= quoteList.length)
         
     | 
| 
      
 80 
     | 
    
         
            +
                                end
         
     | 
| 
      
 81 
     | 
    
         
            +
                            end
         
     | 
| 
      
 82 
     | 
    
         
            +
                            lastIndex = data.length
         
     | 
| 
      
 83 
     | 
    
         
            +
                            part = data[previous...lastIndex]
         
     | 
| 
      
 84 
     | 
    
         
            +
                            str += self.proccess(part, true) if part
         
     | 
| 
      
 85 
     | 
    
         
            +
                            '{' + str + '}'
         
     | 
| 
      
 86 
     | 
    
         
            +
                        end
         
     | 
| 
      
 87 
     | 
    
         
            +
                    end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                    def self.loadFromJSON(json)
         
     | 
| 
      
 90 
     | 
    
         
            +
                        JSON.parse(json, {:object_class => self})
         
     | 
| 
      
 91 
     | 
    
         
            +
                    rescue JSON::ParserError
         
     | 
| 
      
 92 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 93 
     | 
    
         
            +
                    end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                    def self.loadFromFile(file)
         
     | 
| 
      
 96 
     | 
    
         
            +
                        raise ArgumentError, "file must respond to :read" unless file.respond_to?(:read)
         
     | 
| 
      
 97 
     | 
    
         
            +
                        json = self::Parser::toJSON(file.read)
         
     | 
| 
      
 98 
     | 
    
         
            +
                        self.loadFromJSON(json)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                    def self.load(data)
         
     | 
| 
      
 102 
     | 
    
         
            +
                        json = self::Parser::toJSON(data)
         
     | 
| 
      
 103 
     | 
    
         
            +
                        self.loadFromJSON(json)
         
     | 
| 
      
 104 
     | 
    
         
            +
                    end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                    def method_missing(name, *args, &block) # :nodoc:
         
     | 
| 
      
 107 
     | 
    
         
            +
                        return self[name] if args.empty? and block.nil? and key?(name)
         
     | 
| 
      
 108 
     | 
    
         
            +
                        super
         
     | 
| 
      
 109 
     | 
    
         
            +
                    end
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                    def respond_to_missing?(name, include_private = false) # :nodoc:
         
     | 
| 
      
 112 
     | 
    
         
            +
                        return true if key?(name)
         
     | 
| 
      
 113 
     | 
    
         
            +
                        super
         
     | 
| 
      
 114 
     | 
    
         
            +
                    end
         
     | 
| 
      
 115 
     | 
    
         
            +
                end
         
     | 
| 
      
 116 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,45 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SteamCodec
         
     | 
| 
      
 2 
     | 
    
         
            +
                class ValueArray
         
     | 
| 
      
 3 
     | 
    
         
            +
                    def initialize(valueHash = {})
         
     | 
| 
      
 4 
     | 
    
         
            +
                        load(valueHash)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                    def load(valueHash)
         
     | 
| 
      
 8 
     | 
    
         
            +
                        raise ArgumentError, "ValueHash must be instance of Hash" unless valueHash.is_a?(Hash)
         
     | 
| 
      
 9 
     | 
    
         
            +
                        @ValueHash = {}
         
     | 
| 
      
 10 
     | 
    
         
            +
                        valueHash.each do |id, file|
         
     | 
| 
      
 11 
     | 
    
         
            +
                            @ValueHash[id.to_i] = file
         
     | 
| 
      
 12 
     | 
    
         
            +
                        end
         
     | 
| 
      
 13 
     | 
    
         
            +
                    end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    def [](id)
         
     | 
| 
      
 16 
     | 
    
         
            +
                        @ValueHash[id]
         
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    def []=(id, file)
         
     | 
| 
      
 20 
     | 
    
         
            +
                        @ValueHash[id] = file
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    def add(file)
         
     | 
| 
      
 24 
     | 
    
         
            +
                        id = @ValueHash.keys.max + 1
         
     | 
| 
      
 25 
     | 
    
         
            +
                        @ValueHash[id] = file
         
     | 
| 
      
 26 
     | 
    
         
            +
                        id
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                    def remove(id)
         
     | 
| 
      
 30 
     | 
    
         
            +
                        @ValueHash.delete(id)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    def to_a
         
     | 
| 
      
 34 
     | 
    
         
            +
                        check = []
         
     | 
| 
      
 35 
     | 
    
         
            +
                        @ValueHash.sort_by { |key, value| key.to_s.to_i }.each do |array|
         
     | 
| 
      
 36 
     | 
    
         
            +
                            check << array.last
         
     | 
| 
      
 37 
     | 
    
         
            +
                        end
         
     | 
| 
      
 38 
     | 
    
         
            +
                        check
         
     | 
| 
      
 39 
     | 
    
         
            +
                    end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    alias_method :all, :to_a
         
     | 
| 
      
 42 
     | 
    
         
            +
                    alias_method :get, :[]
         
     | 
| 
      
 43 
     | 
    
         
            +
                    alias_method :set, :[]=
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SteamCodec
         
     | 
| 
      
 2 
     | 
    
         
            +
                class VDF < KeyValues
         
     | 
| 
      
 3 
     | 
    
         
            +
                    # About VDF => http://wiki.teamfortress.com/wiki/WebAPI/VDF
         
     | 
| 
      
 4 
     | 
    
         
            +
                    def self.loadFromFile(file)
         
     | 
| 
      
 5 
     | 
    
         
            +
                        vdf = KeyValues::loadFromFile(file)
         
     | 
| 
      
 6 
     | 
    
         
            +
                        return self[vdf] if vdf
         
     | 
| 
      
 7 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 8 
     | 
    
         
            +
                    end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    def self.load(data)
         
     | 
| 
      
 11 
     | 
    
         
            +
                        vdf = KeyValues::load(data)
         
     | 
| 
      
 12 
     | 
    
         
            +
                        return self[vdf] if vdf
         
     | 
| 
      
 13 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 14 
     | 
    
         
            +
                    end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    def isSignaturesValid?(publicKey)
         
     | 
| 
      
 17 
     | 
    
         
            +
                        return true unless key?("kvsignatures")
         
     | 
| 
      
 18 
     | 
    
         
            +
                        self["kvsignatures"].each do |key, signature|
         
     | 
| 
      
 19 
     | 
    
         
            +
                            # TODO
         
     | 
| 
      
 20 
     | 
    
         
            +
                            return false
         
     | 
| 
      
 21 
     | 
    
         
            +
                        end
         
     | 
| 
      
 22 
     | 
    
         
            +
                        true
         
     | 
| 
      
 23 
     | 
    
         
            +
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/acf_spec.rb
    ADDED
    
    | 
         @@ -0,0 +1,137 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe SteamCodec::ACF do
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                let(:appCacheFile) { <<-EOS
         
     | 
| 
      
 6 
     | 
    
         
            +
                    "AppState"
         
     | 
| 
      
 7 
     | 
    
         
            +
                    {
         
     | 
| 
      
 8 
     | 
    
         
            +
                        "appid"             "207930"
         
     | 
| 
      
 9 
     | 
    
         
            +
                        "Universe"          "1"
         
     | 
| 
      
 10 
     | 
    
         
            +
                        "StateFlags"        "4"
         
     | 
| 
      
 11 
     | 
    
         
            +
                        "installdir"        "sacred_citadel"
         
     | 
| 
      
 12 
     | 
    
         
            +
                        "LastUpdated"       "1377100000"
         
     | 
| 
      
 13 
     | 
    
         
            +
                        "UpdateResult"      "0"
         
     | 
| 
      
 14 
     | 
    
         
            +
                        "SizeOnDisk"        "1193761500"
         
     | 
| 
      
 15 
     | 
    
         
            +
                        "buildid"           "60250"
         
     | 
| 
      
 16 
     | 
    
         
            +
                        "LastOwner"         "0"
         
     | 
| 
      
 17 
     | 
    
         
            +
                        "BytesToDownload"   "0"
         
     | 
| 
      
 18 
     | 
    
         
            +
                        "BytesDownloaded"   "0"
         
     | 
| 
      
 19 
     | 
    
         
            +
                        "FullValidateOnNextUpdate"    "1"
         
     | 
| 
      
 20 
     | 
    
         
            +
                        "UserConfig"
         
     | 
| 
      
 21 
     | 
    
         
            +
                        {
         
     | 
| 
      
 22 
     | 
    
         
            +
                            "name"          "Sacred Citadel"
         
     | 
| 
      
 23 
     | 
    
         
            +
                            "gameid"        "207930"
         
     | 
| 
      
 24 
     | 
    
         
            +
                            "installed"     "1"
         
     | 
| 
      
 25 
     | 
    
         
            +
                            "appinstalldir" "C:\\Steam\\steamapps\\common\\sacred_citadel"
         
     | 
| 
      
 26 
     | 
    
         
            +
                            "language"      "english"
         
     | 
| 
      
 27 
     | 
    
         
            +
                            "BetaKey"       "public"
         
     | 
| 
      
 28 
     | 
    
         
            +
                        }
         
     | 
| 
      
 29 
     | 
    
         
            +
                        "MountedDepots"
         
     | 
| 
      
 30 
     | 
    
         
            +
                        {
         
     | 
| 
      
 31 
     | 
    
         
            +
                            "228982"        "6039653574073929574"
         
     | 
| 
      
 32 
     | 
    
         
            +
                            "228983"        "4721092052804263356"
         
     | 
| 
      
 33 
     | 
    
         
            +
                        }
         
     | 
| 
      
 34 
     | 
    
         
            +
                        "SharedDepots"
         
     | 
| 
      
 35 
     | 
    
         
            +
                        {
         
     | 
| 
      
 36 
     | 
    
         
            +
                            "228984"        "228980"
         
     | 
| 
      
 37 
     | 
    
         
            +
                        }
         
     | 
| 
      
 38 
     | 
    
         
            +
                        "checkguid"
         
     | 
| 
      
 39 
     | 
    
         
            +
                        {
         
     | 
| 
      
 40 
     | 
    
         
            +
                            "0"     "Bin\\some.exe"
         
     | 
| 
      
 41 
     | 
    
         
            +
                            "1"     "Bin\\another.exe"
         
     | 
| 
      
 42 
     | 
    
         
            +
                        }
         
     | 
| 
      
 43 
     | 
    
         
            +
                        "InstallScripts"
         
     | 
| 
      
 44 
     | 
    
         
            +
                        {
         
     | 
| 
      
 45 
     | 
    
         
            +
                            "0"     "_CommonRedist\\vcredist\\2008\\installscript.vdf"
         
     | 
| 
      
 46 
     | 
    
         
            +
                            "1"     "_CommonRedist\\vcredist\\2010\\installscript.vdf"
         
     | 
| 
      
 47 
     | 
    
         
            +
                        }
         
     | 
| 
      
 48 
     | 
    
         
            +
                    }
         
     | 
| 
      
 49 
     | 
    
         
            +
                    EOS
         
     | 
| 
      
 50 
     | 
    
         
            +
                }
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                describe '.loadFromFile' do
         
     | 
| 
      
 53 
     | 
    
         
            +
                    it 'should successfully load from file' do
         
     | 
| 
      
 54 
     | 
    
         
            +
                        StringIO.open(appCacheFile) do |file|
         
     | 
| 
      
 55 
     | 
    
         
            +
                            SteamCodec::ACF::loadFromFile(file).should be_an_instance_of SteamCodec::ACF
         
     | 
| 
      
 56 
     | 
    
         
            +
                        end
         
     | 
| 
      
 57 
     | 
    
         
            +
                    end
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                describe '.load' do
         
     | 
| 
      
 61 
     | 
    
         
            +
                    it 'should successfully load' do
         
     | 
| 
      
 62 
     | 
    
         
            +
                        SteamCodec::ACF::load(appCacheFile).should be_an_instance_of SteamCodec::ACF
         
     | 
| 
      
 63 
     | 
    
         
            +
                    end
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                describe '.new' do
         
     | 
| 
      
 67 
     | 
    
         
            +
                    it 'should initialize new instance with empty fields' do
         
     | 
| 
      
 68 
     | 
    
         
            +
                        SteamCodec::ACF.new.AppID.should be_nil
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                describe '#InstallDir' do
         
     | 
| 
      
 73 
     | 
    
         
            +
                    it 'should return value' do
         
     | 
| 
      
 74 
     | 
    
         
            +
                        SteamCodec::ACF::load(appCacheFile).InstallDir.should eq("sacred_citadel")
         
     | 
| 
      
 75 
     | 
    
         
            +
                    end
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                describe SteamCodec::ACF::UserConfig do
         
     | 
| 
      
 79 
     | 
    
         
            +
                    describe '.new' do
         
     | 
| 
      
 80 
     | 
    
         
            +
                        it 'should initialize new instance with empty fields' do
         
     | 
| 
      
 81 
     | 
    
         
            +
                            SteamCodec::ACF::UserConfig.new.Name.should be_nil
         
     | 
| 
      
 82 
     | 
    
         
            +
                        end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                        it 'should initialize new instance with provided fields' do
         
     | 
| 
      
 85 
     | 
    
         
            +
                            SteamCodec::ACF::UserConfig.new(SteamCodec::KeyValues[{"Name" => "Game"}]).Name.should eq("Game")
         
     | 
| 
      
 86 
     | 
    
         
            +
                        end
         
     | 
| 
      
 87 
     | 
    
         
            +
                    end
         
     | 
| 
      
 88 
     | 
    
         
            +
                end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                describe SteamCodec::ACF::MountedDepots do
         
     | 
| 
      
 91 
     | 
    
         
            +
                    let(:depots) { {"228982" => "6039653574073929574"} }
         
     | 
| 
      
 92 
     | 
    
         
            +
                    describe '.new' do
         
     | 
| 
      
 93 
     | 
    
         
            +
                        it 'should initialize new instance with empty fields' do
         
     | 
| 
      
 94 
     | 
    
         
            +
                            SteamCodec::ACF::MountedDepots.new.depots.should eq([])
         
     | 
| 
      
 95 
     | 
    
         
            +
                            SteamCodec::ACF::MountedDepots.new.manifests.should eq([])
         
     | 
| 
      
 96 
     | 
    
         
            +
                        end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                        it 'should initialize new instance with provided fields' do
         
     | 
| 
      
 99 
     | 
    
         
            +
                            SteamCodec::ACF::MountedDepots.new(depots).depots.should eq([228982])
         
     | 
| 
      
 100 
     | 
    
         
            +
                            SteamCodec::ACF::MountedDepots.new(depots).manifests.should eq(["6039653574073929574"])
         
     | 
| 
      
 101 
     | 
    
         
            +
                        end
         
     | 
| 
      
 102 
     | 
    
         
            +
                    end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                    describe '#getManifest' do
         
     | 
| 
      
 105 
     | 
    
         
            +
                        it 'should return manifest' do
         
     | 
| 
      
 106 
     | 
    
         
            +
                            SteamCodec::ACF::MountedDepots.new(depots).getManifest(228982).should eq("6039653574073929574")
         
     | 
| 
      
 107 
     | 
    
         
            +
                        end
         
     | 
| 
      
 108 
     | 
    
         
            +
                    end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                    describe '#getDepot' do
         
     | 
| 
      
 111 
     | 
    
         
            +
                        it 'should return depot' do
         
     | 
| 
      
 112 
     | 
    
         
            +
                            SteamCodec::ACF::MountedDepots.new(depots).getDepot("6039653574073929574").should eq(228982)
         
     | 
| 
      
 113 
     | 
    
         
            +
                        end
         
     | 
| 
      
 114 
     | 
    
         
            +
                    end
         
     | 
| 
      
 115 
     | 
    
         
            +
                end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                describe SteamCodec::ACF::SharedDepots do
         
     | 
| 
      
 118 
     | 
    
         
            +
                    let(:depots) { {"228984" => "228980"} }
         
     | 
| 
      
 119 
     | 
    
         
            +
                    describe '.new' do
         
     | 
| 
      
 120 
     | 
    
         
            +
                        it 'should initialize new instance with empty fields' do
         
     | 
| 
      
 121 
     | 
    
         
            +
                            SteamCodec::ACF::SharedDepots.new.depots.should eq([])
         
     | 
| 
      
 122 
     | 
    
         
            +
                        end
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                        it 'should initialize new instance with provided fields' do
         
     | 
| 
      
 125 
     | 
    
         
            +
                            SteamCodec::ACF::SharedDepots.new(depots).depots.should eq([228984])
         
     | 
| 
      
 126 
     | 
    
         
            +
                            SteamCodec::ACF::SharedDepots.new(depots).getDepot(228984).should eq(228980)
         
     | 
| 
      
 127 
     | 
    
         
            +
                        end
         
     | 
| 
      
 128 
     | 
    
         
            +
                    end
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                    describe '#getDepot' do
         
     | 
| 
      
 131 
     | 
    
         
            +
                        it 'should return depot' do
         
     | 
| 
      
 132 
     | 
    
         
            +
                            SteamCodec::ACF::SharedDepots.new(depots).getDepot(228984).should eq(228980)
         
     | 
| 
      
 133 
     | 
    
         
            +
                        end
         
     | 
| 
      
 134 
     | 
    
         
            +
                    end
         
     | 
| 
      
 135 
     | 
    
         
            +
                end
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,179 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe SteamCodec::KeyValues do
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                let(:tokenKey) { 'TokenKey123' }
         
     | 
| 
      
 6 
     | 
    
         
            +
                let(:tokenValue) { 'Token+Value4567' }
         
     | 
| 
      
 7 
     | 
    
         
            +
                let(:tokenKeyQuoted) { "\"#{tokenKey}\"" }
         
     | 
| 
      
 8 
     | 
    
         
            +
                let(:tokenValueQuoted) { "\"#{tokenValue}\"" }
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                let(:jsonSample1a) { "#{tokenKeyQuoted} #{tokenValueQuoted}" }
         
     | 
| 
      
 11 
     | 
    
         
            +
                let(:jsonSample1b) { "#{tokenKeyQuoted}\n{\t#{tokenKeyQuoted}\t#{tokenValueQuoted}\n}" }
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                let(:jsonSample2a) { "#{tokenKeyQuoted} #{tokenValueQuoted}\n#{tokenKeyQuoted}\t#{tokenValueQuoted}" }
         
     | 
| 
      
 14 
     | 
    
         
            +
                let(:jsonSample2b) { "#{tokenKeyQuoted}\t{}\n#{tokenKeyQuoted} #{tokenValueQuoted}" }
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                let(:jsonSample3a) { '"Ke\\ty\\\\is" "Val\\nue\\\\\\""' }
         
     | 
| 
      
 17 
     | 
    
         
            +
                let(:jsonSample3b) { '"Ke\\\\ty\\is\\\\" "te\\\\s\\\\n\\\\v\\"\\\\"' }
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                let(:jsonSample4a) { "#{tokenKey} #{tokenValue}" }
         
     | 
| 
      
 20 
     | 
    
         
            +
                let(:jsonSample4b) { "#{tokenKey}\n{\t#{tokenKey}\t#{tokenValue}\n}" }
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                let(:jsonSample5a) { 'abc "lol this {weird string}"' }
         
     | 
| 
      
 23 
     | 
    
         
            +
                let(:jsonSample5b) { "\"\\\"really weird\\\"\n{\n\\\"string\\\" \\\"this is\\\"\n}\"\n{\n\"string\" \"this is\"\n}" }
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                let(:jsonSample6a) { "#{tokenKeyQuoted}\\\\this should be ignored\n{\t#{tokenKeyQuoted}\t#{tokenValueQuoted}\n}" }
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                let(:jsonSample7a) { "#base <blah.vdf>\n#{tokenKey}\n{\t#{tokenKey}\t#{tokenValue}\n}" }
         
     | 
| 
      
 28 
     | 
    
         
            +
                let(:jsonSample7b) { "#include <blah.vdf>\n#{tokenKey}\n{\t#{tokenKey}\t#{tokenValue}\n}" }
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                let(:keyValueData) { <<-EOS
         
     | 
| 
      
 31 
     | 
    
         
            +
                    "AppState"
         
     | 
| 
      
 32 
     | 
    
         
            +
                    {
         
     | 
| 
      
 33 
     | 
    
         
            +
                        "appid"     "320"
         
     | 
| 
      
 34 
     | 
    
         
            +
                        "Universe"  "1"
         
     | 
| 
      
 35 
     | 
    
         
            +
                    }
         
     | 
| 
      
 36 
     | 
    
         
            +
                    EOS
         
     | 
| 
      
 37 
     | 
    
         
            +
                }
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                describe SteamCodec::KeyValues::Parser do
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    describe '.isEscaped' do
         
     | 
| 
      
 42 
     | 
    
         
            +
                        it 'empty string should not be escaped' do
         
     | 
| 
      
 43 
     | 
    
         
            +
                            SteamCodec::KeyValues::Parser::isEscaped('', 0).should be_false
         
     | 
| 
      
 44 
     | 
    
         
            +
                        end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                        it 'should be escaped' do
         
     | 
| 
      
 47 
     | 
    
         
            +
                            SteamCodec::KeyValues::Parser::isEscaped('\\"', 1).should be_true
         
     | 
| 
      
 48 
     | 
    
         
            +
                            SteamCodec::KeyValues::Parser::isEscaped('\\\\\\"', 3).should be_true
         
     | 
| 
      
 49 
     | 
    
         
            +
                            SteamCodec::KeyValues::Parser::isEscaped('trol\\lol\\lol\\"trrr', 13).should be_true
         
     | 
| 
      
 50 
     | 
    
         
            +
                        end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                        it 'should not be escaped' do
         
     | 
| 
      
 53 
     | 
    
         
            +
                            SteamCodec::KeyValues::Parser::isEscaped('\\\\"', 2).should be_false
         
     | 
| 
      
 54 
     | 
    
         
            +
                            SteamCodec::KeyValues::Parser::isEscaped('\\\\\\\\"', 4).should be_false
         
     | 
| 
      
 55 
     | 
    
         
            +
                            SteamCodec::KeyValues::Parser::isEscaped('trol\\lol\\lol\\\\"trrr', 14).should be_false
         
     | 
| 
      
 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}}")
         
     | 
| 
      
 102 
     | 
    
         
            +
                        end
         
     | 
| 
      
 103 
     | 
    
         
            +
                    end
         
     | 
| 
      
 104 
     | 
    
         
            +
                end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                describe '.loadFromJSON' do
         
     | 
| 
      
 107 
     | 
    
         
            +
                    it 'should return nil for invalid json' do
         
     | 
| 
      
 108 
     | 
    
         
            +
                        SteamCodec::KeyValues::loadFromJSON('invalid :P').should be_nil
         
     | 
| 
      
 109 
     | 
    
         
            +
                    end
         
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                describe '.load' do
         
     | 
| 
      
 113 
     | 
    
         
            +
                    it 'should load correctly empty data' do
         
     | 
| 
      
 114 
     | 
    
         
            +
                        SteamCodec::KeyValues::load('').should eq({})
         
     | 
| 
      
 115 
     | 
    
         
            +
                    end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                    it 'should raise exception on invalid data' do
         
     | 
| 
      
 118 
     | 
    
         
            +
                        expect { SteamCodec::KeyValues::load(nil) }.to raise_error(ArgumentError)
         
     | 
| 
      
 119 
     | 
    
         
            +
                        expect { SteamCodec::KeyValues::load({})  }.to raise_error(ArgumentError)
         
     | 
| 
      
 120 
     | 
    
         
            +
                    end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                    it 'should load correctly various representations' do
         
     | 
| 
      
 123 
     | 
    
         
            +
                        SteamCodec::KeyValues::load(jsonSample1a).should eq({ tokenKey => tokenValue })
         
     | 
| 
      
 124 
     | 
    
         
            +
                        SteamCodec::KeyValues::load(jsonSample1b).should eq({ tokenKey => { tokenKey => tokenValue } })
         
     | 
| 
      
 125 
     | 
    
         
            +
                        SteamCodec::KeyValues::load(jsonSample2a).should eq({ tokenKey => tokenValue })
         
     | 
| 
      
 126 
     | 
    
         
            +
                        SteamCodec::KeyValues::load(jsonSample2b).should eq({ tokenKey => tokenValue })
         
     | 
| 
      
 127 
     | 
    
         
            +
                        SteamCodec::KeyValues::load(jsonSample3a).should eq({"Ke\ty\\is" => "Val\nue\\\""})
         
     | 
| 
      
 128 
     | 
    
         
            +
                        SteamCodec::KeyValues::load(jsonSample3b).should eq({'Ke\\tyis\\' => "te\\s\\n\\v\"\\"})
         
     | 
| 
      
 129 
     | 
    
         
            +
                        SteamCodec::KeyValues::load(jsonSample4a).should eq({ tokenKey => tokenValue })
         
     | 
| 
      
 130 
     | 
    
         
            +
                        SteamCodec::KeyValues::load(jsonSample4b).should eq({ tokenKey => { tokenKey => tokenValue } })
         
     | 
| 
      
 131 
     | 
    
         
            +
                        SteamCodec::KeyValues::load(jsonSample5a).should eq({"abc" => "lol this {weird string}"})
         
     | 
| 
      
 132 
     | 
    
         
            +
                        SteamCodec::KeyValues::load(jsonSample5b).should eq({"\"really weird\"\n{\n\"string\" \"this is\"\n}" => {"string" => "this is"}})
         
     | 
| 
      
 133 
     | 
    
         
            +
                        SteamCodec::KeyValues::load(jsonSample6a).should eq({ tokenKey => { tokenKey => tokenValue } })
         
     | 
| 
      
 134 
     | 
    
         
            +
                        SteamCodec::KeyValues::load(jsonSample7a).should eq({ tokenKey => { tokenKey => tokenValue } })
         
     | 
| 
      
 135 
     | 
    
         
            +
                        SteamCodec::KeyValues::load(jsonSample7b).should eq({ tokenKey => { tokenKey => tokenValue } })
         
     | 
| 
      
 136 
     | 
    
         
            +
                    end
         
     | 
| 
      
 137 
     | 
    
         
            +
                end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                describe '.loadFromFile' do
         
     | 
| 
      
 140 
     | 
    
         
            +
                    it 'should raise exception if not file' do
         
     | 
| 
      
 141 
     | 
    
         
            +
                        expect { SteamCodec::KeyValues::loadFromFile("blah") }.to raise_error(ArgumentError)
         
     | 
| 
      
 142 
     | 
    
         
            +
                    end
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                    it 'should succesfully load from file' do
         
     | 
| 
      
 145 
     | 
    
         
            +
                        StringIO.open(keyValueData) do |file|
         
     | 
| 
      
 146 
     | 
    
         
            +
                            SteamCodec::KeyValues::loadFromFile(file).should eq({ "AppState" => { "appid" => "320", "Universe" => "1" } })
         
     | 
| 
      
 147 
     | 
    
         
            +
                        end
         
     | 
| 
      
 148 
     | 
    
         
            +
                    end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                    it 'should be KeyValues instance' do
         
     | 
| 
      
 151 
     | 
    
         
            +
                        StringIO.open(keyValueData) do |file|
         
     | 
| 
      
 152 
     | 
    
         
            +
                            SteamCodec::KeyValues::loadFromFile(file).should be_an_instance_of SteamCodec::KeyValues
         
     | 
| 
      
 153 
     | 
    
         
            +
                        end
         
     | 
| 
      
 154 
     | 
    
         
            +
                    end
         
     | 
| 
      
 155 
     | 
    
         
            +
                end
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
                describe 'access any field' do
         
     | 
| 
      
 158 
     | 
    
         
            +
                    let(:keyValues) { SteamCodec::KeyValues::load(keyValueData) }
         
     | 
| 
      
 159 
     | 
    
         
            +
                    it 'should be able to access AppState' do
         
     | 
| 
      
 160 
     | 
    
         
            +
                        keyValues.AppState.should eq({ "appid" => "320", "Universe" => "1" })
         
     | 
| 
      
 161 
     | 
    
         
            +
                    end
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
                    it 'should be able to read AppID' do
         
     | 
| 
      
 164 
     | 
    
         
            +
                        keyValues.AppState.AppID.should eq("320")
         
     | 
| 
      
 165 
     | 
    
         
            +
                    end
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
      
 167 
     | 
    
         
            +
                    it 'should check if field exists' do
         
     | 
| 
      
 168 
     | 
    
         
            +
                        keyValues.AppState.has_key?(:AppID).should be_true
         
     | 
| 
      
 169 
     | 
    
         
            +
                        keyValues.AppState.has_key?(:UserConfig).should be_false
         
     | 
| 
      
 170 
     | 
    
         
            +
                        keyValues.respond_to?(:appstate).should be_true
         
     | 
| 
      
 171 
     | 
    
         
            +
                        keyValues.respond_to?(:nope).should be_false
         
     | 
| 
      
 172 
     | 
    
         
            +
                    end
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
                    it 'should raise exception for non-existent field' do
         
     | 
| 
      
 175 
     | 
    
         
            +
                        expect { keyValues.AppState.UserConfig }.to raise_error(NoMethodError)
         
     | 
| 
      
 176 
     | 
    
         
            +
                    end
         
     | 
| 
      
 177 
     | 
    
         
            +
                end
         
     | 
| 
      
 178 
     | 
    
         
            +
             
     | 
| 
      
 179 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/spec_helper.rb
    ADDED
    
    
    
        data/spec/vdf_spec.rb
    ADDED
    
    | 
         @@ -0,0 +1,136 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe SteamCodec::VDF do
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                let(:valveDataFile) { <<-EOS
         
     | 
| 
      
 6 
     | 
    
         
            +
                    "InstallScript"
         
     | 
| 
      
 7 
     | 
    
         
            +
                    {
         
     | 
| 
      
 8 
     | 
    
         
            +
                        "Registry"
         
     | 
| 
      
 9 
     | 
    
         
            +
                        {
         
     | 
| 
      
 10 
     | 
    
         
            +
                            "HKEY_LOCAL_MACHINE\\SOFTWARE\\Activision\\Singularity"
         
     | 
| 
      
 11 
     | 
    
         
            +
                            {
         
     | 
| 
      
 12 
     | 
    
         
            +
                                "string"
         
     | 
| 
      
 13 
     | 
    
         
            +
                                {
         
     | 
| 
      
 14 
     | 
    
         
            +
                                    "EXEString"     "%INSTALLDIR%\\Binaries\\Singularity.exe"
         
     | 
| 
      
 15 
     | 
    
         
            +
                                    "InstallPath"       "%INSTALLDIR%"
         
     | 
| 
      
 16 
     | 
    
         
            +
                                    "IntVersion"        "35.0"
         
     | 
| 
      
 17 
     | 
    
         
            +
                                    "Version"       "1.0"
         
     | 
| 
      
 18 
     | 
    
         
            +
                                    "english"
         
     | 
| 
      
 19 
     | 
    
         
            +
                                    {
         
     | 
| 
      
 20 
     | 
    
         
            +
                                        "Language"      "1033"
         
     | 
| 
      
 21 
     | 
    
         
            +
                                        "LanguageCode"      "ENU"
         
     | 
| 
      
 22 
     | 
    
         
            +
                                        "Localization"      "ENU"
         
     | 
| 
      
 23 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 24 
     | 
    
         
            +
                                    "french"
         
     | 
| 
      
 25 
     | 
    
         
            +
                                    {
         
     | 
| 
      
 26 
     | 
    
         
            +
                                        "Language"      "1036"
         
     | 
| 
      
 27 
     | 
    
         
            +
                                        "LanguageCode"      "FRA"
         
     | 
| 
      
 28 
     | 
    
         
            +
                                        "Localization"      "FRA"
         
     | 
| 
      
 29 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 30 
     | 
    
         
            +
                                    "german"
         
     | 
| 
      
 31 
     | 
    
         
            +
                                    {
         
     | 
| 
      
 32 
     | 
    
         
            +
                                        "Language"      "1031"
         
     | 
| 
      
 33 
     | 
    
         
            +
                                        "LanguageCode"      "DEU"
         
     | 
| 
      
 34 
     | 
    
         
            +
                                        "Localization"      "DEU"
         
     | 
| 
      
 35 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 36 
     | 
    
         
            +
                                    "italian"
         
     | 
| 
      
 37 
     | 
    
         
            +
                                    {
         
     | 
| 
      
 38 
     | 
    
         
            +
                                        "Language"      "1040"
         
     | 
| 
      
 39 
     | 
    
         
            +
                                        "LanguageCode"      "ITA"
         
     | 
| 
      
 40 
     | 
    
         
            +
                                        "Localization"      "ITA"
         
     | 
| 
      
 41 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 42 
     | 
    
         
            +
                                    "spanish"
         
     | 
| 
      
 43 
     | 
    
         
            +
                                    {
         
     | 
| 
      
 44 
     | 
    
         
            +
                                        "Language"      "1034"
         
     | 
| 
      
 45 
     | 
    
         
            +
                                        "LanguageCode"      "ESP"
         
     | 
| 
      
 46 
     | 
    
         
            +
                                        "Localization"      "ESP"
         
     | 
| 
      
 47 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 48 
     | 
    
         
            +
                                }
         
     | 
| 
      
 49 
     | 
    
         
            +
                                "dword"
         
     | 
| 
      
 50 
     | 
    
         
            +
                                {
         
     | 
| 
      
 51 
     | 
    
         
            +
                                    "english"
         
     | 
| 
      
 52 
     | 
    
         
            +
                                    {
         
     | 
| 
      
 53 
     | 
    
         
            +
                                        "GameLanguage"      "0"
         
     | 
| 
      
 54 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 55 
     | 
    
         
            +
                                    "french"
         
     | 
| 
      
 56 
     | 
    
         
            +
                                    {
         
     | 
| 
      
 57 
     | 
    
         
            +
                                        "GameLanguage"      "1"
         
     | 
| 
      
 58 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 59 
     | 
    
         
            +
                                    "german"
         
     | 
| 
      
 60 
     | 
    
         
            +
                                    {
         
     | 
| 
      
 61 
     | 
    
         
            +
                                        "GameLanguage"      "0"
         
     | 
| 
      
 62 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 63 
     | 
    
         
            +
                                    "italian"
         
     | 
| 
      
 64 
     | 
    
         
            +
                                    {
         
     | 
| 
      
 65 
     | 
    
         
            +
                                        "GameLanguage"      "2"
         
     | 
| 
      
 66 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 67 
     | 
    
         
            +
                                    "spanish"
         
     | 
| 
      
 68 
     | 
    
         
            +
                                    {
         
     | 
| 
      
 69 
     | 
    
         
            +
                                        "GameLanguage"      "4"
         
     | 
| 
      
 70 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 71 
     | 
    
         
            +
                                }
         
     | 
| 
      
 72 
     | 
    
         
            +
                            }
         
     | 
| 
      
 73 
     | 
    
         
            +
                        }
         
     | 
| 
      
 74 
     | 
    
         
            +
                        "Run Process"
         
     | 
| 
      
 75 
     | 
    
         
            +
                        {
         
     | 
| 
      
 76 
     | 
    
         
            +
                            "DirectX"
         
     | 
| 
      
 77 
     | 
    
         
            +
                            {
         
     | 
| 
      
 78 
     | 
    
         
            +
                                "process 1"     "%INSTALLDIR%\\redist\\DirectX\\DXSETUP.exe"
         
     | 
| 
      
 79 
     | 
    
         
            +
                                "command 1"     "/silent"
         
     | 
| 
      
 80 
     | 
    
         
            +
                                "Description"       "DirectX Installation"
         
     | 
| 
      
 81 
     | 
    
         
            +
                                "NoCleanUp"     "1"
         
     | 
| 
      
 82 
     | 
    
         
            +
                            }
         
     | 
| 
      
 83 
     | 
    
         
            +
                            "VC++"
         
     | 
| 
      
 84 
     | 
    
         
            +
                            {
         
     | 
| 
      
 85 
     | 
    
         
            +
                                "process 1"     "%INSTALLDIR%\\redist\\vcredist_x86.exe"
         
     | 
| 
      
 86 
     | 
    
         
            +
                                "command 1"     "/q:a"
         
     | 
| 
      
 87 
     | 
    
         
            +
                                "process 2"     "%INSTALLDIR%\\redist\\vcredist_x86_2005.exe"
         
     | 
| 
      
 88 
     | 
    
         
            +
                                "command 2"     "/q:a"
         
     | 
| 
      
 89 
     | 
    
         
            +
                                "Description"       "VC++ Redist Installation"
         
     | 
| 
      
 90 
     | 
    
         
            +
                                "NoCleanUp"     "1"
         
     | 
| 
      
 91 
     | 
    
         
            +
                            }
         
     | 
| 
      
 92 
     | 
    
         
            +
                            "PhysX Version"
         
     | 
| 
      
 93 
     | 
    
         
            +
                            {
         
     | 
| 
      
 94 
     | 
    
         
            +
                                "HasRunKey"     "HKEY_LOCAL_MACHINE\\SOFTWARE\\AGEIA Technologies"
         
     | 
| 
      
 95 
     | 
    
         
            +
                                "process 1"     "%INSTALLDIR%\\redist\\PhysX_9.09.1112_SystemSoftware.exe"
         
     | 
| 
      
 96 
     | 
    
         
            +
                                "command 1"     "/quiet"
         
     | 
| 
      
 97 
     | 
    
         
            +
                                "NoCleanUp"     "1"
         
     | 
| 
      
 98 
     | 
    
         
            +
                                "MinimumHasRunValue"        "9091112"
         
     | 
| 
      
 99 
     | 
    
         
            +
                            }
         
     | 
| 
      
 100 
     | 
    
         
            +
                        }
         
     | 
| 
      
 101 
     | 
    
         
            +
                    }
         
     | 
| 
      
 102 
     | 
    
         
            +
                    "kvsignatures"
         
     | 
| 
      
 103 
     | 
    
         
            +
                    {
         
     | 
| 
      
 104 
     | 
    
         
            +
                        "InstallScript"     "973f7d89125ad1fc782a970deb175cf84d48c49581ba3a76fedfefa8116a6d500459fd8df99285850ef99d767a83c2de009de5951607930557c937439908fbc1cc8156e963320c54080e7a1a634ccbf2e5f58883bd11bb2ed10c07be5af8e482d9a17d22a6fe40980124e5fced1c241f158b460941984c41432eeeb2aeaa01b1"
         
     | 
| 
      
 105 
     | 
    
         
            +
                    }        
         
     | 
| 
      
 106 
     | 
    
         
            +
                    EOS
         
     | 
| 
      
 107 
     | 
    
         
            +
                }
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                describe '.loadFromFile' do
         
     | 
| 
      
 110 
     | 
    
         
            +
                    it 'should successfully load from file' do
         
     | 
| 
      
 111 
     | 
    
         
            +
                        StringIO.open(valveDataFile) do |file|
         
     | 
| 
      
 112 
     | 
    
         
            +
                            SteamCodec::VDF::loadFromFile(file).should be_an_instance_of SteamCodec::VDF
         
     | 
| 
      
 113 
     | 
    
         
            +
                        end
         
     | 
| 
      
 114 
     | 
    
         
            +
                    end
         
     | 
| 
      
 115 
     | 
    
         
            +
                end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                describe '.load' do
         
     | 
| 
      
 118 
     | 
    
         
            +
                    it 'should successfully load' do
         
     | 
| 
      
 119 
     | 
    
         
            +
                        SteamCodec::VDF::load(valveDataFile).should be_an_instance_of SteamCodec::VDF
         
     | 
| 
      
 120 
     | 
    
         
            +
                    end
         
     | 
| 
      
 121 
     | 
    
         
            +
                end
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                describe 'key field' do
         
     | 
| 
      
 124 
     | 
    
         
            +
                    it 'should return value' do
         
     | 
| 
      
 125 
     | 
    
         
            +
                        SteamCodec::VDF::load(valveDataFile).InstallScript.Registry.should be_an_instance_of SteamCodec::KeyValues
         
     | 
| 
      
 126 
     | 
    
         
            +
                    end
         
     | 
| 
      
 127 
     | 
    
         
            +
                end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                describe '#isSignaturesValid?' do
         
     | 
| 
      
 130 
     | 
    
         
            +
                    it 'should check if signature is valid' do
         
     | 
| 
      
 131 
     | 
    
         
            +
                        SteamCodec::VDF.new.isSignaturesValid?(nil).should be_true
         
     | 
| 
      
 132 
     | 
    
         
            +
                        SteamCodec::VDF::load(valveDataFile).isSignaturesValid?(nil).should be_false
         
     | 
| 
      
 133 
     | 
    
         
            +
                    end
         
     | 
| 
      
 134 
     | 
    
         
            +
                end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
            end
         
     | 
    
        data/steam_codec.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # coding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            lib = File.expand_path('../lib', __FILE__)
         
     | 
| 
      
 3 
     | 
    
         
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'steam_codec/version'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            Gem::Specification.new do |spec|
         
     | 
| 
      
 7 
     | 
    
         
            +
              spec.name          = 'steam_codec'
         
     | 
| 
      
 8 
     | 
    
         
            +
              spec.version       = SteamCodec::VERSION
         
     | 
| 
      
 9 
     | 
    
         
            +
              spec.authors       = ['Dāvis']
         
     | 
| 
      
 10 
     | 
    
         
            +
              spec.email         = ['davispuh@gmail.com']
         
     | 
| 
      
 11 
     | 
    
         
            +
              spec.description   = 'Load, parse and manage various Steam client, Source Engine file formats. For example VDF and ACF'
         
     | 
| 
      
 12 
     | 
    
         
            +
              spec.summary       = 'Library for working with different Steam client (and Source engine) file formats.'
         
     | 
| 
      
 13 
     | 
    
         
            +
              spec.homepage      = 'https://github.com/davispuh/SteamCodec'
         
     | 
| 
      
 14 
     | 
    
         
            +
              spec.license       = 'UNLICENSE'
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              spec.files         = `git ls-files`.split($/)
         
     | 
| 
      
 17 
     | 
    
         
            +
              spec.executables   = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
         
     | 
| 
      
 18 
     | 
    
         
            +
              spec.test_files    = spec.files.grep(%r{^(test|spec|features)/})
         
     | 
| 
      
 19 
     | 
    
         
            +
              spec.require_paths = ['lib']
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              spec.add_runtime_dependency 'insensitive_hash', '~> 0.3', '>= 0.3.3'
         
     | 
| 
      
 22 
     | 
    
         
            +
              spec.add_development_dependency 'bundler'
         
     | 
| 
      
 23 
     | 
    
         
            +
              spec.add_development_dependency 'rake'
         
     | 
| 
      
 24 
     | 
    
         
            +
              spec.add_development_dependency 'rspec'
         
     | 
| 
      
 25 
     | 
    
         
            +
              spec.add_development_dependency 'yard'
         
     | 
| 
      
 26 
     | 
    
         
            +
              spec.add_development_dependency 'simplecov'
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,159 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: steam_codec
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.1
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Dāvis
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2013-09-16 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: insensitive_hash
         
     | 
| 
      
 15 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 16 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 19 
     | 
    
         
            +
                    version: '0.3'
         
     | 
| 
      
 20 
     | 
    
         
            +
                - - '>='
         
     | 
| 
      
 21 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 22 
     | 
    
         
            +
                    version: 0.3.3
         
     | 
| 
      
 23 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 24 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 25 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 26 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 27 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 28 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 29 
     | 
    
         
            +
                    version: '0.3'
         
     | 
| 
      
 30 
     | 
    
         
            +
                - - '>='
         
     | 
| 
      
 31 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 32 
     | 
    
         
            +
                    version: 0.3.3
         
     | 
| 
      
 33 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 34 
     | 
    
         
            +
              name: bundler
         
     | 
| 
      
 35 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 36 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 37 
     | 
    
         
            +
                - - '>='
         
     | 
| 
      
 38 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 39 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 40 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 41 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 42 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 43 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 44 
     | 
    
         
            +
                - - '>='
         
     | 
| 
      
 45 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 46 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 47 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 48 
     | 
    
         
            +
              name: rake
         
     | 
| 
      
 49 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 50 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 51 
     | 
    
         
            +
                - - '>='
         
     | 
| 
      
 52 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 53 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 54 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 55 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 56 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 57 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 58 
     | 
    
         
            +
                - - '>='
         
     | 
| 
      
 59 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 60 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 61 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 62 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 63 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 64 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 65 
     | 
    
         
            +
                - - '>='
         
     | 
| 
      
 66 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 67 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 68 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 69 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 70 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 71 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 72 
     | 
    
         
            +
                - - '>='
         
     | 
| 
      
 73 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 74 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 75 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 76 
     | 
    
         
            +
              name: yard
         
     | 
| 
      
 77 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 78 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 79 
     | 
    
         
            +
                - - '>='
         
     | 
| 
      
 80 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 81 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 82 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 83 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 84 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 85 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 86 
     | 
    
         
            +
                - - '>='
         
     | 
| 
      
 87 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 88 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 89 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 90 
     | 
    
         
            +
              name: simplecov
         
     | 
| 
      
 91 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 92 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 93 
     | 
    
         
            +
                - - '>='
         
     | 
| 
      
 94 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 95 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 96 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 97 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 98 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 99 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 100 
     | 
    
         
            +
                - - '>='
         
     | 
| 
      
 101 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 102 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 103 
     | 
    
         
            +
            description: Load, parse and manage various Steam client, Source Engine file formats.
         
     | 
| 
      
 104 
     | 
    
         
            +
              For example VDF and ACF
         
     | 
| 
      
 105 
     | 
    
         
            +
            email:
         
     | 
| 
      
 106 
     | 
    
         
            +
            - davispuh@gmail.com
         
     | 
| 
      
 107 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 108 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 109 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 110 
     | 
    
         
            +
            files:
         
     | 
| 
      
 111 
     | 
    
         
            +
            - .gitignore
         
     | 
| 
      
 112 
     | 
    
         
            +
            - .travis.yml
         
     | 
| 
      
 113 
     | 
    
         
            +
            - .yardopts
         
     | 
| 
      
 114 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 115 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 116 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 117 
     | 
    
         
            +
            - UNLICENSE
         
     | 
| 
      
 118 
     | 
    
         
            +
            - lib/steam_codec.rb
         
     | 
| 
      
 119 
     | 
    
         
            +
            - lib/steam_codec/ACF.rb
         
     | 
| 
      
 120 
     | 
    
         
            +
            - lib/steam_codec/key_values.rb
         
     | 
| 
      
 121 
     | 
    
         
            +
            - lib/steam_codec/value_array.rb
         
     | 
| 
      
 122 
     | 
    
         
            +
            - lib/steam_codec/vdf.rb
         
     | 
| 
      
 123 
     | 
    
         
            +
            - lib/steam_codec/version.rb
         
     | 
| 
      
 124 
     | 
    
         
            +
            - spec/acf_spec.rb
         
     | 
| 
      
 125 
     | 
    
         
            +
            - spec/key_values_spec.rb
         
     | 
| 
      
 126 
     | 
    
         
            +
            - spec/spec_helper.rb
         
     | 
| 
      
 127 
     | 
    
         
            +
            - spec/vdf_spec.rb
         
     | 
| 
      
 128 
     | 
    
         
            +
            - steam_codec.gemspec
         
     | 
| 
      
 129 
     | 
    
         
            +
            homepage: https://github.com/davispuh/SteamCodec
         
     | 
| 
      
 130 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 131 
     | 
    
         
            +
            - UNLICENSE
         
     | 
| 
      
 132 
     | 
    
         
            +
            metadata: {}
         
     | 
| 
      
 133 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 134 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 135 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 136 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 137 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 138 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 139 
     | 
    
         
            +
              - - '>='
         
     | 
| 
      
 140 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 141 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 142 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 143 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 144 
     | 
    
         
            +
              - - '>='
         
     | 
| 
      
 145 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 146 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 147 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 148 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 149 
     | 
    
         
            +
            rubygems_version: 2.0.7
         
     | 
| 
      
 150 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 151 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 152 
     | 
    
         
            +
            summary: Library for working with different Steam client (and Source engine) file
         
     | 
| 
      
 153 
     | 
    
         
            +
              formats.
         
     | 
| 
      
 154 
     | 
    
         
            +
            test_files:
         
     | 
| 
      
 155 
     | 
    
         
            +
            - spec/acf_spec.rb
         
     | 
| 
      
 156 
     | 
    
         
            +
            - spec/key_values_spec.rb
         
     | 
| 
      
 157 
     | 
    
         
            +
            - spec/spec_helper.rb
         
     | 
| 
      
 158 
     | 
    
         
            +
            - spec/vdf_spec.rb
         
     | 
| 
      
 159 
     | 
    
         
            +
            has_rdoc: 
         
     |