module Puppet::Util::Plist
Public Class Methods
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
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
# 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
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
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
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
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
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 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
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
# 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
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