diff options
-rw-r--r-- | lib/plist.rb | 1 | ||||
-rw-r--r-- | lib/plist/generator.rb | 38 | ||||
-rw-r--r-- | lib/plist/parser.rb | 24 | ||||
-rw-r--r-- | test/assets/test_empty_key.plist | 13 | ||||
-rw-r--r-- | test/test_generator_basic_types.rb | 34 | ||||
-rw-r--r-- | test/test_parser.rb | 42 |
6 files changed, 95 insertions, 57 deletions
diff --git a/lib/plist.rb b/lib/plist.rb index 814bf0a..e0ea72d 100644 --- a/lib/plist.rb +++ b/lib/plist.rb @@ -10,6 +10,7 @@ # # This is the main file for plist. Everything interesting happens in Plist and Plist::Emit. +require 'cgi' require 'plist/generator' require 'plist/parser' diff --git a/lib/plist/generator.rb b/lib/plist/generator.rb index c44c979..255449e 100644 --- a/lib/plist/generator.rb +++ b/lib/plist/generator.rb @@ -1,11 +1,9 @@ -#-- ############################################################## # Copyright 2006, Ben Bleything <ben@bleything.net> and # # Patrick May <patrick@hexane.org> # # # # Distributed under the MIT license. # ############################################################## -#++ # === Save a plist # You can turn the variables back into a plist string: @@ -56,9 +54,9 @@ module Plist # expected plist classes (plist@hexane.org) def to_plist( header = true ) if (header) - Plist::_xml(self.to_plist_fragment) + Plist::_xml(self.to_plist_node) else - self.to_plist_fragment + self.to_plist_node end end end @@ -66,66 +64,66 @@ end class String include Plist::Emit - def to_plist_fragment - "<string>#{self}</string>" + def to_plist_node + "<string>#{CGI::escapeHTML(self)}</string>" end end class Symbol include Plist::Emit - def to_plist_fragment - "<string>#{self}</string>" + def to_plist_node + "<string>#{CGI::escapeHTML(self.to_s)}</string>" end end class Float include Plist::Emit - def to_plist_fragment + def to_plist_node "<real>#{self}</real>" end end class Time include Plist::Emit - def to_plist_fragment + def to_plist_node "<date>#{self.utc.strftime('%Y-%m-%dT%H:%M:%SZ')}</date>" end end class Date include Plist::Emit - def to_plist_fragment + def to_plist_node "<date>#{self.strftime('%Y-%m-%dT%H:%M:%SZ')}</date>" end end class Integer include Plist::Emit - def to_plist_fragment + def to_plist_node "<integer>#{self}</integer>" end end class FalseClass include Plist::Emit - def to_plist_fragment + def to_plist_node "<false/>" end end class TrueClass include Plist::Emit - def to_plist_fragment + def to_plist_node "<true/>" end end class Array include Plist::Emit - def to_plist_fragment + def to_plist_node fragment = "<array>\n" self.each do |e| - element_plist = e.to_plist_fragment + element_plist = e.to_plist_node element_plist.each do |l| fragment += "\t#{l.chomp}\n" end @@ -137,11 +135,11 @@ end class Hash include Plist::Emit - def to_plist_fragment + def to_plist_node fragment = "<dict>\n" self.keys.sort.each do |k| - fragment += "\t<key>#{k}</key>\n" - element_plist = self[k].to_plist_fragment + fragment += "\t<key>#{CGI::escapeHTML(k)}</key>\n" + element_plist = self[k].to_plist_node element_plist.each do |l| fragment += "\t#{l.chomp}\n" end @@ -155,7 +153,7 @@ require 'stringio' [ IO, StringIO ].each do |io_class| io_class.module_eval do include Plist::Emit - def to_plist_fragment + def to_plist_node self.rewind data = self.read diff --git a/lib/plist/parser.rb b/lib/plist/parser.rb index a92b997..ae2728d 100644 --- a/lib/plist/parser.rb +++ b/lib/plist/parser.rb @@ -1,11 +1,9 @@ -#-- ############################################################## # Copyright 2006, Ben Bleything <ben@bleything.net> and # # Patrick May <patrick@hexane.org> # # # # Distributed under the MIT license. # ############################################################## -#++ # # Plist parses Mac OS X xml property list files into ruby data structures. # @@ -162,13 +160,13 @@ XML class PKey < PTag def to_ruby - text + CGI::unescapeHTML(text || '') end end class PString < PTag def to_ruby - text || '' + CGI::unescapeHTML(text || '') end end @@ -212,15 +210,21 @@ XML end require 'base64' - require 'tempfile' class PData < PTag def to_ruby - tf = Tempfile.new("plist.tmp") - tf.write Base64.decode64(text.gsub(/\s+/,'')) - tf.close + # replacing Tempfile with StringIO + # think it might be a bit nicer + #require 'tempfile' + #tf = Tempfile.new("plist.tmp") + #tf.write Base64.decode64(text.gsub(/\s+/,'')) + #tf.close # is this a good idea? - tf.open - tf + #tf.open + #tf + io = StringIO.new + io.write Base64.decode64(text.gsub(/\s+/,'')) + io.rewind + io end end end diff --git a/test/assets/test_empty_key.plist b/test/assets/test_empty_key.plist new file mode 100644 index 0000000..5b37513 --- /dev/null +++ b/test/assets/test_empty_key.plist @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> + <dict> + <key>key</key> + <dict> + <key></key> + <string>1</string> + <key>subkey</key> + <string>2</string> + </dict> + </dict> +</plist>
\ No newline at end of file diff --git a/test/test_generator_basic_types.rb b/test/test_generator_basic_types.rb index 3483373..ed59757 100644 --- a/test/test_generator_basic_types.rb +++ b/test/test_generator_basic_types.rb @@ -49,4 +49,38 @@ class TestBasicTypes < Test::Unit::TestCase assert_equal wrap('date', test_date.strftime('%Y-%m-%dT%H:%M:%SZ')), [test_date].to_plist(false) assert_equal wrap('date', test_datetime.strftime('%Y-%m-%dT%H:%M:%SZ')), [test_datetime].to_plist(false) end + + # generater tests from patrick's plist.rb code + def test_to_plist + assert_equal( Plist::_xml("<string>Hello, World</string>"), "Hello, World".to_plist ) + assert_equal( Plist::_xml("<real>151936595.697543</real>"), 151936595.697543.to_plist ) + assert_equal( Plist::_xml("<date>2006-04-21T16:47:58Z</date>"), DateTime.parse("2006-04-21T16:47:58Z").to_plist ) + assert_equal( Plist::_xml("<integer>999000</integer>"), 999000.to_plist ) + assert_equal( Plist::_xml("<false/>"), false.to_plist ) + assert_equal( Plist::_xml("<true/>"), true.to_plist ) + + assert_equal( Plist::_xml("<array>\n\t<true/>\n\t<false/>\n</array>"), + [ true, false ].to_plist ) + + assert_equal( Plist::_xml("<dict>\n\t<key>False</key>\n\t<false/>\n\t<key>True</key>\n\t<true/>\n</dict>"), + { 'True' => true, 'False' => false }.to_plist ) + + source = File.open("test/assets/AlbumData.xml") { |f| f.read } + + result = Plist::parse_xml(source) + + assert_equal( result, Plist::parse_xml(result.to_plist) ) + + File.delete('hello.plist') if File.exists?('hello.plist') + "Hello, World".save_plist('hello.plist') + assert_equal( Plist::_xml("<string>Hello, World</string>"), + File.open('hello.plist') {|f| f.read } ) + File.delete('hello.plist') if File.exists?('hello.plist') + end + + def test_escape_string_values + assert_equal( Plist::_xml("<string><plist></string>"), "<plist>".to_plist ) + assert_equal( Plist::_xml("<string>Fish & Chips</string>"), "Fish & Chips".to_plist ) + end + end diff --git a/test/test_parser.rb b/test/test_parser.rb index 2e94a1c..5aeda6c 100644 --- a/test/test_parser.rb +++ b/test/test_parser.rb @@ -54,6 +54,7 @@ class TestPlist < Test::Unit::TestCase end + # uncomment this test to work on speed optimization #def test_load_something_big # plist = Plist::parse_xml( "~/Pictures/iPhoto Library/AlbumData.xml" ) #end @@ -66,33 +67,6 @@ class TestPlist < Test::Unit::TestCase assert_equal( "2007-10-25T12:36:35Z", result.first['Expires'].to_s ) end - def test_to_plist - assert_equal( Plist::_xml("<string>Hello, World</string>"), "Hello, World".to_plist ) - assert_equal( Plist::_xml("<real>151936595.697543</real>"), 151936595.697543.to_plist ) - assert_equal( Plist::_xml("<date>2006-04-21T16:47:58Z</date>"), DateTime.parse("2006-04-21T16:47:58Z").to_plist ) - assert_equal( Plist::_xml("<integer>999000</integer>"), 999000.to_plist ) - assert_equal( Plist::_xml("<false/>"), false.to_plist ) - assert_equal( Plist::_xml("<true/>"), true.to_plist ) - - assert_equal( Plist::_xml("<array>\n\t<true/>\n\t<false/>\n</array>"), - [ true, false ].to_plist ) - - assert_equal( Plist::_xml("<dict>\n\t<key>False</key>\n\t<false/>\n\t<key>True</key>\n\t<true/>\n</dict>"), - { 'True' => true, 'False' => false }.to_plist ) - - source = File.open("test/assets/AlbumData.xml") { |f| f.read } - - result = Plist::parse_xml(source) - - assert_equal( result, Plist::parse_xml(result.to_plist) ) - - File.delete('hello.plist') if File.exists?('hello.plist') - "Hello, World".save_plist('hello.plist') - assert_equal( Plist::_xml("<string>Hello, World</string>"), - File.open('hello.plist') {|f| f.read } ) - File.delete('hello.plist') if File.exists?('hello.plist') - 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. @@ -109,6 +83,20 @@ class TestPlist < Test::Unit::TestCase end + # bug fix for empty <key> + # reported by Matthias Peick <matthias@peick.de> + # reported and fixed by Frederik Seiffert <ego@frederikseiffert.de> + 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 <matthias@peick.de> + def test_decode_entities + data = Plist::parse_xml(Plist::_xml('<string>Fish & Chips</string>')) + assert_equal('Fish & Chips', data) + end end __END__ |