Module: Puppet::Util::Plist

Defined in:
lib/puppet/util/plist.rb

Defined Under Namespace

Classes: FormatError

Class Method Summary collapse

Class Method Details

.binary_plist_magic_numberObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Defines the magic number for binary plists



15
16
17
# File 'lib/puppet/util/plist.rb', line 15

def binary_plist_magic_number
  "bplist00"
end

.convert_cfpropertylist_to_native_types(plist_obj) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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



90
91
92
# File 'lib/puppet/util/plist.rb', line 90

def convert_cfpropertylist_to_native_types(plist_obj)
  CFPropertyList.native_types(plist_obj.value)
end

.dump_plist(plist_data, format = :xml) ⇒ Object



124
125
126
127
128
# File 'lib/puppet/util/plist.rb', line 124

def dump_plist(plist_data, format = :xml)
  plist_to_save       = CFPropertyList::List.new
  plist_to_save.value = CFPropertyList.guess(plist_data)
  plist_to_save.to_str(to_format(format))
end

.new_cfpropertylist(plist_opts) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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



82
83
84
# File 'lib/puppet/util/plist.rb', line 82

def new_cfpropertylist(plist_opts)
  CFPropertyList::List.new(plist_opts)
end

.open_file_with_args(file, args) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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



74
75
76
# File 'lib/puppet/util/plist.rb', line 74

def open_file_with_args(file, args)
  File.open(file, args).read
end

.parse_plist(plist_data, file_path = '') ⇒ Object

Read plist text using the CFPropertyList gem.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/puppet/util/plist.rb', line 54

def parse_plist(plist_data, file_path = '')
  bad_xml_doctype = /^.*<!DOCTYPE plist PUBLIC -\/\/Apple Computer.*$/
  if plist_data =~ bad_xml_doctype
    plist_data.gsub!( bad_xml_doctype, plist_xml_doctype )
    Puppet.debug("Had to fix plist with incorrect DOCTYPE declaration: #{file_path}")
  end

  begin
    plist_obj = new_cfpropertylist(:data => plist_data)
  rescue CFFormatError => e
    Puppet.debug "Failed with #{e.class} on #{file_path}: #{e.inspect}"
    return nil
  end
  convert_cfpropertylist_to_native_types(plist_obj)
end

.plist_xml_doctypeObject

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.



24
25
26
# File 'lib/puppet/util/plist.rb', line 24

def plist_xml_doctype
  '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'
end

.read_file_with_offset(file_path, offset) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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



98
99
100
# File 'lib/puppet/util/plist.rb', line 98

def read_file_with_offset(file_path, offset)
  IO.read(file_path, offset)
end

.read_plist_file(file_path) ⇒ Object

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



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/puppet/util/plist.rb', line 30

def read_plist_file(file_path)
  # We can't really read the file until we know the source encoding in
  # Ruby 1.9.x, so we use the magic number to detect it.
  # NOTE: We used IO.read originally to be Ruby 1.8.x compatible.
  if read_file_with_offset(file_path, binary_plist_magic_number.length) == binary_plist_magic_number
    plist_obj = new_cfpropertylist(:file => file_path)
    convert_cfpropertylist_to_native_types(plist_obj)
  else
    plist_data = open_file_with_args(file_path, "r:UTF-8")
    plist = parse_plist(plist_data, file_path)
    return plist if plist

    Puppet.debug "Plist #{file_path} ill-formatted, converting with plutil"
    begin
      plist = Puppet::Util::Execution.execute(['/usr/bin/plutil', '-convert', 'xml1', '-o', '/dev/stdout', file_path],
                                              {:failonfail => true, :combine => true})
      return parse_plist(plist)
    rescue Puppet::ExecutionFailure => detail
      Puppet.warning("Cannot read file #{path}; Puppet is skipping it.\n" + "Details: #{detail}")
    end
  end
end

.to_format(format) ⇒ Object



102
103
104
105
106
107
108
109
110
# File 'lib/puppet/util/plist.rb', line 102

def to_format(format)
  if format.to_sym == :xml
    plist_format = CFPropertyList::List::FORMAT_XML
  elsif format.to_sym == :binary
    plist_format = CFPropertyList::List::FORMAT_BINARY
  else
    raise FormatError.new "Unknown plist format #{format}"
  end
end

.write_plist_file(plist, file_path, format = :xml) ⇒ Object

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



114
115
116
117
118
119
120
121
122
# File 'lib/puppet/util/plist.rb', line 114

def write_plist_file(plist, file_path, format = :xml)
  begin
    plist_to_save       = CFPropertyList::List.new
    plist_to_save.value = CFPropertyList.guess(plist)
    plist_to_save.save(file_path, to_format(format))
  rescue IOError => e
    Puppet.error("Unable to write the file #{file_path}. #{e.inspect}")
  end
end