keyed_archive 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 20bed81f6f133648cf631d3216523aeddbc14eeb
4
- data.tar.gz: 2d7912ef9102f3ece3b77a64fc872ed1207676c2
2
+ SHA256:
3
+ metadata.gz: d932ce3e1c5bf7832937aeba3b66736cc94b9036ae9a242e32ef3d4310cece72
4
+ data.tar.gz: 74e5020a25d5346e1789fd12d4e4038c00f64c99a9a44f8906bbfa47d677f879
5
5
  SHA512:
6
- metadata.gz: 3762da9e73d7512f57c2132b04694a94b8b7b34711253b1b1785b88a5c7835c5d3ea558c32094bb5dde4cc7f68b3ffbd1ea0fb5ff7c20f9cfdc6946f1d292c4d
7
- data.tar.gz: e68c08996edb3c3e0932c1c5e842de86dd56e263a95ae73ebeba886dd66aea00ec486b428e6878a875b146aed104f61e2cc8254085f3fa062e43dd6f9f914553
6
+ metadata.gz: 0a0152d78b35fd324d3c48838ce21c19d71530e5d0234dabe668dd89e5dd88fae5f51539dbf6a62162a52fd4fabf1ac4e7ecba7540170acf277c75d5122e53d5
7
+ data.tar.gz: 5051e71618ab45823bd96fa1e1e00ec0d33c5311af024da0a1e2ec14e31115570b523324c6f64f060bf434da3559c864de0df2f72572b64c81a124280ea3daa6
data/README.md CHANGED
@@ -18,6 +18,22 @@ Or install it yourself as:
18
18
 
19
19
  ## Usage
20
20
 
21
+ ### Basic Syntax
22
+
23
+ KeyedArchive supports the initializer arguments which CFPropertyList supports: `:file` to read data directly from a file and `:data` to read data from a variable that already has your NSKeyedArchive data within it.
24
+
25
+ ```ruby
26
+
27
+ # Create KeyedArchive by reading a file directly
28
+ keyed_archive_from_file = KeyedArchive.new(:file => "path/to/file.plist")
29
+
30
+ # Create KeyedArchive from a variable holding content which can
31
+ # be parsed as a plist, either XML or binary.
32
+ file_contents = File.read("path/to/file.plist")
33
+ keyed_archive_from_variable = KeyedArchive.new(:data => file_contents)
34
+
35
+ ```
36
+
21
37
  ### Opening a keyed archive
22
38
  ```xml
23
39
  <?xml version="1.0" encoding="UTF-8"?>
@@ -48,11 +64,12 @@ Or install it yourself as:
48
64
  require 'keyed_archive'
49
65
 
50
66
  filename = "path/to/file.plist"
51
- keyed_archive = KeyedArchive.new("path/to/file.plist")
52
- keyed_archive.archiver # "NSKeyedArchiver"
53
- keyed_archive.objects # ["$null"]
54
- keyed_archive.top # {"root"=>{"CF$UID"=>1}}
55
- keyed_archive.version # 100000
67
+ keyed_archive = KeyedArchive.new(:file => "path/to/file.plist")
68
+ keyed_archive.archiver # "NSKeyedArchiver"
69
+ keyed_archive.objects # ["$null"]
70
+ keyed_archive.top # {"root"=>1}
71
+ keyed_archive.version # 100000
72
+ keyed_archive.unpacked_top # {"root"=>nil}
56
73
  ```
57
74
 
58
75
  ### Unpacking keyed archive objects
@@ -88,14 +105,15 @@ keyed_archive.version # 100000
88
105
  ```ruby
89
106
  require 'keyed_archive'
90
107
 
91
- keyed_archive = KeyedArchive.new("path/to/file.plist")
92
- keyed_archive.objects # ["$null", "value", {"reference"=>{"CF$UID"=>3}}, {"key"=>{"CF$UID"=>1}}]
93
- keyed_archive.unpacked_objects() # ["$null", {"key"=>"value"}]
108
+ keyed_archive = KeyedArchive.new(:file => "path/to/file.plist")
109
+ keyed_archive.objects # ["$null", {"key"=>"value"}]
110
+ keyed_archive.top # {"root"=>1}
111
+ keyed_archive.unpacked_top() # {"root"=>{"key"=>"value"}}
94
112
  ```
