plist4r 0.2.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/.gitignore +4 -0
  2. data/.yardopts +11 -0
  3. data/LICENSE +3 -1
  4. data/README.rdoc +25 -122
  5. data/Rakefile +14 -0
  6. data/VERSION +1 -1
  7. data/bin/plist4r +2 -0
  8. data/ext/osx_plist/Makefile +157 -0
  9. data/ext/osx_plist/extconf.rb +9 -0
  10. data/ext/osx_plist/plist.c +606 -0
  11. data/ext/osx_plist/plist.o +0 -0
  12. data/lib/plist4r.rb +6 -3
  13. data/lib/plist4r/application.rb +1 -2
  14. data/lib/plist4r/backend.rb +102 -34
  15. data/lib/plist4r/backend/c_f_property_list.rb +65 -0
  16. data/lib/plist4r/backend/c_f_property_list/LICENSE +19 -0
  17. data/lib/plist4r/backend/c_f_property_list/README +34 -0
  18. data/lib/plist4r/backend/c_f_property_list/cfpropertylist.rb +6 -0
  19. data/lib/plist4r/backend/c_f_property_list/rbBinaryCFPropertyList.rb +663 -0
  20. data/lib/plist4r/backend/c_f_property_list/rbCFPlistError.rb +26 -0
  21. data/lib/plist4r/backend/c_f_property_list/rbCFPropertyList.rb +348 -0
  22. data/lib/plist4r/backend/c_f_property_list/rbCFTypes.rb +241 -0
  23. data/lib/plist4r/backend/c_f_property_list/rbXMLCFPropertyList.rb +116 -0
  24. data/lib/plist4r/backend/example.rb +37 -52
  25. data/lib/plist4r/backend/haml.rb +47 -36
  26. data/lib/plist4r/backend/libxml4r.rb +24 -20
  27. data/lib/plist4r/backend/osx_plist.rb +82 -0
  28. data/lib/plist4r/backend/ruby_cocoa.rb +172 -54
  29. data/lib/plist4r/backend/test/data_types.rb +163 -0
  30. data/lib/plist4r/backend/test/harness.rb +255 -0
  31. data/lib/plist4r/backend/test/output.rb +47 -0
  32. data/lib/plist4r/backend_base.rb +4 -2
  33. data/lib/plist4r/{options.rb → cli.rb} +2 -1
  34. data/lib/plist4r/commands.rb +13 -8
  35. data/lib/plist4r/config.rb +36 -9
  36. data/lib/plist4r/docs/Backends.html +59 -0
  37. data/lib/plist4r/docs/DeveloperGuide.rdoc +53 -0
  38. data/lib/plist4r/docs/EditingPlistFiles.rdoc +88 -0
  39. data/lib/plist4r/docs/InfoPlistExample.rdoc +33 -0
  40. data/lib/plist4r/docs/LaunchdPlistExample.rdoc +33 -0
  41. data/lib/plist4r/docs/PlistKeyNames.rdoc +47 -0
  42. data/lib/plist4r/mixin/array_dict.rb +61 -0
  43. data/lib/plist4r/mixin/data_methods.rb +178 -54
  44. data/lib/plist4r/mixin/haml4r.rb +4 -0
  45. data/lib/plist4r/mixin/haml4r/css_attributes.rb +19 -0
  46. data/lib/plist4r/mixin/haml4r/examples.rb +261 -0
  47. data/lib/plist4r/mixin/haml4r/haml_table_example.rb +79 -0
  48. data/lib/plist4r/mixin/haml4r/table.rb +157 -0
  49. data/lib/plist4r/mixin/haml4r/table_cell.rb +160 -0
  50. data/lib/plist4r/mixin/haml4r/table_cells.rb +485 -0
  51. data/lib/plist4r/mixin/haml4r/table_section.rb +101 -0
  52. data/lib/plist4r/mixin/ordered_hash.rb +9 -1
  53. data/lib/plist4r/mixin/popen4.rb +1 -1
  54. data/lib/plist4r/mixin/ruby_stdlib.rb +154 -1
  55. data/lib/plist4r/mixin/script.rb +133 -0
  56. data/lib/plist4r/mixin/table.rb +435 -0
  57. data/lib/plist4r/plist.rb +272 -94
  58. data/lib/plist4r/plist_cache.rb +42 -43
  59. data/lib/plist4r/plist_type.rb +31 -74
  60. data/lib/plist4r/plist_type/info.rb +157 -3
  61. data/lib/plist4r/plist_type/launchd.rb +54 -48
  62. data/lib/plist4r/plist_type/plist.rb +1 -3
  63. data/plist4r.gemspec +74 -14
  64. data/spec/{examples.rb → launchd_examples.rb} +131 -139
  65. data/spec/plist4r/application_spec.rb +37 -0
  66. data/spec/plist4r/backend_spec.rb +256 -0
  67. data/spec/plist4r/cli_spec.rb +25 -0
  68. data/spec/plist4r/commands_spec.rb +20 -0
  69. data/spec/plist4r/config_spec.rb +38 -0
  70. data/spec/plist4r/mixin/array_dict_spec.rb +120 -0
  71. data/spec/plist4r/mixin/data_methods_spec.rb +96 -0
  72. data/spec/plist4r/mixin/haml4r/examples.rb +261 -0
  73. data/spec/plist4r/mixin/ruby_stdlib_spec.rb +228 -0
  74. data/spec/plist4r/plist_cache_spec.rb +261 -0
  75. data/spec/plist4r/plist_spec.rb +841 -23
  76. data/spec/plist4r/plist_type_spec.rb +126 -0
  77. data/spec/plist4r_spec.rb +53 -27
  78. data/spec/scratchpad.rb +226 -0
  79. data/spec/spec_helper.rb +5 -1
  80. metadata +109 -23
  81. data/lib/plist4r/backend/plutil.rb +0 -25
  82. data/lib/plist4r/mixin.rb +0 -7
  83. data/plists/array_mini.xml +0 -14
  84. data/plists/example_big_binary.plist +0 -0
  85. data/plists/example_medium_binary_launchd.plist +0 -0
  86. data/plists/example_medium_launchd.xml +0 -53
  87. data/plists/mini.xml +0 -12
  88. data/test.rb +0 -40
