module Puppet::Util::Plist

Public Class Methods

binary_plist_magic_number() click to toggle source

Defines the magic number for binary plists

@api private

   # File lib/puppet/util/plist.rb
15 def binary_plist_magic_number
16   "bplist00"
17 end
convert_cfpropertylist_to_native_types(plist_obj) click to toggle source

Helper method to assist in converting a native CFPropertyList object to a native Ruby object (hash). It's its own method for stubbing purposes

@api private

    # File lib/puppet/util/plist.rb
111 def convert_cfpropertylist_to_native_types(plist_obj)
112   CFPropertyList.native_types(plist_obj.value)
113 end
dump_plist(plist_data, format = :xml) click to toggle source
    # File lib/puppet/util/plist.rb
155 def dump_plist(plist_data, format = :xml)
156   plist_to_save       = CFPropertyList::List.new
157   plist_to_save.value = CFPropertyList.guess(plist_data)
158   plist_to_save.to_str(to_format(format), :formatted => true)
159 end
new_cfpropertylist(plist_opts) click to toggle source

Helper method to assist in generating a new CFPropertyList Plist. It's its own method for stubbing purposes

@api private

    # File lib/puppet/util/plist.rb
103 def new_cfpropertylist(plist_opts)
104   CFPropertyList::List.new(plist_opts)
105 end
open_file_with_args(file, args) click to toggle source

Helper method to assist in reading a file. It's its own method for stubbing purposes

@api private

@param args [String] Extra file operation mode information to use

(defaults to read-only mode 'r')
This is the standard mechanism Ruby uses in the IO class, and therefore
encoding may be explicitly like fmode : encoding or fmode : "BOM|UTF-*"
for example, a:ASCII or w+:UTF-8
   # File lib/puppet/util/plist.rb
95 def open_file_with_args(file, args)
96   File.open(file, args).read
97 end
parse_plist(plist_data, file_path = '') click to toggle source

Read plist text using the CFPropertyList gem.

   # File lib/puppet/util/plist.rb
57 def parse_plist(plist_data, file_path = '')
58   bad_xml_doctype = /^.*<!DOCTYPE plist PUBLIC -\/\/Apple Computer.*$/
59   # Depending on where parse_plist is called from, plist_data can be either XML or binary.
60   # If we get XML, make sure ruby knows it's UTF-8 so we avoid invalid byte sequence errors.
61   if plist_data.include?('encoding="UTF-8"') && plist_data.encoding != Encoding::UTF_8
62     plist_data.force_encoding(Encoding::UTF_8)
63   end
64 
65   begin
66     if plist_data =~ bad_xml_doctype
67       plist_data.gsub!( bad_xml_doctype, plist_xml_doctype )
68       Puppet.debug("Had to fix plist with incorrect DOCTYPE declaration: #{file_path}")
69     end
70   rescue ArgumentError => e
71     Puppet.debug "Failed with #{e.class} on #{file_path}: #{e.inspect}"
72     return nil
73   end
74 
75   begin
76     plist_obj = new_cfpropertylist(:data => plist_data)
77   # CFPropertyList library will raise NoMethodError for invalid data
78   rescue CFFormatError, NoMethodError => e
79     Puppet.debug "Failed with #{e.class} on #{file_path}: #{e.inspect}"
80     return nil
81   end
82   convert_cfpropertylist_to_native_types(plist_obj)
83 end
plist_xml_doctype() click to toggle source

Defines a default doctype string that should be at the top of most plist files. Useful if we need to modify an invalid doctype string in memory. In version 10.9 and lower of OS X the plist at /System/Library/LaunchDaemons/org.ntp.ntpd.plist had an invalid doctype string. This corrects for that.

   # File lib/puppet/util/plist.rb
24 def plist_xml_doctype
25   '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'
26 end
read_file_with_offset(file_path, offset) click to toggle source

Helper method to assist in reading a file with an offset value. It's its own method for stubbing purposes

@api private

    # File lib/puppet/util/plist.rb
127 def read_file_with_offset(file_path, offset)
128   IO.read(file_path, offset)
129 end
read_plist_file(file_path) click to toggle source

Read a plist file, whether its format is XML or in Apple's “binary1” format, using the CFPropertyList gem.

   # File lib/puppet/util/plist.rb
30 def read_plist_file(file_path)
31   # We can't really read the file until we know the source encoding in
32   # Ruby 1.9.x, so we use the magic number to detect it.
33   # NOTE: We used IO.read originally to be Ruby 1.8.x compatible.
34   if read_file_with_offset(file_path, binary_plist_magic_number.length) == binary_plist_magic_number
35     plist_obj = new_cfpropertylist(:file => file_path)
36     return convert_cfpropertylist_to_native_types(plist_obj)
37   else
38     plist_data = open_file_with_args(file_path, "r:UTF-8")
39     plist = parse_plist(plist_data, file_path)
40     return plist if plist
41 
42     Puppet.debug "Plist #{file_path} ill-formatted, converting with plutil"
43     begin
44       plist = Puppet::Util::Execution.execute(['/usr/bin/plutil', '-convert', 'xml1', '-o', '-', file_path],
45                                               {:failonfail => true, :combine => true})
46       return parse_plist(plist)
47     rescue Puppet::ExecutionFailure => detail
48       message = _("Cannot read file %{file_path}; Puppet is skipping it.") % { file_path: file_path }
49       message += '\n' + _("Details: %{detail}") % { detail: detail }
50       Puppet.warning(message)
51     end
52   end
53   return nil
54 end
string_to_blob(str) click to toggle source

Helper method to convert a string into a CFProperty::Blob, which is needed to properly handle binary strings

@api private

    # File lib/puppet/util/plist.rb
119 def string_to_blob(str)
120   CFPropertyList::Blob.new(str)
121 end
to_format(format) click to toggle source
    # File lib/puppet/util/plist.rb
131 def to_format(format)
132   if format.to_sym == :xml
133     CFPropertyList::List::FORMAT_XML
134   elsif format.to_sym == :binary
135     CFPropertyList::List::FORMAT_BINARY
136   elsif format.to_sym == :plain
137     CFPropertyList::List::FORMAT_PLAIN
138   else
139     raise FormatError.new "Unknown plist format #{format}"
140   end
141 end
write_plist_file(plist, file_path, format = :xml) click to toggle source

This method will write a plist file using a specified format (or XML by default)

    # File lib/puppet/util/plist.rb
145 def write_plist_file(plist, file_path, format = :xml)
146   begin
147     plist_to_save       = CFPropertyList::List.new
148     plist_to_save.value = CFPropertyList.guess(plist)
149     plist_to_save.save(file_path, to_format(format), :formatted => true)
150   rescue IOError => e
151     Puppet.err(_("Unable to write the file %{file_path}. %{error}") % { file_path: file_path, error: e.inspect })
152   end
153 end