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