95
113
 
96
114
  ## Contributing
97
115
 
98
- 1. Fork it ( http://github.com/<my-github-username>/keyed_archive/fork )
116
+ 1. Fork it ( http://github.com/\<my-github-username\>/keyed_archive/fork )
99
117
  2. Create your feature branch (`git checkout -b my-new-feature`)
100
118
  3. Commit your changes (`git commit -am 'Add some feature'`)
101
119
  4. Push to the branch (`git push origin my-new-feature`)
@@ -17,9 +17,9 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ["lib"]
19
19
 
20
- spec.add_dependency "CFPropertyList", "~> 2.2.7"
20
+ spec.add_dependency "CFPropertyList", "~> 3.0"
21
21
 
22
- spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "bundler", "~> 2.1"
23
23
  spec.add_development_dependency "rake"
24
- spec.add_development_dependency "rspec", "~> 2.14.1"
24
+ spec.add_development_dependency "rspec", "~> 3.9"
25
25
  end
@@ -1,18 +1,31 @@
1
1
  require 'cfpropertylist'
2
2
 
3
- require "keyed_archive/unpacked_objects"
4
- require "keyed_archive/version"
3
+ require 'keyed_archive/unpacked_objects'
4
+ require 'keyed_archive/version'
5
5
 
6
6
  class KeyedArchive
7
7
  attr_accessor :archiver, :objects, :top, :version
8
8
 
9
- def initialize(file)
10
- plist = CFPropertyList::List.new(:file => file)
11
- data = CFPropertyList.native_types(plist.value)
9
+ #
10
+ # Take the same sort of arguments as CFPropertyList
11
+ # :file => filename to load
12
+ # :data => variable with the data to load directly
13
+ def initialize(opts={})
14
+ blob = opts[:data]
15
+ filename = opts[:file]
12
16
 
13
- @archiver = data['$archiver']
14
- @objects = data['$objects']
15
- @top = data['$top']
16
- @version = data['$version']
17
+ plist = CFPropertyList::List.new(:file => filename) unless filename.nil? or !File.exists?(filename)
18
+ plist = CFPropertyList::List.new(:data => blob) unless blob.nil? or blob.length < 1
19
+
20
+ if !plist.nil?
21
+ data = CFPropertyList.native_types(plist.value)
22
+
23
+ @archiver = data['$archiver']
24
+ @objects = data['$objects']
25
+ @top = data['$top']
26
+ @version = data['$version']
27
+ else
28
+ raise "Plist not created"
29
+ end
17
30
  end
18
31
  end
@@ -1,31 +1,75 @@
1
1
  class KeyedArchive
2
- def unpacked_objects
3
- objects = @objects.clone
4
- unpacked_objects = []
5
-
6
- objects.each_with_index do |object, index|
7
- if object.is_a? Hash
8
- object.each_pair do |key, value|
9
- if value.is_a? Hash
10
- uid = value['CF$UID']
11
-
12
- if uid
13
- new_object = {}
14
- new_object[key] = @objects[uid]
15
- objects.push new_object
16
- unpacked_objects.delete_at(index - 1)
17
- end
18
- else
19
- new_object = {}
20
- new_object[key] = value
21
- unpacked_objects.push new_object
2
+
3
+ # Loops through the entries within '$top'
4
+ # to replace any values that are pointers to objects.
5
+ def unpacked_top
6
+
7
+ # Create the return value
8
+ unpacked_top = Hash.new
9
+
10
+ # Loop over each pair in the '$top' hash
11
+ # to recursively replace the values
12
+ @top.each_pair do |key, value|
13
+ unpacked_top[key] = recursive_replace(value, -1, [])
14
+ end
15
+
16
+ # Politely return, our job is done
17
+ return unpacked_top
18
+ end
19
+
20
+ private
21
+
22
+ # Handles the recursive replacement of values within the
23
+ # '$objects' array. Tracks the object locations it has
24
+ # already touched to prevent infinite loops.
25
+ def recursive_replace(value, current_location, locations)
26
+ # By default we just return the value itself, usually a String
27
+ to_return = value
28
+
29
+ # If the value is really representing nil, change it to nil
30
+ if value.is_a? String and value == "$null"
31
+ to_return = nil
32
+ end
33
+
34
+ # If we have an Integer, we want to bring in the object
35
+ # that Integer points to
36
+ if value.is_a? Integer
37
+
38
+ # If we ever find a reference to one of our parents, just stop where we are
39
+ if locations.include?(current_location)
40
+ to_return = value
41
+ else
42
+ to_return = recursive_replace(@objects[value], value, locations.clone.push(current_location))
43
+ end
44
+
45
+ # If we have a Hash, we want to check each entry
46
+ # and replace any values which need it
47
+ elsif value.is_a? Hash
48
+
49
+ # Build up a new Hash
50
+ to_return = Hash.new
51
+
52
+ # Loop over the pairs to check the key, value, or both
53
+ value.each_pair do |tmp_key, tmp_value|
54
+
55
+ # If this points to an array of objects,
56
+ # then we should bring those values in
57
+ if tmp_key == "NS.objects" or tmp_key == "NS.keys"
58
+ new_array = Array.new
59
+ tmp_value.each do |entry|
60
+ new_array.push(recursive_replace(entry, entry, locations.clone.push(current_location)))
22
61
  end
62
+ to_return[tmp_key] = new_array
63
+
64
+ # Otherwise, we just want to replace the value with
65
+ # its recursive version
66
+ else
67
+ to_return[tmp_key] = recursive_replace(tmp_value, tmp_value, locations.clone.push(current_location))
23
68
  end
24
- else
25
- unpacked_objects.push object
26
69
  end
27
70
  end
28
71
 
29
- return unpacked_objects
72
+ # Give back the value, politely
73
+ return to_return
30
74
  end
31
75
  end
@@ -1,3 +1,3 @@
1
1
  class KeyedArchive
2
- VERSION = "0.1.0"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -2,29 +2,35 @@ require "keyed_archive"
2
2
 
3
3
  describe KeyedArchive, "#initialize" do
4
4
  let(:filename) { 'spec/fixtures/empty.plist' }
5
+ let(:blob) { File.read('spec/fixtures/empty.bplist') }
5
6
 
6
7
  it "should create an instance" do
7
- keyed_archive = KeyedArchive.new(filename)
8
+ keyed_archive = KeyedArchive.new(:file => filename)
8
9
  expect(keyed_archive).to be_instance_of(KeyedArchive)
9
10
  end
10
11
 
11
12
  it "should set the archiver" do
12
- keyed_archive = KeyedArchive.new(filename)
13
+ keyed_archive = KeyedArchive.new(:file => filename)
13
14
  expect(keyed_archive.archiver).to be_a(String)
14
15
  end
15
16
 
16
17
  it "should set the objects" do
17
- keyed_archive = KeyedArchive.new(filename)
18
+ keyed_archive = KeyedArchive.new(:file => filename)
18
19
  expect(keyed_archive.objects).to be_an(Array)
19
20
  end
20
21
 
21
22
  it "should set the top" do
22
- keyed_archive = KeyedArchive.new(filename)
23
+ keyed_archive = KeyedArchive.new(:file => filename)
23
24
  expect(keyed_archive.top).to be_a(Hash)
24
25
  end
25
26
 
26
27
  it "should set the version" do
27
- keyed_archive = KeyedArchive.new(filename)
28
+ keyed_archive = KeyedArchive.new(:file => filename)
29
+ expect(keyed_archive.version).to be_an(Integer)
30
+ end
31
+
32
+ it "should read data from variables as well" do
33
+ keyed_archive = KeyedArchive.new(:data => blob)
28
34
  expect(keyed_archive.version).to be_an(Integer)
29
35
  end
30
36
  end
@@ -2,10 +2,17 @@ require "keyed_archive/unpacked_objects"
2
2
 
3
3
  shared_examples "unpack" do
4
4
  it "should unpack objects" do
5
- keyed_archive = KeyedArchive.new(filename)
6
- unpacked_objects = keyed_archive.unpacked_objects()
7
- fixture_archive = KeyedArchive.new(fixture)
8
- expect(unpacked_objects).to eq(fixture_archive.objects)
5
+ keyed_archive = KeyedArchive.new(:file => filename)
6
+ unpacked_top = keyed_archive.unpacked_top()
7
+ fixture_archive = KeyedArchive.new(:file => fixture)
8
+ expect(unpacked_top["root"]).to eq(fixture_archive.objects[1]["key"])
9
+ end
10
+
11
+ it "should handle variables" do
12
+ keyed_archive = KeyedArchive.new(:data => blob)
13
+ unpacked_top = keyed_archive.unpacked_top()
14
+ fixture_archive = KeyedArchive.new(:file => fixture)
15
+ expect(unpacked_top["root"]).to eq(fixture_archive.objects[1]["key"])
9
16
  end
10
17
  end
11
18
 
@@ -13,6 +20,7 @@ describe KeyedArchive, "#unpack" do
13
20
  context "single reference" do
14
21
  it_behaves_like "unpack" do
15
22
  let(:filename) { "spec/fixtures/single_object_reference.plist" }
23
+ let(:blob) { File.read("spec/fixtures/single_object_reference.plist") }
16
24
  let(:fixture) { "spec/fixtures/single_object_reference_unpacked.plist" }
17
25
  end
18
26
  end
@@ -20,6 +28,7 @@ describe KeyedArchive, "#unpack" do
20
28
  context "double reference" do
21
29
  it_behaves_like "unpack" do
22
30
  let(:filename) { "spec/fixtures/double_object_reference.plist" }
31
+ let(:blob) { File.read("spec/fixtures/double_object_reference.plist") }
23
32
  let(:fixture) { "spec/fixtures/double_object_reference_unpacked.plist" }
24
33
  end
25
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: keyed_archive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Young
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-22 00:00:00.000000000 Z
11
+ date: 2020-09-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: CFPropertyList
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 2.2.7
19
+ version: '3.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 2.2.7
26
+ version: '3.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.5'
33
+ version: '2.1'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.5'
40
+ version: '2.1'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,15 +58,15 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 2.14.1
61
+ version: '3.9'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 2.14.1
69
- description:
68
+ version: '3.9'
69
+ description:
70
70
  email:
71
71
  - paulyoungonline@gmail.com
72
72
  executables: []
@@ -85,7 +85,9 @@ files:
85
85
  - lib/keyed_archive/version.rb
86
86
  - spec/fixtures/double_object_reference.plist
87
87
  - spec/fixtures/double_object_reference_unpacked.plist
88
+ - spec/fixtures/empty.bplist
88
89
  - spec/fixtures/empty.plist
90
+ - spec/fixtures/single_object_reference.bplist
89
91
  - spec/fixtures/single_object_reference.plist
90
92
  - spec/fixtures/single_object_reference_unpacked.plist
91
93
  - spec/keyed_archive_spec.rb
@@ -94,7 +96,7 @@ homepage: https://github.com/paulyoung/keyed_archive
94
96
  licenses:
95
97
  - MIT
96
98
  metadata: {}
97
- post_install_message:
99
+ post_install_message:
98
100
  rdoc_options: []
99
101
  require_paths:
100
102
  - lib
@@ -109,15 +111,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
111
  - !ruby/object:Gem::Version
110
112
  version: '0'
111
113
  requirements: []
112
- rubyforge_project:
113
- rubygems_version: 2.2.2
114
- signing_key:
114
+ rubygems_version: 3.1.2
115
+ signing_key:
115
116
  specification_version: 4
116
117
  summary: A Ruby gem for working with files produced by NSKeyedArchiver.
117
118
  test_files:
118
119
  - spec/fixtures/double_object_reference.plist
119
120
  - spec/fixtures/double_object_reference_unpacked.plist
121
+ - spec/fixtures/empty.bplist
120
122
  - spec/fixtures/empty.plist
123
+ - spec/fixtures/single_object_reference.bplist
121
124
  - spec/fixtures/single_object_reference.plist
122
125
  - spec/fixtures/single_object_reference_unpacked.plist
123
126
  - spec/keyed_archive_spec.rb