plist-3.1.0/ 0000755 0001750 0001750 00000000000 12131276043 012223 5 ustar boutil boutil plist-3.1.0/README.rdoc 0000644 0001750 0001750 00000013460 12131276043 014035 0 ustar boutil boutil = All-purpose Property List manipulation library
Plist is a library to manipulate Property List files, also known as plists. It can parse plist files into native Ruby data structures as well as generating new plist files from your Ruby objects.
== Usage
=== Parsing
result = Plist::parse_xml('path/to/example.plist')
result.class
=> Hash
"#{result['FirstName']} #{result['LastName']}"
=> "John Public"
result['ZipPostal']
=> "12345"
==== Example Property List
FirstName
John
LastName
Public
StreetAddr1
123 Anywhere St.
StateProv
CA
City
Some Town
CountryName
United States
AreaCode
555
LocalPhoneNumber
5551212
ZipPostal
12345
=== Generation
plist also provides the ability to generate plists from Ruby objects. The following Ruby classes are converted into native plist types:
Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time, true, false
* +Array+ and +Hash+ are both recursive; their elements will be converted into plist nodes inside the and containers (respectively).
* +IO+ (and its descendants) and +StringIO+ objects are read from and their contents placed in a element.
* User classes may implement +to_plist_node+ to dictate how they should be serialized; otherwise the object will be passed to Marshal.dump and the result placed in a element. See below for more details.
==== Creating a plist
There are two ways to generate complete plists. Given an object:
obj = [1, :two, {'c' => 0xd}]
If you've mixed in Plist::Emit (which is already done for +Array+ and +Hash+), you can simply call +to_plist+:
obj.to_plist
This is equivalent to calling Plist::Emit.dump(obj). Either one will yield:
1
two
c
13
You can also dump plist fragments by passing +false+ as the second parameter:
Plist::Emit.dump('holy cow!', false)
=> "holy cow!"
==== Custom serialization
If your class can be safely coerced into a native plist datatype, you can implement +to_plist_node+. Upon encountering an object of a class it doesn't recognize, the plist library will check to see if it responds to +to_plist_node+, and if so, insert the result of that call into the plist output.
An example:
class MyFancyString
...
def to_plist_node
return "#{self.defancify}"
end
end
When you attempt to serialize a +MyFancyString+ object, the +to_plist_node+ method will be called and the object's contents will be defancified and placed in the plist.
If for whatever reason you can't add this method, your object will be serialized with Marshal.dump instead.
== Links
[Project Page] http://plist.rubyforge.org
[GitHub] http://github.com/bleything/plist
[RDoc] http://plist.rubyforge.org
== Credits
plist is maintained by Ben Bleything and Patrick May . Patrick wrote most of the code; Ben is a recent addition to the project, having merged in his plist generation library.
Other folks who have helped along the way:
[Martin Dittus] who pointed out that +Time+ wasn't enough for plist Dates, especially those in ~/Library/Cookies/Cookies.plist
[Chuck Remes] who pushed Patrick towards implementing #to_plist
[Mat Schaffer] who supplied code and test cases for elements
[Michael Granger] for encouragement and help
[Carsten Bormann, Chris Hoffman, Dana Contreras, Hongli Lai, Johan Sørensen] for contributing Ruby 1.9.x compatibility fixes
== License and Copyright
plist is released under the MIT License.
Portions of the code (notably the Rakefile) contain code pulled and/or adapted from other projects. These files contain a comment at the top describing what was used.
=== MIT License
Copyright (c) 2006-2010, Ben Bleything and Patrick May
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
plist-3.1.0/metadata.yml 0000644 0001750 0001750 00000003566 12131276043 014540 0 ustar boutil boutil --- !ruby/object:Gem::Specification
name: plist
version: !ruby/object:Gem::Version
prerelease: false
segments:
- 3
- 1
- 0
version: 3.1.0
platform: ruby
authors:
- Ben Bleything and Patrick May
autorequire: plist
bindir: bin
cert_chain: []
date: 2010-02-23 00:00:00 -08:00
default_executable:
dependencies: []
description: |
Plist is a library to manipulate Property List files, also known as plists. It can parse plist files into native Ruby data structures as well as generating new plist files from your Ruby objects.
email:
executables: []
extensions: []
extra_rdoc_files: []
files:
- Rakefile
- README.rdoc
- CHANGELOG
- LICENSE
- lib/plist/generator.rb
- lib/plist/parser.rb
- lib/plist.rb
- test/test_data_elements.rb
- test/test_generator.rb
- test/test_generator_basic_types.rb
- test/test_generator_collections.rb
- test/test_parser.rb
- test/assets/AlbumData.xml
- test/assets/commented.plist
- test/assets/Cookies.plist
- test/assets/example_data.bin
- test/assets/example_data.jpg
- test/assets/example_data.plist
- test/assets/test_data_elements.plist
- test/assets/test_empty_key.plist
has_rdoc: true
homepage: http://plist.rubyforge.org
licenses: []
post_install_message:
rdoc_options: []
require_paths:
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
segments:
- 0
version: "0"
required_rubygems_version: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
segments:
- 0
version: "0"
requirements: []
rubyforge_project: plist
rubygems_version: 1.3.6
signing_key:
specification_version: 3
summary: All-purpose Property List manipulation library.
test_files:
- test/test_data_elements.rb
- test/test_generator.rb
- test/test_generator_basic_types.rb
- test/test_generator_collections.rb
- test/test_parser.rb
plist-3.1.0/test/ 0000755 0001750 0001750 00000000000 12131276043 013202 5 ustar boutil boutil plist-3.1.0/test/test_parser.rb 0000644 0001750 0001750 00000005203 12131276043 016062 0 ustar boutil boutil #!/usr/bin/env ruby
require 'test/unit'
require 'plist'
class TestParser < Test::Unit::TestCase
def test_Plist_parse_xml
result = Plist::parse_xml("test/assets/AlbumData.xml")
# dict
assert_kind_of( Hash, result )
expected = [
"List of Albums",
"Minor Version",
"Master Image List",
"Major Version",
"List of Keywords",
"Archive Path",
"List of Rolls",
"Application Version"
]
assert_equal( expected.sort, result.keys.sort )
# array
assert_kind_of( Array, result["List of Rolls"] )
assert_equal( [ {"PhotoCount"=>1,
"KeyList"=>["7"],
"Parent"=>999000,
"Album Type"=>"Regular",
"AlbumName"=>"Roll 1",
"AlbumId"=>6}],
result["List of Rolls"] )
# string
assert_kind_of( String, result["Application Version"] )
assert_equal( "5.0.4 (263)", result["Application Version"] )
# integer
assert_kind_of( Integer, result["Major Version"] )
assert_equal( 2, result["Major Version"] )
# true
assert_kind_of( TrueClass, result["List of Albums"][0]["Master"] )
assert( result["List of Albums"][0]["Master"] )
# false
assert_kind_of( FalseClass, result["List of Albums"][1]["SlideShowUseTitles"] )
assert( ! result["List of Albums"][1]["SlideShowUseTitles"] )
end
# uncomment this test to work on speed optimization
#def test_load_something_big
# plist = Plist::parse_xml( "~/Pictures/iPhoto Library/AlbumData.xml" )
#end
# date fields are credited to
def test_date_fields
result = Plist::parse_xml("test/assets/Cookies.plist")
assert_kind_of( DateTime, result.first['Expires'] )
assert_equal DateTime.parse( "2007-10-25T12:36:35Z" ), result.first['Expires']
end
# bug fix for empty
# reported by Matthias Peick
# reported and fixed by Frederik Seiffert
def test_empty_dict_key
data = Plist::parse_xml("test/assets/test_empty_key.plist");
assert_equal("2", data['key']['subkey'])
end
# bug fix for decoding entities
# reported by Matthias Peick
def test_decode_entities
data = Plist::parse_xml('Fish & Chips')
assert_equal('Fish & Chips', data)
end
def test_comment_handling_and_empty_plist
assert_nothing_raised do
assert_nil( Plist::parse_xml( File.read('test/assets/commented.plist') ) )
end
end
def test_filename_or_xml_is_stringio
require 'stringio'
str = StringIO.new
data = Plist::parse_xml(str)
assert_nil data
end
end
__END__
plist-3.1.0/test/test_generator_collections.rb 0000644 0001750 0001750 00000002575 12131276043 021163 0 ustar boutil boutil #!/usr/bin/env ruby
require 'test/unit'
require 'plist'
class TestGeneratorCollections < Test::Unit::TestCase
def test_array
expected = <
1
2
3
END
assert_equal expected, [1,2,3].to_plist(false)
end
def test_empty_array
expected = <
END
assert_equal expected, [].to_plist(false)
end
def test_hash
expected = <
abc
123
foo
bar
END
# thanks to recent changes in the generator code, hash keys are sorted before emission,
# so multi-element hash tests should be reliable. We're testing that here too.
assert_equal expected, {:foo => :bar, :abc => 123}.to_plist(false)
end
def test_empty_hash
expected = <
END
assert_equal expected, {}.to_plist(false)
end
def test_hash_with_array_element
expected = <
ary
1
b
3
END
assert_equal expected, {:ary => [1,:b,'3']}.to_plist(false)
end
def test_array_with_hash_element
expected = <
foo
bar
b
3
END
assert_equal expected, [{:foo => 'bar'}, :b, 3].to_plist(false)
end
end
plist-3.1.0/test/test_data_elements.rb 0000644 0001750 0001750 00000006735 12131276043 017406 0 ustar boutil boutil #!/usr/bin/env ruby
require 'test/unit'
require 'plist'
require 'stringio'
class MarshalableObject
attr_accessor :foo
def initialize(str)
@foo = str
end
end
class TestDataElements < Test::Unit::TestCase
def setup
@result = Plist.parse_xml( 'test/assets/test_data_elements.plist' )
end
def test_data_object_header
expected = < element below contains a Ruby object which has been serialized with Marshal.dump. -->
BAhvOhZNYXJzaGFsYWJsZU9iamVjdAY6CUBmb28iHnRoaXMgb2JqZWN0IHdhcyBtYXJz
aGFsZWQ=
END
expected_elements = expected.chomp.split( "\n" )
actual = Plist::Emit.dump( Object.new, false )
actual_elements = actual.chomp.split( "\n" )
# check for header
assert_equal expected_elements.shift, actual_elements.shift
# check for opening and closing data tags
assert_equal expected_elements.shift, actual_elements.shift
assert_equal expected_elements.pop, actual_elements.pop
end
def test_marshal_round_trip
expected = MarshalableObject.new('this object was marshaled')
actual = Plist.parse_xml( Plist::Emit.dump(expected, false) )
assert_kind_of expected.class, actual
assert_equal expected.foo, actual.foo
end
def test_generator_io_and_file
expected = <
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
END
expected.chomp!
fd = IO.sysopen('test/assets/example_data.bin')
io = IO.open(fd, 'r')
# File is a subclass of IO, so catching IO in the dispatcher should work for File as well...
f = File.open('test/assets/example_data.bin')
assert_equal expected, Plist::Emit.dump(io, false).chomp
assert_equal expected, Plist::Emit.dump(f, false).chomp
assert_instance_of StringIO, @result['io']
assert_instance_of StringIO, @result['file']
io.rewind
f.rewind
assert_equal io.read, @result['io'].read
assert_equal f.read, @result['file'].read
io.close
f.close
end
def test_generator_string_io
expected = <
dGhpcyBpcyBhIHN0cmluZ2lvIG9iamVjdA==
END
sio = StringIO.new('this is a stringio object')
assert_equal expected.chomp, Plist::Emit.dump(sio, false).chomp
assert_instance_of StringIO, @result['stringio']
sio.rewind
assert_equal sio.read, @result['stringio'].read
end
# this functionality is credited to Mat Schaffer,
# who discovered the plist with the data tag
# supplied the test data, and provided the parsing code.
def test_data
# test reading plist elements
data = Plist::parse_xml("test/assets/example_data.plist");
assert_equal( File.open("test/assets/example_data.jpg"){|f| f.read }, data['image'].read )
# test writing data elements
expected = File.read("test/assets/example_data.plist")
result = data.to_plist
#File.open('result.plist', 'w') {|f|f.write(result)} # debug
assert_equal( expected, result )
# Test changing the object in the plist to a StringIO and writing.
# This appears extraneous given that plist currently returns a StringIO,
# so the above writing test also flexes StringIO#to_plist_node.
# However, the interface promise is to return an IO, not a particular class.
# plist used to return Tempfiles, which was changed solely for performance reasons.
data['image'] = StringIO.new( File.read("test/assets/example_data.jpg"))
assert_equal(expected, data.to_plist )
end
end
plist-3.1.0/test/test_generator.rb 0000644 0001750 0001750 00000002162 12131276043 016555 0 ustar boutil boutil #!/usr/bin/env ruby
require 'test/unit'
require 'plist'
class SerializableObject
attr_accessor :foo
def initialize(str)
@foo = str
end
def to_plist_node
return "#{CGI::escapeHTML @foo}"
end
end
class TestGenerator < Test::Unit::TestCase
def test_to_plist_vs_plist_emit_dump_no_envelope
source = [1, :b, true]
to_plist = source.to_plist(false)
plist_emit_dump = Plist::Emit.dump(source, false)
assert_equal to_plist, plist_emit_dump
end
def test_to_plist_vs_plist_emit_dump_with_envelope
source = [1, :b, true]
to_plist = source.to_plist
plist_emit_dump = Plist::Emit.dump(source)
assert_equal to_plist, plist_emit_dump
end
def test_dumping_serializable_object
str = 'this object implements #to_plist_node'
so = SerializableObject.new(str)
assert_equal "#{str}", Plist::Emit.dump(so, false)
end
def test_write_plist
data = [1, :two, {:c => 'dee'}]
data.save_plist('test.plist')
file = File.open('test.plist') {|f| f.read}
assert_equal file, data.to_plist
File.unlink('test.plist')
end
end
plist-3.1.0/test/test_generator_basic_types.rb 0000644 0001750 0001750 00000003002 12131276043 021134 0 ustar boutil boutil #!/usr/bin/env ruby
require 'test/unit'
require 'plist'
class TestGeneratorBasicTypes < Test::Unit::TestCase
def wrap(tag, content)
return "<#{tag}>#{content}#{tag}>"
end
def test_strings
expected = wrap('string', 'testdata')
assert_equal expected, Plist::Emit.dump('testdata', false).chomp
assert_equal expected, Plist::Emit.dump(:testdata, false).chomp
end
def test_strings_with_escaping
expected = wrap('string', "<Fish & Chips>")
assert_equal expected, Plist::Emit.dump('', false).chomp
end
def test_integers
[42, 2376239847623987623, -8192].each do |i|
assert_equal wrap('integer', i), Plist::Emit.dump(i, false).chomp
end
end
def test_floats
[3.14159, -38.3897, 2398476293847.9823749872349980].each do |i|
assert_equal wrap('real', i), Plist::Emit.dump(i, false).chomp
end
end
def test_booleans
assert_equal "", Plist::Emit.dump(true, false).chomp
assert_equal "", Plist::Emit.dump(false, false).chomp
end
def test_time
test_time = Time.now
assert_equal wrap('date', test_time.utc.strftime('%Y-%m-%dT%H:%M:%SZ')), Plist::Emit.dump(test_time, false).chomp
end
def test_dates
test_date = Date.today
test_datetime = DateTime.now
assert_equal wrap('date', test_date.strftime('%Y-%m-%dT%H:%M:%SZ')), Plist::Emit.dump(test_date, false).chomp
assert_equal wrap('date', test_datetime.strftime('%Y-%m-%dT%H:%M:%SZ')), Plist::Emit.dump(test_datetime, false).chomp
end
end
plist-3.1.0/test/assets/ 0000755 0001750 0001750 00000000000 12131276043 014504 5 ustar boutil boutil plist-3.1.0/test/assets/test_data_elements.plist 0000644 0001750 0001750 00000001575 12131276043 021435 0 ustar boutil boutil
stringio
dGhpcyBpcyBhIHN0cmluZ2lvIG9iamVjdA==
file
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAA==
io
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAA==
marshal
BAhvOhZNYXJzaGFsYWJsZU9iamVjdAY6CUBmb28iHnRoaXMgb2JqZWN0IHdh
cyBtYXJzaGFsZWQ=
plist-3.1.0/test/assets/test_empty_key.plist 0000644 0001750 0001750 00000000517 12131276043 020631 0 ustar boutil boutil
key
1
subkey
2
plist-3.1.0/test/assets/Cookies.plist 0000644 0001750 0001750 00000005004 12131276043 017154 0 ustar boutil boutil
Created
151936595.697543
Domain
.cleveland.com
Expires
2007-10-25T12:36:35Z
Name
CTC
Path
/
Value
:broadband:
Created
151778895.063041
Domain
.gamefaqs.com
Expires
2006-04-21T16:47:58Z
Name
ctk
Path
/
Value
NDM1YmJlYmU0NjZiOGYxZjc1NjgxODg0YmRkMA%3D%3D
Created
183530456
Domain
arstechnica.com
Expires
2006-10-26T13:56:36Z
Name
fontFace
Path
/
Value
1
Created
183004526
Domain
.sourceforge.net
Expires
2006-10-20T02:35:26Z
Name
FRQSTR
Path
/
Value
18829595x86799:1:1440x87033:1:1440x86799:1:1440x87248:1:1440|18829595|18829595|18829595|18829595
Created
151053128.640531
Domain
.tvguide.com
Expires
2025-10-10T07:12:17Z
Name
DMSEG
Path
/
Value
1BDF3D1CC07FC70F&D04451&434EC763&4351FD51&0&
Created
151304125.760261
Domain
.code.blogspot.com
Expires
2038-01-18T00:00:00Z
Name
__utma
Path
/
Value
11680422.1172819419.1129611326.1129611326.1129611326.1
Created
599529600
Domain
.tvguide.com
Expires
2020-01-01T00:00:00Z
Name
gfm
Path
/
Value
0
plist-3.1.0/test/assets/example_data.plist 0000644 0001750 0001750 00000036635 12131276043 020222 0 ustar boutil boutil
IMs
com.apple.syncservices:9583BE42-EC1A-4B3F-B248-7904BA60634B
com.apple.syncservices:2A222E96-4CC6-4320-BE0C-61D5F08C2E64
com.apple.syncservices:64DAA772-4558-49F8-9B87-C4A32D5E05C1
com.apple.syncservices:AF7C6884-B760-4E55-A4D5-B1B114C8A7DC
com.apple.syncservices:ECC7FAED-47D6-4DB9-8120-2F029C7D64C8
com.apple.syncservices:D704F079-F869-4613-9CFC-697C1976E8F4
URLs
com.apple.syncservices:5BA97109-F8E3-46A9-AF0B-5F8C093F49EA
com.apple.syncservices.RecordEntityName
com.apple.contacts.Contact
display as company
person
email addresses
com.apple.syncservices:B97DCC9C-5B00-4D38-AB06-4B7A5D6BC369
com.apple.syncservices:E508D679-43E1-49E2-B5D7-F14A8E48C067
com.apple.syncservices:C6478063-34A5-4CCB-BD41-1F131D56F7BD
com.apple.syncservices:2B3E352C-7831-4349-9A87-0FA4BD290515
first name
Mat
image
/9j/4AAQSkZJRgABAQAAAQABAAD/7QAcUGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAD/
4g9ASUNDX1BST0ZJTEUAAQEAAA8wYXBwbAIAAABtbnRyUkdCIFhZWiAH1gAFABUAFAAg
AAZhY3NwQVBQTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWFwcGxx
EHyAeZ4fvAacU+DW7cbVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5yWFla
AAABLAAAABRnWFlaAAABQAAAABRiWFlaAAABVAAAABR3dHB0AAABaAAAABRjaGFkAAAB
fAAAACxyVFJDAAABqAAAAA5nVFJDAAABuAAAAA5iVFJDAAAByAAAAA52Y2d0AAAB2AAA
BhJuZGluAAAH7AAABj5kZXNjAAAOLAAAAGRkc2NtAAAOkAAAAEhtbW9kAAAO2AAAAChj
cHJ0AAAPAAAAAC1YWVogAAAAAAAAZwIAADyoAAAJjlhZWiAAAAAAAABowAAAq7QAAB5o
WFlaIAAAAAAAACcUAAAXvwAAqy9YWVogAAAAAAAA81IAAQAAAAEWz3NmMzIAAAAAAAEM
QgAABd7///MmAAAHkgAA/ZH///ui///9owAAA9wAAMBsY3VydgAAAAAAAAABAc0AAGN1
cnYAAAAAAAAAAQHNAABjdXJ2AAAAAAAAAAEBzQAAdmNndAAAAAAAAAAAAAMBAAACAAAA
JwCJARYBsAJsA0kESAV0BsgIPAnXC5YNcA9oEX0ToxXSGAwaJRvMHW4fDSCbIi8jtSUy
JqooFil9KuEsOS2MLtwwLTF1Mr80CDVINmQ3cjh8OYs6nTuuPL890j7lP/hBCUIUQxtE
H0UdRhhHDkf9SOhJ30r0TBxNQE5iT4NQo1HEUudUDVUxVlZXhFizWeRbGlxSXY9e0mAU
YVtin2PhZSBmWmeWaMtp/WsybGJtkm7Gb/hxKnJhc5502HYYd1d4mHmyerx7wHzFfc9+
1n/egOmB94MHhBiFLIZCh1uIdomViraL2Yz+jiKPRZBokY+SrpPMlOWV/ZcVmCmZOJpG
m1ScX51onnCfdqB8oYGiiqORpJmlo6asp7yozancqumr9q0ArgWvBK/8sO+x2bK/s5q0
bLU7thK2/7f8uPu5+Lr0u+68573bvtS/0MDKwcnCzMPUxN/F88cLyCPJQMpFyyHL5cyq
zXHOOM79z8XQkdFe0izS/dPP1KbVf9Za1zjYF9j42dnamNtD2+TchN0i3cDeWt7z34zg
JuC/4Vjh8OKL4yfjxeRi5QHlouZN5wDnwOh76TPp5eqP6zPr0exj7PLtce3w7l/uzu8z
75Pv9PBK8KDw+/GN8iny2fOD9Cn0yfVp9gj2qfdM9/H4ovla+hr66vvN/MD9yf7Q//8A
AAAUAEYAkQD0AYQCNQMQBA0FPAaSCA8Jtgt1DUoPNBEtEy0VNhcUGJ0aIhujHRsekB/+
IWIixCQgJWwmuyf8KTcqcCumLNUuAy8vME0xXjJoM200cjV3Nnk3ejh6OXg6dDtwPGc9
Wz5NPzxAKEEUQf1C5EPRRM9F1kbcR+JI50nsSvBL9kz+TgNPB1ANURNSF1MdVCJVJ1Yv
VzNYOVk/WkZbTlxTXV9ebF95YIxhomK9Y+BlBWYuZ15ol2nQaw5sTG2NbqdvsXC1cbpy
xHPLdNN13nbsd/x5DXohezd8UH1rfop/q4DOgfODF4Q6hV2GhIejiMGJ2oryjAqNHo4t
jzuQSZFUkl2TZZRrlXGWdpd/mIWZi5qQm5Gcl52dnp6fnKCdoZiilaOMpICldKZjp1Go
PKkkqg2q9KvarL6tqK6Rr4Cwb7FgslOzSbRDtT+2PLc8uD25QLpFu0m8Tb1Qvk2/O8Ah
wQrB9sLiw83EusWrxprHich5yWjKVctDzC/NGs4DzurPz9DE0cPSvNOx1J/VhtZm10HY
F9jp2brahttT3CHc8N3F3prfdOBR4Svh+uLA44XkSeUO5dPml+db6B/o4+mm6mrrLuvz
7Lbteu4+7wPvx/CM8VDyFPLX8530YfUk9er2rfdx+DX4+vm9+oH7RfwK/M79kv5W/x7/
/wAAAAkAIABDAHAApwDoAVAB1gJ8Az4EHAUcBjUHXwiaCecLPAyVDekPExA2EVgSdBON
FKEVrxa6F7sYtRmoGpMbdxxWHTAeAh7QH5kgZCE6Ih8i/yPgJL0llyZvJ0UoGijpKbgq
hCtPLBcs3S2jLmgvLS/xMLQxdzI6MvYzrzRmNRo1yzZ8Ny432jiJOTk56jqdO1I8CjzF
PYQ+RD8IP8xAkUFVQhZC2UOZRFhFFkXQRopHQ0f0SKRJVEoBSqxLVUv5TJVNJ02tTjBO
tE85T75QRFDMUVZR41JyUwNTl1QtVMZVYVYAVqBXQlgDWO1Z81r7XANdCl4QXxpgKGE1
YkNjVGRqZYJmm2e4aNdp92sabEFtaW6Nb69wzXHrcwh0H3UwdkB3SXhQeVB6SntDfDV9
JX4Rfvp/44DPgciCx4PFhMCFuoauh5+IiYlyilqLPowfjQCN4I7Aj6GQg5FikkSTHpPt
lLWVgZZTlyeX/JjWmbaal5t6nGKdSZ4ynxygBqDvodeivqOjpJill6aSp4eoeKlkqkur
L6wTrPet3a7Gr7GwqLGgsqazr7S/tdu2+rgeuUS6aLuJvKu9yb7owATBIMI6w1TEb8WM
xqrHx8jpygjLLMxSzYHOxtAm0YvS/9SF1hTXstlr2zXdFt8M4SjjZOXI6G7rae7F8ur4
1P//AABuZGluAAAAAAAABjYAAJQXAABYjQAAUbUAAI5iAAAoWwAAFqgAAFANAABUOQAC
o9cAAkAAAAFKPQADAQAAAgAAABQALQBGAF8AdwCOAKUAvADTAOkA/wEWASwBQwFZAXAB
hgGdAbQBywHjAfsCEwIsAkcCYgKGAqoC0AL3Ax8DSgN1A6EDzwP/BDEEZASZBNEFCgVF
BYEFwQYCBkYGigbQBxkHYweuB/sISwimCQgJbwnVCjwKpQsQC3wL6gxZDMsNPw24DjQO
tA85D8EQTxDjEXwSChKIEwUThxQKFI8VFxWfFikWsxc9F8oYWBjjGW8Z/BqJGxUbohwu
HLkdRR3SHl4e7R99IBAgpSE+IdYiciMSI7MkVCT5JaAmRCbsJ5UoPyjnKY0qNyrfK4cs
MizZLZkuaS8/MBgw7jHGMqIzfDRWNS82CDbjN7w4ljluOkc7Hjv1PMw9pD58P1dAM0ER
QexCz0O0RJ9FjEZ5R2tIYkleSlxLW0xfTWdOcE99UIxRnVKsU75U0VXjVvhYCFkXWipb
QVxYXXRelV++YPNiLmN6ZM1mNmewaTVqkmvTbQ9uUm+WcOByLHOBdNJ2IHdyeL96CXtO
fJF9zH8CgDuBb4KjhBWF2oehiWOLLYz1jrSQdpIwk+yVnZdOmPiaopxKnfOf66JEpKen
FqmZrCGurbFCs8+2V7jhu2C9qr/JwfzESsa7yV/MRs+Y02vX2tzd39riV+T157bqg+1L
8AjykvT69yr5LfsI/L3+g///AAAAJwBHAGQAgACaALMAzADkAPwBEwErAUMBWwF0AYwB
pQG+AdgB8gIMAicCRQJkAooCsgLbAwUDMQNfA44DvgPxBCYEXASUBM4FDAVKBYsF0AYX
BmAGqgb4B0gHmgfuCEcIpgkKCXIJ3ApICrcLKQudDBQMjw0LDYwOEQ6ZDyYPthBJEOER
fBISEp4TLBO8FE8U4xV6FhMWrBdGF+UYhRklGcgabhsUG70caB0SHcEecB8hH9MghiE9
IfEipiNdJBEkxSV5Jikm2CeIKDYo4imKKjUq3iuHLDIs2S2ZLmkvPzAYMO4xxjKiM3w0
VjUvNgg24ze8OJY5bjpHOx479TzMPaQ+fD9XQDNBEUHsQs9DtESfRYxGeUdrSGJJXkpc
S1tMX01nTnBPfVCMUZ1SrFO/VNRV7FcKWCNZP1phW4hcrl3cXwpgQWF+YrxkBWVOZqFn
92lPaqxsD21qbslwIHF5ctB0KHV5dsl4GXloerV8An1Pfpp/6oE8go6D9IV1hveIc4nw
i3OM8o5tj+2Rb5LxlHmWApePmR+atpxRnfOffKD2onukCqWmp1GpEKrbrLSulLCBsmu0
WbY3uBe57bu7va2/vMHSw+nGBMghykHMZ86P0LfS4dUP1z/Zctum3dvgFuJV5I7m1ekU
617tqu/x8kT0lPbm+Tr7k/3w//8AAABVAIoAtwDhAQgBLgFUAXoBoAHGAe0CFQI+AmoC
ngLUAwwDRwOFA8UECQRQBJoE6gU+BZcF9wZcBscHOQexCDEIrAkhCZsKFwqZCyALqww6
DNANag4KDq8PWRAHELkRbxIqEugTsBSAFVoWOhcfGA0Y/BnsGtwbyxy3HaMejR96IGoh
YSJZI1skYCVvJoInpSjPKgArPSyHLf8vqzFXMwc0sTZUN/E5hjsVPJ4+JD9kQFtBUUJG
Qz9EOUU2Ri9HJ0giSR5KGEsPTAVM/U3zTuhP3lDUUclSu1OvVKdVoVaiV6NYpVmsWrtb
z1zlXgVfKGBVYYtixGQJZVBmomf3aU9qlWvTbRBuVW+ccOxyQ3OndQ52eXfveWl65nxo
feh/aYDxgnWEE4XQh4eJMIrbjICOGY+wkUaS1ZRolfiXipkdmrWcUZ3zn3yg9qJ5pAal
nac+qO2qoKxWrgmvubFlsv+0mbYct5+5GbqEu++9U761wBnBgcLvxFrFzMc+yLTKLMuo
zSbOpNAh0Z/TG9Sa1hTXlNkQ2oncAd1q3rvf+eE24m/jneTA5eDm/egT6STqJ+sm7CHt
E+4B7unv0PCp8X/yTfMZ8930m/VX9gT2svdW9+/4ifkZ+aL6K/qv+x37jPv6/Gj8tv0E
/VL9oP3v/jz+gf7G/wz/Uf+X/9z//wAAZGVzYwAAAAAAAAAKQ29sb3IgTENEAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1sdWMAAAAAAAAAAgAAAAxlblVTAAAAEgAAAChq
YUpQAAAADgAAADoAQwBvAGwAbwByACAATABDAEQwqzDpMPwAIABMAEMARG1tb2QAAAAA
AAAGEAAAnF4AAAAAwEuKAAAAAAAAAAAAAAAAAAAAAAB0ZXh0AAAAAENvcHlyaWdodCBB
cHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBD
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQH/wAARCAAwADADAREAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAA
AAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1Fh
ByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpT
VFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKz
tLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA
AwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAEC
AxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2
Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaX
mJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP0
9fb3+Pn6/9oADAMBAAIRAxEAPwDd+Bfxs/4J+ftC/EFPhp4M+LXjLQtVl8P6pr9trvxE
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
zSptxk21dX5pWbuo3SS//9k=
last name
Schaffer
phone numbers
com.apple.syncservices:64ED42EB-109B-43A9-BEFC-3463D944251A
com.apple.syncservices:FB7585EB-A3DE-46D5-920C-DF8028689BC5
com.apple.syncservices:020036FD-22B3-41C9-BC3D-CDA6083582C6
com.apple.syncservices:C6661518-90CA-45C7-A988-02F73B958951
primary URL
com.apple.syncservices:5BA97109-F8E3-46A9-AF0B-5F8C093F49EA
primary email address
com.apple.syncservices:B97DCC9C-5B00-4D38-AB06-4B7A5D6BC369
primary phone number
com.apple.syncservices:64ED42EB-109B-43A9-BEFC-3463D944251A
primary related name
com.apple.syncservices:CD0B7021-0228-4770-8FB0-3739479E9788
primary street address
com.apple.syncservices:377B9105-9D15-4F69-BCD6-B01E587F7760
related names
com.apple.syncservices:CD0B7021-0228-4770-8FB0-3739479E9788
street addresses
com.apple.syncservices:377B9105-9D15-4F69-BCD6-B01E587F7760
plist-3.1.0/test/assets/example_data.jpg 0000644 0001750 0001750 00000022437 12131276043 017642 0 ustar boutil boutil JFIF Photoshop 3.0 8BIM @ICC_PROFILE 0appl mntrRGB XYZ acspAPPL -applq|yS rXYZ , gXYZ @ bXYZ T wtpt h chad | ,rTRC gTRC bTRC vcgt ndin >desc , ddscm Hmmod (cprt -XYZ g <