@@ -0,0 +1,26 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Exceptions used:
4
+ # CFPlistError:: General base exception
5
+ # CFFormatError:: Format error
6
+ # CFTypeError:: Type error
7
+ #
8
+ # Easy and simple :-)
9
+ #
10
+ # Author:: Christian Kruse (mailto:cjk@wwwtech.de)
11
+ # Copyright:: Copyright (c) 2010
12
+ # License:: MIT License
13
+
14
+ # general plist error. All exceptions thrown are derived from this class.
15
+ class CFPlistError < Exception
16
+ end
17
+
18
+ # Exception thrown when format errors occur
19
+ class CFFormatError < CFPlistError
20
+ end
21
+
22
+ # Exception thrown when type errors occur
23
+ class CFTypeError < CFPlistError
24
+ end
25
+
26
+ # eof
@@ -0,0 +1,348 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'libxml'
4
+ require 'kconv'
5
+ require 'date'
6
+
7
+ #
8
+ # CFPropertyList implementation
9
+ #
10
+ # class to read, manipulate and write both XML and binary property list
11
+ # files (plist(5)) as defined by Apple. Have a look at CFPropertyList::List
12
+ # for more documentation.
13
+ #
14
+ # == Example
15
+ # require 'cfpropertylist'
16
+ #
17
+ # # create a arbitrary data structure of basic data types
18
+ # data = {
19
+ # 'name' => 'John Doe',
20
+ # 'missing' => true,
21
+ # 'last_seen' => Time.now,
22
+ # 'friends' => ['Jane Doe','Julian Doe'],
23
+ # 'likes' => {
24
+ # 'me' => false
25
+ # }
26
+ # }
27
+ #
28
+ # # create CFPropertyList::List object
29
+ # plist = CFPropertyList::List.new
30
+ #
31
+ # # call CFPropertyList.guess() to create corresponding CFType values
32
+ # # pass in optional :convert_unknown_to_string => true to convert things like symbols into strings.
33
+ # plist.value = CFPropertyList.guess(data)
34
+ #
35
+ # # write plist to file
36
+ # plist.save("example.plist", CFPropertyList::List::FORMAT_BINARY)
37
+ #
38
+ # # … later, read it again
39
+ # plist = CFPropertyList::List.new(:file => "example.plist")
40
+ # data = CFPropertyList.native_types(plist.value)
41
+ #
42
+ # Author:: Christian Kruse (mailto:cjk@wwwtech.de)
43
+ # Copyright:: Copyright (c) 2010
44
+ # License:: MIT License
45
+ module CFPropertyList
46
+ # interface class for PList parsers
47
+ class ParserInterface
48
+ # load a plist
49
+ def load(opts={})
50
+ return ""
51
+ end
52
+
53
+ # convert a plist to string
54
+ def to_str(opts={})
55
+ return true
56
+ end
57
+ end
58
+ end
59
+
60
+ class String
61
+ unless("".respond_to?(:blob) && "".respond_to?(:blob=)) then
62
+ # The blob status of this string (to set to true if a binary string)
63
+ attr_accessor :blob
64
+ end
65
+
66
+ unless("".respond_to?(:blob?)) then
67
+ # Returns whether or not +str+ is a blob.
68
+ # @return [true,false] If true, this string contains binary data. If false, its a regular string
69
+ def blob?
70
+ @blob
71
+ end
72
+ end
73
+
74
+ unless("".respond_to?(:bytesize)) then
75
+ def bytesize
76
+ self.length
77
+ end
78
+ end
79
+ end
80
+
81
+ dirname = File.dirname(__FILE__)
82
+ require dirname + '/rbCFPlistError.rb'
83
+ require dirname + '/rbCFTypes.rb'
84
+ require dirname + '/rbXMLCFPropertyList.rb'
85
+ require dirname + '/rbBinaryCFPropertyList.rb'
86
+
87
+ require 'iconv' unless "".respond_to?("encode")
88
+
89
+ module CFPropertyList
90
+ # Create CFType hierarchy by guessing the correct CFType, e.g.
91
+ #
92
+ # x = {
93
+ # 'a' => ['b','c','d']
94
+ # }
95
+ # cftypes = CFPropertyList.guess(x)
96
+ #
97
+ # pass optional options hash. Only possible value actually:
98
+ # +convert_unknown_to_string+:: Convert unknown objects to string calling to_str()
99
+ # +converter_method+:: Convert unknown objects to known objects calling +method_name+
100
+ #
101
+ # cftypes = CFPropertyList.guess(x,:convert_unknown_to_string => true,:converter_method => :to_hash)
102
+ def guess(object, options = {})
103
+ if(object.is_a?(Fixnum) || object.is_a?(Integer)) then
104
+ return CFInteger.new(object)
105
+ elsif(object.is_a?(Float) || (Object.const_defined?('BigDecimal') and object.is_a?(BigDecimal))) then
106
+ return CFReal.new(object)
107
+ elsif(object.is_a?(TrueClass) || object.is_a?(FalseClass)) then
108
+ return CFBoolean.new(object)
109
+ elsif(object.is_a?(String)) then
110
+ return object.blob? ? CFData.new(object, CFData::DATA_RAW) : CFString.new(object)
111
+ elsif(object.is_a?(Time) || object.is_a?(DateTime) || object.is_a?(Date)) then
112
+ return CFDate.new(object)
113
+ elsif(object.is_a?(Array)) then
114
+ ary = Array.new
115
+ object.each do
116
+ |o|
117
+ ary.push CFPropertyList.guess(o, options)
118
+ end
119
+
120
+ return CFArray.new(ary)
121
+ elsif(object.is_a?(Hash)) then
122
+ hsh = Hash.new
123
+ object.each_pair do
124
+ |k,v|
125
+ k = k.to_s if k.is_a?(Symbol)
126
+ hsh[k] = CFPropertyList.guess(v, options)
127
+ end
128
+
129
+ return CFDictionary.new(hsh)
130
+ elsif options[:converter_method] and object.respond_to?(options[:converter_method]) then
131
+ return CFPropertyList.guess(object.send(options[:converter_method]))
132
+ elsif options[:convert_unknown_to_string] then
133
+ return CFString.new(object.to_s)
134
+ else
135
+ raise CFTypeError.new("Unknown class #{object.class.to_s}! Try using :convert_unknown_to_string if you want to use unknown object types!")
136
+ end
137
+ end
138
+
139
+ # Converts a CFType hiercharchy to native Ruby types
140
+ def native_types(object,keys_as_symbols=false)
141
+ return if object.nil?
142
+
143
+ if(object.is_a?(CFDate) || object.is_a?(CFString) || object.is_a?(CFInteger) || object.is_a?(CFReal) || object.is_a?(CFBoolean)) then
144
+ return object.value
145
+ elsif(object.is_a?(CFData)) then
146
+ return object.decoded_value
147
+ elsif(object.is_a?(CFArray)) then
148
+ ary = []
149
+ object.value.each do
150
+ |v|
151
+ ary.push CFPropertyList.native_types(v)
152
+ end
153
+
154
+ return ary
155
+ elsif(object.is_a?(CFDictionary)) then
156
+ hsh = {}
157
+ object.value.each_pair do
158
+ |k,v|
159
+ k = k.to_sym if keys_as_symbols
160
+ hsh[k] = CFPropertyList.native_types(v)
161
+ end
162
+
163
+ return hsh
164
+ end
165
+ end
166
+
167
+ module_function :guess, :native_types
168
+
169
+ # Class representing a CFPropertyList. Instanciate with #new
170
+ class List
171
+ # Format constant for binary format
172
+ FORMAT_BINARY = 1
173
+
174
+ # Format constant for XML format
175
+ FORMAT_XML = 2
176
+
177
+ # Format constant for automatic format recognizing
178
+ FORMAT_AUTO = 0
179
+
180
+ @@parsers = [Binary,XML]
181
+
182
+ # Path of PropertyList
183
+ attr_accessor :filename
184
+ # Path of PropertyList
185
+ attr_accessor :format
186
+ # the root value in the plist file
187
+ attr_accessor :value
188
+
189
+ # initialize a new CFPropertyList, arguments are:
190
+ #
191
+ # :file:: Parse a file
192
+ # :format:: Format is one of FORMAT_BINARY or FORMAT_XML. Defaults to FORMAT_AUTO
193
+ # :data:: Parse a string
194
+ #
195
+ # All arguments are optional
196
+ def initialize(opts={})
197
+ @filename = opts[:file]
198
+ @format = opts[:format] || FORMAT_AUTO
199
+ @data = opts[:data]
200
+
201
+ load(@filename) unless @filename.nil?
202
+ load_str(@data) unless @data.nil?
203
+ end
204
+
205
+ # Load an XML PropertyList
206
+ # filename = nil:: The filename to read from; if nil, read from the file defined by instance variable +filename+
207
+ def load_xml(filename=nil)
208
+ load(filename,List::FORMAT_XML)
209
+ end
210
+
211
+ # read a binary plist file
212
+ # filename = nil:: The filename to read from; if nil, read from the file defined by instance variable +filename+
213
+ def load_binary(filename=nil)
214
+ load(filename,List::FORMAT_BINARY)
215
+ end
216
+
217
+ # load a plist from a XML string
218
+ # str:: The string containing the plist
219
+ def load_xml_str(str=nil)
220
+ load_str(str,List::FORMAT_XML)
221
+ end
222
+
223
+ # load a plist from a binary string
224
+ # str:: The string containing the plist
225
+ def load_binary_str(str=nil)
226
+ load_str(str,List::FORMAT_BINARY)
227
+ end
228
+
229
+ # load a plist from a string
230
+ # str = nil:: The string containing the plist
231
+ # format = nil:: The format of the plist
232
+ def load_str(str=nil,format=nil)
233
+ str = @data if str.nil?
234
+ format = @format if format.nil?
235
+
236
+ @value = {}
237
+ case format
238
+ when List::FORMAT_BINARY, List::FORMAT_XML then
239
+ prsr = @@parsers[format-1].new
240
+ @value = prsr.load({:data => str})
241
+
242
+ when List::FORMAT_AUTO then # what we now do is ugly, but neccessary to recognize the file format
243
+ filetype = str[0..5]
244
+ version = str[6..7]
245
+
246
+ prsr = nil
247
+ if filetype == "bplist" then
248
+ raise CFFormatError.new("Wong file version #{version}") unless version == "00"
249
+ prsr = Binary.new
250
+ else
251
+ prsr = XML.new
252
+ end
253
+
254
+ @value = prsr.load({:data => str})
255
+ end
256
+ end
257
+
258
+ # Read a plist file
259
+ # file = nil:: The filename of the file to read. If nil, use +filename+ instance variable
260
+ # format = nil:: The format of the plist file. Auto-detect if nil
261
+ def load(file=nil,format=nil)
262
+ file = @filename if file.nil?
263
+ format = @format if format.nil?
264
+ @value = {}
265
+
266
+ raise IOError.new("File #{file} not readable!") unless File.readable? file
267
+
268
+ case format
269
+ when List::FORMAT_BINARY, List::FORMAT_XML then
270
+ prsr = @@parsers[format-1].new
271
+ @value = prsr.load({:file => file})
272
+
273
+ when List::FORMAT_AUTO then # what we now do is ugly, but neccessary to recognize the file format
274
+ magic_number = IO.read(file,8)
275
+ filetype = magic_number[0..5]
276
+ version = magic_number[6..7]
277
+
278
+ prsr = nil
279
+ if filetype == "bplist" then
280
+ raise CFFormatError.new("Wong file version #{version}") unless version == "00"
281
+ prsr = Binary.new
282
+ else
283
+ prsr = XML.new
284
+ end
285
+
286
+ @value = prsr.load({:file => file})
287
+ end
288
+ end
289
+
290
+ # Serialize CFPropertyList object to specified format and write it to file
291
+ # file = nil:: The filename of the file to write to. Uses +filename+ instance variable if nil
292
+ # format = nil:: The format to save in. Uses +format+ instance variable if nil
293
+ def save(file=nil,format=nil,opts={})
294
+ format = @format if format.nil?
295
+ file = @filename if file.nil?
296
+
297
+ raise CFFormatError.new("Format #{format} not supported, use List::FORMAT_BINARY or List::FORMAT_XML") if format != FORMAT_BINARY && format != FORMAT_XML
298
+
299
+ if(!File.exists?(file)) then
300
+ raise IOError.new("File #{file} not writable!") unless File.writable?(File.dirname(file))
301
+ elsif(!File.writable?(file)) then
302
+ raise IOError.new("File #{file} not writable!")
303
+ end
304
+
305
+ opts[:root] = @value
306
+ prsr = @@parsers[format-1].new
307
+ content = prsr.to_str(opts)
308
+
309
+ File.open(file, 'wb') {
310
+ |fd|
311
+ fd.write content
312
+ }
313
+ end
314
+
315
+ # convert plist to string
316
+ # format = List::FORMAT_BINARY:: The format to save the plist
317
+ # opts={}:: Pass parser options
318
+ def to_str(format=List::FORMAT_BINARY,opts={})
319
+ prsr = @@parsers[format-1].new
320
+ opts[:root] = @value
321
+ return prsr.to_str(opts)
322
+ end
323
+ end
324
+ end
325
+
326
+ class Array
327
+ # convert an array to plist format
328
+ def to_plist(options={})
329
+ options[:plist_format] ||= CFPropertyList::List::FORMAT_BINARY
330
+
331
+ plist = CFPropertyList::List.new
332
+ plist.value = CFPropertyList.guess(self, options)
333
+ plist.to_str(options[:plist_format])
334
+ end
335
+ end
336
+
337
+ class Hash
338
+ # convert a hash to plist format
339
+ def to_plist(options={})
340
+ options[:plist_format] ||= CFPropertyList::List::FORMAT_BINARY
341
+
342
+ plist = CFPropertyList::List.new
343
+ plist.value = CFPropertyList.guess(self, options)
344
+ plist.to_str(options[:plist_format])
345
+ end
346
+ end
347
+
348
+ # eof
@@ -0,0 +1,241 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # CFTypes, e.g. CFString, CFInteger
4
+ # needed to create unambiguous plists
5
+ #
6
+ # Author:: Christian Kruse (mailto:cjk@wwwtech.de)
7
+ # Copyright:: Copyright (c) 2009
8
+ # License:: MIT License
9
+
10
+ require 'base64'
11
+
12
+ module CFPropertyList
13
+ # This class defines the base class for all CFType classes
14
+ #
15
+ class CFType
16
+ # value of the type
17
+ attr_accessor :value
18
+
19
+
20
+ # set internal value to parameter value by default
21
+ def initialize(value=nil)
22
+ @value = value
23
+ end
24
+
25
+ # convert type to XML
26
+ def to_xml
27
+ end
28
+
29
+ # convert type to binary
30
+ def to_binary(bplist)
31
+ end
32
+ end
33
+
34
+ # This class holds string values, both, UTF-8 and UTF-16BE
35
+ # It will convert the value to UTF-16BE if necessary (i.e. if non-ascii char contained)
36
+ class CFString < CFType
37
+ # convert to XML
38
+ def to_xml
39
+ n = LibXML::XML::Node.new('string')
40
+ n << LibXML::XML::Node.new_text(@value) unless @value.nil?
41
+ return n
42
+ end
43
+
44
+ # convert to binary
45
+ def to_binary(bplist)
46
+ return bplist.string_to_binary(@value);
47
+ end
48
+ end
49
+
50
+ # This class holds integer/fixnum values
51
+ class CFInteger < CFType
52
+ # convert to XML
53
+ def to_xml
54
+ return LibXML::XML::Node.new('integer') << LibXML::XML::Node.new_text(@value.to_s)
55
+ end
56
+
57
+ # convert to binary
58
+ def to_binary(bplist)
59
+ return bplist.num_to_binary(self)
60
+ end
61
+ end
62
+
63
+ # This class holds float values
64
+ class CFReal < CFType
65
+ # convert to XML
66
+ def to_xml
67
+ return LibXML::XML::Node.new('real') << LibXML::XML::Node.new_text(@value.to_s)
68
+ end
69
+
70
+ # convert to binary
71
+ def to_binary(bplist)
72
+ return bplist.num_to_binary(self)
73
+ end
74
+ end
75
+
76
+ # This class holds Time values. While Apple uses seconds since 2001,
77
+ # the rest of the world uses seconds since 1970. So if you access value
78
+ # directly, you get the Time class. If you access via get_value you either
79
+ # geht the timestamp or the Apple timestamp
80
+ class CFDate < CFType
81
+ TIMESTAMP_APPLE = 0
82
+ TIMESTAMP_UNIX = 1;
83
+ DATE_DIFF_APPLE_UNIX = 978307200
84
+
85
+ # create a XML date strimg from a time object
86
+ def CFDate.date_string(val)
87
+ # 2009-05-13T20:23:43Z
88
+ val.getutc.strftime("%Y-%m-%dT%H:%M:%SZ")
89
+ end
90
+
91
+ # parse a XML date string
92
+ def CFDate.parse_date(val)
93
+ # 2009-05-13T20:23:43Z
94
+ val =~ %r{^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$}
95
+ year,month,day,hour,min,sec = $1, $2, $3, $4, $5, $6
96
+ return Time.utc(year,month,day,hour,min,sec).getlocal
97
+ end
98
+
99
+ # set value to defined state
100
+ def initialize(value = nil,format=CFDate::TIMESTAMP_UNIX)
101
+ if(value.is_a?(Time) || value.nil?) then
102
+ @value = value.nil? ? Time.now : value
103
+ else
104
+ set_value(value,format)
105
+ end
106
+ end
107
+
108
+ # set value with timestamp, either Apple or UNIX
109
+ def set_value(value,format=CFDate::TIMESTAMP_UNIX)
110
+ if(format == CFDate::TIMESTAMP_UNIX) then
111
+ @value = Time.at(value)
112
+ else
113
+ @value = Time.at(value + CFDate::DATE_DIFF_APPLE_UNIX)
114
+ end
115
+ end
116
+
117
+ # get timestamp, either UNIX or Apple timestamp
118
+ def get_value(format=CFDate::TIMESTAMP_UNIX)
119
+ if(format == CFDate::TIMESTAMP_UNIX) then
120
+ return @value.to_i
121
+ else
122
+ return @value.to_f - CFDate::DATE_DIFF_APPLE_UNIX
123
+ end
124
+ end
125
+
126
+ # convert to XML
127
+ def to_xml
128
+ return LibXML::XML::Node.new('date') << LibXML::XML::Node.new_text(CFDate::date_string(@value))
129
+ end
130
+
131
+ # convert to binary
132
+ def to_binary(bplist)
133
+ return bplist.date_to_binary(@value)
134
+ end
135
+ end
136
+
137
+ # This class contains a boolean value
138
+ class CFBoolean < CFType
139
+ # convert to XML
140
+ def to_xml
141
+ return LibXML::XML::Node.new(@value ? 'true' : 'false')
142
+ end
143
+
144
+ # convert to binary
145
+ def to_binary(bplist)
146
+ return bplist.bool_to_binary(@value);
147
+ end
148
+ end
149
+
150
+ # This class contains binary data values
151
+ class CFData < CFType
152
+ # Base64 encoded data
153
+ DATA_BASE64 = 0
154
+ # Raw data
155
+ DATA_RAW = 1
156
+
157
+ # set value to defined state, either base64 encoded or raw
158
+ def initialize(value=nil,format=DATA_BASE64)
159
+ if(format == DATA_RAW) then
160
+ @raw_value = value
161
+ @raw_value.blob = true
162
+ else
163
+ @value = value
164
+ end
165
+ end
166
+
167
+ # get base64 encoded value
168
+ def encoded_value
169
+ @value ||= Base64.encode64(@raw_value)
170
+ end
171
+
172
+ # get base64 decoded value
173
+ def decoded_value
174
+ @raw_value ||= String.new(Base64.decode64(@value))
175
+ @raw_value.blob = true
176
+ @raw_value
177
+ end
178
+
179
+ # convert to XML
180
+ def to_xml
181
+ return LibXML::XML::Node.new('data') << LibXML::XML::Node.new_text(encoded_value())
182
+ end
183
+
184
+ # convert to binary
185
+ def to_binary(bplist)
186
+ return bplist.data_to_binary(decoded_value())
187
+ end
188
+ end
189
+
190
+ # This class contains an array of values
191
+ class CFArray < CFType
192
+ # create a new array CFType
193
+ def initialize(val=[])
194
+ @value = val
195
+ end
196
+
197
+ # convert to XML
198
+ def to_xml
199
+ n = LibXML::XML::Node.new('array')
200
+ @value.each do
201
+ |v|
202
+ n << v.to_xml
203
+ end
204
+
205
+ return n
206
+ end
207
+
208
+ # convert to binary
209
+ def to_binary(bplist)
210
+ return bplist.array_to_binary(self)
211
+ end
212
+ end
213
+
214
+ # this class contains a hash of values
215
+ class CFDictionary < CFType
216
+ # Create new CFDictonary type.
217
+ def initialize(value={})
218
+ @value = value
219
+ end
220
+
221
+ # convert to XML
222
+ def to_xml
223
+ n = LibXML::XML::Node.new('dict')
224
+ @value.each_pair do
225
+ |key,value|
226
+ k = LibXML::XML::Node.new('key') << LibXML::XML::Node.new_text(key)
227
+ n << k
228
+ n << value.to_xml
229
+ end
230
+
231
+ return n
232
+ end
233
+
234
+ # convert to binary
235
+ def to_binary(bplist)
236
+ return bplist.dict_to_binary(self)
237
+ end
238
+ end
239
+ end
240
+
241
+ # eof