lib/plist/parser.rb in plist-3.2.0 vs lib/plist/parser.rb in plist-3.3.0
- old
+ new
@@ -1,7 +1,7 @@
-#!/usr/bin/env ruby
-#
+# encoding: utf-8
+
# = plist
#
# Copyright 2006-2010 Ben Bleything and Patrick May
# Distributed under the MIT License
#
@@ -71,14 +71,14 @@
@listener = listener
end
TEXT = /([^<]+)/
- XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>*/um
- DOCTYPE_PATTERN = /\s*<!DOCTYPE\s+(.*?)(\[|>)/um
- COMMENT_START = /\A<!--/u
- COMMENT_END = /.*?-->/um
+ XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>*/m
+ DOCTYPE_PATTERN = /\s*<!DOCTYPE\s+(.*?)(\[|>)/m
+ COMMENT_START = /\A<!--/
+ COMMENT_END = /.*?-->/m
def parse
plist_tags = PTag::mappings.keys.join('|')
start_tag = /<(#{plist_tags})([^>]*)>/i
@@ -89,11 +89,18 @@
@scanner = StringScanner.new( @xml )
until @scanner.eos?
if @scanner.scan(COMMENT_START)
@scanner.scan(COMMENT_END)
elsif @scanner.scan(XMLDECL_PATTERN)
+ encoding = parse_encoding_from_xml_declaration(@scanner[1])
+ next if encoding.nil?
+
+ # use the specified encoding for the rest of the file
+ next unless String.method_defined?(:force_encoding)
+ @scanner.string = @scanner.rest.force_encoding(encoding)
elsif @scanner.scan(DOCTYPE_PATTERN)
+ next
elsif @scanner.scan(start_tag)
@listener.tag_start(@scanner[1], nil)
if (@scanner[2] =~ /\/$/)
@listener.tag_end(@scanner[1])
end
@@ -104,10 +111,26 @@
else
raise "Unimplemented element"
end
end
end
+
+ private
+
+ def parse_encoding_from_xml_declaration(xml_declaration)
+ return unless defined?(Encoding)
+
+ xml_encoding = xml_declaration.match(/(?:\A|\s)encoding=(?:"(.*?)"|'(.*?)')(?:\s|\Z)/)
+
+ return if xml_encoding.nil?
+
+ begin
+ Encoding.find(xml_encoding[1])
+ rescue ArgumentError
+ nil
+ end
+ end
end
class PTag
@@mappings = { }
def PTag::mappings
@@ -211,10 +234,10 @@
class PData < PTag
def to_ruby
data = Base64.decode64(text.gsub(/\s+/, '')) unless text.nil?
begin
return Marshal.load(data)
- rescue Exception => e
+ rescue Exception
io = StringIO.new
io.write data
io.rewind
return io
end