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