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
16 def binary_plist_magic_number
17   "bplist00"
18 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
112 def convert_cfpropertylist_to_native_types(plist_obj)
113   CFPropertyList.native_types(plist_obj.value)
114 end
dump_plist(plist_data, format = :xml) click to toggle source
    # File lib/puppet/util/plist.rb
156 def dump_plist(plist_data, format = :xml)
157   plist_to_save       = CFPropertyList::List.new
158   plist_to_save.value = CFPropertyList.guess(plist_data)
159   plist_to_save.to_str(to_format(format), :formatted => true)
160 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
104 def new_cfpropertylist(plist_opts)
105   CFPropertyList::List.new(plist_opts)
106 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
96 def open_file_with_args(file, args)
97   File.open(file, args).read
98 end
parse_plist(plist_data, file_path = '') click to toggle source

Read plist text using the CFPropertyList gem.

   # File lib/puppet/util/plist.rb
58 def parse_plist(plist_data, file_path = '')
59   bad_xml_doctype = /^.*<!DOCTYPE plist PUBLIC -\/\/Apple Computer.*$/
60   # Depending on where parse_plist is called from, plist_data can be either XML or binary.
61   # If we get XML, make sure ruby knows it's UTF-8 so we avoid invalid byte sequence errors.
62   if plist_data.include?('encoding="UTF-8"') && plist_data.encoding != Encoding::UTF_8
63     plist_data.force_encoding(Encoding::UTF_8)
64   end
65 
66   begin
67     if plist_data =~ bad_xml_doctype
68       plist_data.gsub!( bad_xml_doctype, plist_xml_doctype )
69       Puppet.debug("Had to fix plist with incorrect DOCTYPE declaration: #{file_path}")
70     end
71   rescue ArgumentError => e
72     Puppet.debug "Failed with #{e.class} on #{file_path}: #{e.inspect}"
73     return nil
74   end
75 
76   begin
77     plist_obj = new_cfpropertylist(:data => plist_data)
78   # CFPropertyList library will raise NoMethodError for invalid data
79   rescue CFFormatError, NoMethodError => e
80     Puppet.debug "Failed with #{e.class} on #{file_path}: #{e.inspect}"
81     return nil
82   end
83   convert_cfpropertylist_to_native_types(plist_obj)
84 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
25 def plist_xml_doctype
26   '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'
27 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
128 def read_file_with_offset(file_path, offset)
129   IO.read(file_path, offset)
130 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
31 def read_plist_file(file_path)
32   # We can't really read the file until we know the source encoding in
33   # Ruby 1.9.x, so we use the magic number to detect it.
34   # NOTE: We used IO.read originally to be Ruby 1.8.x compatible.
35   if read_file_with_offset(file_path, binary_plist_magic_number.length) == binary_plist_magic_number
36     plist_obj = new_cfpropertylist(:file => file_path)
37     return convert_cfpropertylist_to_native_types(plist_obj)
38   else
39     plist_data = open_file_with_args(file_path, "r:UTF-8")
40     plist = parse_plist(plist_data, file_path)
41     return plist if plist
42 
43     Puppet.debug "Plist #{file_path} ill-formatted, converting with plutil"
44     begin
45       plist = Puppet::Util::Execution.execute(['/usr/bin/plutil', '-convert', 'xml1', '-o', '-', file_path],
46                                               {:failonfail => true, :combine => true})
47       return parse_plist(plist)
48     rescue Puppet::ExecutionFailure => detail
49       message = _("Cannot read file %{file_path}; Puppet is skipping it.") % { file_path: file_path }
50       message += '\n' + _("Details: %{detail}") % { detail: detail }
51       Puppet.warning(message)
52     end
53   end
54   return nil
55 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
120 def string_to_blob(str)
121   CFPropertyList::Blob.new(str)
122 end
to_format(format) click to toggle source
    # File lib/puppet/util/plist.rb
132 def to_format(format)
133   if format.to_sym == :xml
134     CFPropertyList::List::FORMAT_XML
135   elsif format.to_sym == :binary
136     CFPropertyList::List::FORMAT_BINARY
137   elsif format.to_sym == :plain
138     CFPropertyList::List::FORMAT_PLAIN
139   else
140     raise FormatError.new "Unknown plist format #{format}"
141   end
142 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
146 def write_plist_file(plist, file_path, format = :xml)
147   begin
148     plist_to_save       = CFPropertyList::List.new
149     plist_to_save.value = CFPropertyList.guess(plist)
150     plist_to_save.save(file_path, to_format(format), :formatted => true)
151   rescue IOError => e
152     Puppet.err(_("Unable to write the file %{file_path}. %{error}") % { file_path: file_path, error: e.inspect })
153   end
154 end