CFPropertyList 2.0.14 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,199 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'strscan'
4
+
5
+ module CFPropertyList
6
+ # XML parser
7
+ class PlainParser < XMLParserInterface
8
+ # read a XML file
9
+ # opts::
10
+ # * :file - The filename of the file to load
11
+ # * :data - The data to parse
12
+ def load(opts)
13
+ @doc = nil
14
+
15
+ if(opts.has_key?(:file)) then
16
+ File.open(opts[:file], :external_encoding => "ASCII") do |fd|
17
+ @doc = StringScanner.new(fd.read)
18
+ end
19
+ else
20
+ @doc = StringScanner.new(opts[:data])
21
+ end
22
+
23
+ if @doc
24
+ root = import_plain
25
+ raise CFFormatError.new('content after root object') unless @doc.eos?
26
+
27
+ return root
28
+ end
29
+
30
+ raise CFFormatError.new('invalid plist string or file not found')
31
+ end
32
+
33
+ SPACES_AND_COMMENTS = %r{((?:/\*.*?\*/)|(?://.*?$\n?)|(?:\s*))+}x
34
+
35
+ # serialize CFPropertyList object to XML
36
+ # opts = {}:: Specify options: :formatted - Use indention and line breaks
37
+ def to_str(opts={})
38
+ opts[:root].to_plain(self)
39
+ end
40
+
41
+ protected
42
+ def skip_whitespaces
43
+ @doc.skip SPACES_AND_COMMENTS
44
+ end
45
+
46
+ def read_dict
47
+ skip_whitespaces
48
+ hsh = {}
49
+
50
+ while not @doc.scan(/\}/)
51
+ key = import_plain
52
+ raise CFFormatError.new("invalid dictionary format") if !key
53
+
54
+ if key.is_a?(CFString)
55
+ key = key.value
56
+ elsif key.is_a?(CFInteger) or key.is_a?(CFReal)
57
+ key = key.value.to_s
58
+ else
59
+ raise CFFormatError.new("invalid key format")
60
+ end
61
+
62
+ skip_whitespaces
63
+
64
+ raise CFFormatError.new("invalid dictionary format") unless @doc.scan(/=/)
65
+
66
+ skip_whitespaces
67
+ val = import_plain
68
+
69
+ skip_whitespaces
70
+ raise CFFormatError.new("invalid dictionary format") unless @doc.scan(/;/)
71
+ skip_whitespaces
72
+
73
+ hsh[key] = val
74
+ raise CFFormatError.new("invalid dictionary format") if @doc.eos?
75
+ end
76
+
77
+ CFDictionary.new(hsh)
78
+ end
79
+
80
+ def read_array
81
+ skip_whitespaces
82
+ ary = []
83
+
84
+ while not @doc.scan(/\)/)
85
+ val = import_plain
86
+
87
+ return nil if not val or not val.value
88
+ skip_whitespaces
89
+
90
+ if not @doc.skip(/,\s*/)
91
+ if @doc.scan(/\)/)
92
+ ary << val
93
+ return CFArray.new(ary)
94
+ end
95
+
96
+ raise CFFormatError.new("invalid array format")
97
+ end
98
+
99
+ ary << val
100
+ raise CFFormatError.new("invalid array format") if @doc.eos?
101
+ end
102
+
103
+ CFArray.new(ary)
104
+ end
105
+
106
+ def escape_char
107
+ case @doc.matched
108
+ when '"'
109
+ '"'
110
+ when '\\'
111
+ '\\'
112
+ when 'a'
113
+ "\a"
114
+ when 'b'
115
+ "\b"
116
+ when 'f'
117
+ "\f"
118
+ when 'n'
119
+ "\n"
120
+ when 'v'
121
+ "\v"
122
+ when 'r'
123
+ "\r"
124
+ when 't'
125
+ "\t"
126
+ when 'U'
127
+ @doc.scan(/.{4}/).hex.chr('utf-8')
128
+ end
129
+ end
130
+
131
+ def read_quoted
132
+ str = ''
133
+
134
+ while not @doc.scan(/"/)
135
+ if @doc.scan(/\\/)
136
+ @doc.scan(/./)
137
+ str << escape_char
138
+
139
+ elsif @doc.eos?
140
+ raise CFFormatError.new("unterminated string")
141
+
142
+ else @doc.scan(/./)
143
+ str << @doc.matched
144
+ end
145
+ end
146
+
147
+ CFString.new(str)
148
+ end
149
+
150
+ def read_unquoted
151
+ raise CFFormatError.new("unexpected end of file") if @doc.eos?
152
+
153
+ if @doc.scan(/(\d\d\d\d)-(\d\d)-(\d\d)\s+(\d\d):(\d\d):(\d\d)(?:\s+(\+|-)(\d\d)(\d\d))?/)
154
+ year,month,day,hour,min,sec,pl_min,tz_hour, tz_min = @doc[1], @doc[2], @doc[3], @doc[4], @doc[5], @doc[6], @doc[7], @doc[8], @doc[9]
155
+ CFDate.new(Time.new(year, month, day, hour, min, sec, pl_min ? sprintf("%s%s:%s", pl_min, tz_hour, tz_min) : nil))
156
+
157
+ elsif @doc.scan(/-?\d+?\.\d+\b/)
158
+ CFReal.new(@doc.matched.to_f)
159
+
160
+ elsif @doc.scan(/-?\d+\b/)
161
+ CFInteger.new(@doc.matched.to_i)
162
+
163
+ elsif @doc.scan(/\b(true|false)\b/)
164
+ CFBoolean.new(@doc.matched == 'true')
165
+ else
166
+ CFString.new(@doc.scan(/\w+/))
167
+ end
168
+ end
169
+
170
+ def read_binary
171
+ @doc.scan(/(.*?)>/)
172
+
173
+ hex_str = @doc[1].gsub(/ /, '')
174
+ CFData.new([hex_str].pack("H*"), CFData::DATA_RAW)
175
+ end
176
+
177
+ # import the XML values
178
+ def import_plain
179
+ skip_whitespaces
180
+ ret = nil
181
+
182
+ if @doc.scan(/\{/) # dict
183
+ ret = read_dict
184
+ elsif @doc.scan(/\(/) # array
185
+ ret = read_array
186
+ elsif @doc.scan(/"/) # string
187
+ ret = read_quoted
188
+ elsif @doc.scan(/</) # binary
189
+ ret = read_binary
190
+ else # string w/o quotes
191
+ ret = read_unquoted
192
+ end
193
+
194
+ return ret
195
+ end
196
+ end
197
+ end
198
+
199
+ # eof
@@ -0,0 +1,148 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'rexml/document'
4
+
5
+ module CFPropertyList
6
+ # XML parser
7
+ class ReXMLParser < ParserInterface
8
+ # read a XML file
9
+ # opts::
10
+ # * :file - The filename of the file to load
11
+ # * :data - The data to parse
12
+ def load(opts)
13
+
14
+ doc = nil
15
+ if(opts.has_key?(:file)) then
16
+ File.open(opts[:file], "rb") { |fd| doc = REXML::Document.new(fd) }
17
+ else
18
+ doc = REXML::Document.new(opts[:data])
19
+ end
20
+
21
+ if doc
22
+ root = doc.root.elements[1]
23
+ return import_xml(root)
24
+ end
25
+ rescue REXML::ParseException => e
26
+ raise CFFormatError.new('invalid XML: ' + e.message)
27
+ end
28
+
29
+ # serialize CFPropertyList object to XML
30
+ # opts = {}:: Specify options: :formatted - Use indention and line breaks
31
+ def to_str(opts={})
32
+ doc = REXML::Document.new
33
+ @doc = doc
34
+
35
+ doc.context[:attribute_quote] = :quote
36
+
37
+ doc.add_element 'plist', {'version' => '1.0'}
38
+ doc.root << opts[:root].to_xml(self)
39
+
40
+ formatter = if opts[:formatted] then
41
+ f = REXML::Formatters::Pretty.new(2)
42
+ f.compact = true
43
+ f.width = Float::INFINITY
44
+ f
45
+ else
46
+ REXML::Formatters::Default.new
47
+ end
48
+
49
+ str = formatter.write(doc.root, "")
50
+ str1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" + str + "\n"
51
+ str1.force_encoding('UTF-8') if str1.respond_to?(:force_encoding)
52
+
53
+ return str1
54
+ end
55
+
56
+ def new_node(name)
57
+ REXML::Element.new(name)
58
+ end
59
+
60
+ def new_text(val)
61
+ val
62
+ end
63
+
64
+ def append_node(parent, child)
65
+ if child.is_a?(String) then
66
+ parent.add_text child
67
+ else
68
+ parent.elements << child
69
+ end
70
+ parent
71
+ end
72
+
73
+ protected
74
+
75
+ # get the value of a DOM node
76
+ def get_value(n)
77
+ content = n.text
78
+
79
+ content.force_encoding('UTF-8') if content.respond_to?(:force_encoding)
80
+ content
81
+ end
82
+
83
+ # import the XML values
84
+ def import_xml(node)
85
+ ret = nil
86
+
87
+ case node.name
88
+ when 'dict'
89
+ hsh = Hash.new
90
+ key = nil
91
+
92
+ if node.has_elements? then
93
+ node.elements.each do |n|
94
+ next if n.name == '#text' # avoid a bug of libxml
95
+ next if n.name == '#comment'
96
+
97
+ if n.name == "key" then
98
+ key = get_value(n)
99
+ key = '' if key.nil? # REXML returns nil if key is empty
100
+ else
101
+ raise CFFormatError.new("Format error!") if key.nil?
102
+ hsh[key] = import_xml(n)
103
+ key = nil
104
+ end
105
+ end
106
+ end
107
+
108
+ if hsh['CF$UID'] and hsh.keys.length == 1
109
+ ret = CFUid.new(hsh['CF$UID'].value)
110
+ else
111
+ ret = CFDictionary.new(hsh)
112
+ end
113
+
114
+ when 'array'
115
+ ary = Array.new
116
+
117
+ if node.has_elements? then
118
+ node.elements.each do |n|
119
+ next if n.name == '#text' # avoid a bug of libxml
120
+ ary.push import_xml(n)
121
+ end
122
+ end
123
+
124
+ ret = CFArray.new(ary)
125
+
126
+ when 'true'
127
+ ret = CFBoolean.new(true)
128
+ when 'false'
129
+ ret = CFBoolean.new(false)
130
+ when 'real'
131
+ ret = CFReal.new(get_value(node).to_f)
132
+ when 'integer'
133
+ ret = CFInteger.new(get_value(node).to_i)
134
+ when 'string'
135
+ ret = CFString.new(get_value(node))
136
+ ret.value = '' if ret.value.nil? # REXML returns nil for empty elements' .text attribute
137
+ when 'data'
138
+ ret = CFData.new(get_value(node))
139
+ when 'date'
140
+ ret = CFDate.new(CFDate.parse_date(get_value(node)))
141
+ end
142
+
143
+ return ret
144
+ end
145
+ end
146
+ end
147
+
148
+ # eof
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- require File.dirname(__FILE__) + '/rbCFPropertyList.rb'
3
+ require 'cfpropertylist/rbCFPropertyList'
4
4
 
5
5
 
6
- # eof
6
+ # eof
metadata CHANGED
@@ -1,80 +1,73 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: CFPropertyList
3
- version: !ruby/object:Gem::Version
4
- version: 2.0.14
3
+ version: !ruby/object:Gem::Version
4
+ version: 3.0.0
5
5
  platform: ruby
6
- authors:
6
+ authors:
7
7
  - Christian Kruse
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
-
12
- date: 2010-09-27 00:00:00 +02:00
13
- default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: libxml-ruby
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: 1.1.0
24
- version:
25
- - !ruby/object:Gem::Dependency
11
+ date: 2018-01-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
26
14
  name: rake
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.7.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
31
24
  - - ">="
32
- - !ruby/object:Gem::Version
25
+ - !ruby/object:Gem::Version
33
26
  version: 0.7.0
34
- version:
35
- description: This is a module to read, write and manipulate both binary and XML property lists as defined by apple.
36
- email: cjk@wwwtech.de
27
+ description: This is a module to read, write and manipulate both binary and XML property
28
+ lists as defined by apple.
29
+ email: cjk@defunct.ch
37
30
  executables: []
38
-
39
31
  extensions: []
40
-
41
- extra_rdoc_files:
42
- - README
43
- files:
32
+ extra_rdoc_files:
33
+ - README.rdoc
34
+ files:
35
+ - LICENSE
36
+ - README.md
37
+ - README.rdoc
38
+ - THANKS
44
39
  - lib/cfpropertylist.rb
45
- - lib/rbBinaryCFPropertyList.rb
46
- - lib/rbCFPlistError.rb
47
- - lib/rbCFPropertyList.rb
48
- - lib/rbCFTypes.rb
49
- - lib/rbXMLCFPropertyList.rb
50
- - README
51
- has_rdoc: true
40
+ - lib/cfpropertylist/rbBinaryCFPropertyList.rb
41
+ - lib/cfpropertylist/rbCFPlistError.rb
42
+ - lib/cfpropertylist/rbCFPropertyList.rb
43
+ - lib/cfpropertylist/rbCFTypes.rb
44
+ - lib/cfpropertylist/rbLibXMLParser.rb
45
+ - lib/cfpropertylist/rbNokogiriParser.rb
46
+ - lib/cfpropertylist/rbPlainCFPropertyList.rb
47
+ - lib/cfpropertylist/rbREXMLParser.rb
52
48
  homepage: http://github.com/ckruse/CFPropertyList
53
- licenses: []
54
-
49
+ licenses:
50
+ - MIT
51
+ metadata: {}
55
52
  post_install_message:
56
53
  rdoc_options: []
57
-
58
- require_paths:
54
+ require_paths:
59
55
  - lib
60
- required_ruby_version: !ruby/object:Gem::Requirement
61
- requirements:
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
62
58
  - - ">="
63
- - !ruby/object:Gem::Version
64
- version: "0"
65
- version:
66
- required_rubygems_version: !ruby/object:Gem::Requirement
67
- requirements:
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
68
63
  - - ">="
69
- - !ruby/object:Gem::Version
70
- version: "0"
71
- version:
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
72
66
  requirements: []
73
-
74
- rubyforge_project: cfpropertylist
75
- rubygems_version: 1.3.5
67
+ rubyforge_project:
68
+ rubygems_version: 2.7.3
76
69
  signing_key:
77
- specification_version: 3
78
- summary: Read, write and manipulate both binary and XML property lists as defined by apple
70
+ specification_version: 4
71
+ summary: Read, write and manipulate both binary and XML property lists as defined
72
+ by apple
79
73
  test_files: []
80
-