nexpose 0.2.8 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/nexpose.rb +18 -9
- data/lib/nexpose/ajax.rb +127 -0
- data/lib/nexpose/alert.rb +29 -36
- data/lib/nexpose/common.rb +13 -12
- data/lib/nexpose/connection.rb +18 -13
- data/lib/nexpose/creds.rb +16 -55
- data/lib/nexpose/dag.rb +73 -0
- data/lib/nexpose/data_table.rb +134 -0
- data/lib/nexpose/device.rb +111 -0
- data/lib/nexpose/engine.rb +194 -0
- data/lib/nexpose/filter.rb +341 -0
- data/lib/nexpose/group.rb +33 -37
- data/lib/nexpose/manage.rb +4 -0
- data/lib/nexpose/pool.rb +142 -0
- data/lib/nexpose/report.rb +72 -278
- data/lib/nexpose/report_template.rb +249 -0
- data/lib/nexpose/scan.rb +196 -54
- data/lib/nexpose/scan_template.rb +103 -0
- data/lib/nexpose/site.rb +91 -237
- data/lib/nexpose/ticket.rb +173 -119
- data/lib/nexpose/user.rb +11 -3
- data/lib/nexpose/vuln.rb +81 -338
- data/lib/nexpose/vuln_exception.rb +368 -0
- metadata +12 -4
- data/lib/nexpose/misc.rb +0 -35
- data/lib/nexpose/scan_engine.rb +0 -325
    
        data/lib/nexpose/group.rb
    CHANGED
    
    | @@ -8,35 +8,33 @@ module Nexpose | |
| 8 8 | 
             
                #
         | 
| 9 9 | 
             
                # @return [Boolean] Whether group deletion succeeded.
         | 
| 10 10 | 
             
                #
         | 
| 11 | 
            -
                def  | 
| 11 | 
            +
                def delete_asset_group(id)
         | 
| 12 12 | 
             
                  r = execute(make_xml('AssetGroupDeleteRequest', {'group-id' => id}))
         | 
| 13 13 | 
             
                  r.success
         | 
| 14 14 | 
             
                end
         | 
| 15 15 |  | 
| 16 | 
            -
                 | 
| 17 | 
            -
             | 
| 18 | 
            -
                # Retrieve a list of all asset groups the user is authorized to view or
         | 
| 16 | 
            +
                # Retrieve an array of all asset groups the user is authorized to view or
         | 
| 19 17 | 
             
                # manage.
         | 
| 20 18 | 
             
                #
         | 
| 21 19 | 
             
                # @return [Array[AssetGroupSummary]] Array of AssetGroupSummary objects.
         | 
| 22 20 | 
             
                #
         | 
| 23 | 
            -
                def  | 
| 21 | 
            +
                def list_asset_groups
         | 
| 24 22 | 
             
                  r = execute(make_xml('AssetGroupListingRequest'))
         | 
| 25 23 |  | 
| 26 | 
            -
                   | 
| 24 | 
            +
                  groups = []
         | 
| 27 25 | 
             
                  if r.success
         | 
| 28 26 | 
             
                    r.res.elements.each('AssetGroupListingResponse/AssetGroupSummary') do |group|
         | 
| 29 | 
            -
                       | 
| 30 | 
            -
                                                   group.attributes['name'] | 
| 31 | 
            -
                                                   group.attributes['description'] | 
| 27 | 
            +
                      groups << AssetGroupSummary.new(group.attributes['id'].to_i,
         | 
| 28 | 
            +
                                                   group.attributes['name'],
         | 
| 29 | 
            +
                                                   group.attributes['description'],
         | 
| 32 30 | 
             
                                                   group.attributes['riskscore'].to_f)
         | 
| 33 31 | 
             
                    end
         | 
| 34 32 | 
             
                  end
         | 
| 35 | 
            -
                   | 
| 33 | 
            +
                  groups
         | 
| 36 34 | 
             
                end
         | 
| 37 35 |  | 
| 38 | 
            -
                alias_method : | 
| 39 | 
            -
                alias_method : | 
| 36 | 
            +
                alias_method :groups, :list_asset_groups
         | 
| 37 | 
            +
                alias_method :asset_groups, :list_asset_groups
         | 
| 40 38 | 
             
              end
         | 
| 41 39 |  | 
| 42 40 | 
             
              # Summary value object for asset group information.
         | 
| @@ -53,7 +51,7 @@ module Nexpose | |
| 53 51 | 
             
                # @param [Connection] connection Connection to security console.
         | 
| 54 52 | 
             
                #
         | 
| 55 53 | 
             
                def delete(connection)
         | 
| 56 | 
            -
                  connection. | 
| 54 | 
            +
                  connection.delete_asset_group(@id)
         | 
| 57 55 | 
             
                end
         | 
| 58 56 | 
             
              end
         | 
| 59 57 |  | 
| @@ -71,13 +69,11 @@ module Nexpose | |
| 71 69 | 
             
                end
         | 
| 72 70 |  | 
| 73 71 | 
             
                def save(connection)
         | 
| 74 | 
            -
                  xml =  | 
| 72 | 
            +
                  xml = "<AssetGroupSaveRequest session-id='#{connection.session_id}'>"
         | 
| 75 73 | 
             
                  xml << to_xml
         | 
| 76 74 | 
             
                  xml << '</AssetGroupSaveRequest>'
         | 
| 77 | 
            -
                   | 
| 78 | 
            -
                  if  | 
| 79 | 
            -
                    @id = response.attributes['group-id'].to_i if @id < 0
         | 
| 80 | 
            -
                  end
         | 
| 75 | 
            +
                  res = connection.execute(xml)
         | 
| 76 | 
            +
                  @id = res.attributes['group-id'].to_i if res.success and @id < 1
         | 
| 81 77 | 
             
                end
         | 
| 82 78 |  | 
| 83 79 | 
             
                # Get an XML representation of the group that is valid for a save request.
         | 
| @@ -87,12 +83,12 @@ module Nexpose | |
| 87 83 | 
             
                # @return [String] XML representation of the asset group.
         | 
| 88 84 | 
             
                #
         | 
| 89 85 | 
             
                def to_xml
         | 
| 90 | 
            -
                  xml = % | 
| 91 | 
            -
                  xml << % | 
| 86 | 
            +
                  xml = %(<AssetGroup id="#{@id}" name="#{@name}")
         | 
| 87 | 
            +
                  xml << %( description="#{@description}") if @description
         | 
| 92 88 | 
             
                  xml << '>'
         | 
| 93 89 | 
             
                  xml << '<Devices>'
         | 
| 94 90 | 
             
                  @devices.each do |device|
         | 
| 95 | 
            -
                    xml << % | 
| 91 | 
            +
                    xml << %(<device id="#{device.id}"/>)
         | 
| 96 92 | 
             
                  end
         | 
| 97 93 | 
             
                  xml << '</Devices>'
         | 
| 98 94 | 
             
                  xml << '</AssetGroup>'
         | 
| @@ -100,45 +96,45 @@ module Nexpose | |
| 100 96 |  | 
| 101 97 | 
             
                # Launch ad hoc scans against each group of assets per site.
         | 
| 102 98 | 
             
                #
         | 
| 103 | 
            -
                # @param [Connection] connection Connection to console where asset group | 
| 104 | 
            -
                #  | 
| 105 | 
            -
                # | 
| 99 | 
            +
                # @param [Connection] connection Connection to console where asset group
         | 
| 100 | 
            +
                #   is configured.
         | 
| 101 | 
            +
                # @return [Hash] Hash of site ID to Scan launch information for each scan.
         | 
| 106 102 | 
             
                #
         | 
| 107 103 | 
             
                def rescan_assets(connection)
         | 
| 108 | 
            -
                  sites_ids = @devices. | 
| 109 | 
            -
                  scans =  | 
| 104 | 
            +
                  sites_ids = @devices.map { |d| d.site_id }.uniq
         | 
| 105 | 
            +
                  scans = {}
         | 
| 110 106 | 
             
                  sites_ids.each do |id|
         | 
| 111 | 
            -
                     | 
| 112 | 
            -
                    scans  | 
| 107 | 
            +
                    to_scan = @devices.select { |d| d.site_id == id }
         | 
| 108 | 
            +
                    scans[id] = connection.scan_devices(to_scan)
         | 
| 113 109 | 
             
                  end
         | 
| 114 110 | 
             
                  scans
         | 
| 115 111 | 
             
                end
         | 
| 116 112 |  | 
| 117 113 | 
             
                # Load an existing configuration from a Nexpose instance.
         | 
| 118 114 | 
             
                #
         | 
| 119 | 
            -
                # @param [Connection] connection Connection to console where asset group | 
| 115 | 
            +
                # @param [Connection] connection Connection to console where asset group
         | 
| 116 | 
            +
                #   is configured.
         | 
| 120 117 | 
             
                # @param [Fixnum] id Asset group ID of an existing group.
         | 
| 121 | 
            -
                # @return [AssetGroup] Asset group configuration loaded from a Nexpose | 
| 118 | 
            +
                # @return [AssetGroup] Asset group configuration loaded from a Nexpose
         | 
| 119 | 
            +
                #   console.
         | 
| 122 120 | 
             
                #
         | 
| 123 121 | 
             
                def self.load(connection, id)
         | 
| 124 | 
            -
                   | 
| 125 | 
            -
             | 
| 122 | 
            +
                  xml = %(<AssetGroupConfigRequest session-id="#{connection.session_id}" group-id="#{id}"/>)
         | 
| 123 | 
            +
                  r = APIRequest.execute(connection.url, xml)
         | 
| 126 124 | 
             
                  parse(r.res)
         | 
| 127 125 | 
             
                end
         | 
| 128 126 |  | 
| 129 | 
            -
                alias_method :get, :load
         | 
| 130 | 
            -
             | 
| 131 127 | 
             
                def self.parse(xml)
         | 
| 132 128 | 
             
                  return nil unless xml
         | 
| 133 129 |  | 
| 134 130 | 
             
                  group = REXML::XPath.first(xml, 'AssetGroupConfigResponse/AssetGroup')
         | 
| 135 | 
            -
                  asset_group = new(group.attributes['name'] | 
| 136 | 
            -
                                    group.attributes['description'] | 
| 131 | 
            +
                  asset_group = new(group.attributes['name'],
         | 
| 132 | 
            +
                                    group.attributes['description'],
         | 
| 137 133 | 
             
                                    group.attributes['id'].to_i,
         | 
| 138 134 | 
             
                                    group.attributes['riskscore'].to_f)
         | 
| 139 135 | 
             
                  group.elements.each('Devices/device') do |dev|
         | 
| 140 136 | 
             
                    asset_group.devices << Device.new(dev.attributes['id'].to_i,
         | 
| 141 | 
            -
                                                      dev.attributes['address'] | 
| 137 | 
            +
                                                      dev.attributes['address'],
         | 
| 142 138 | 
             
                                                      dev.attributes['site-id'].to_i,
         | 
| 143 139 | 
             
                                                      dev.attributes['riskfactor'].to_f,
         | 
| 144 140 | 
             
                                                      dev.attributes['riskscore'].to_f)
         | 
    
        data/lib/nexpose/manage.rb
    CHANGED
    
    | @@ -7,6 +7,7 @@ module Nexpose | |
| 7 7 | 
             
                # supplied parameter. Console commands are documented in the
         | 
| 8 8 | 
             
                # administrator's guide. If you use a command that is not listed in the
         | 
| 9 9 | 
             
                # administrator's guide, the application will return the XMLResponse.
         | 
| 10 | 
            +
                #
         | 
| 10 11 | 
             
                def console_command(cmd_string)
         | 
| 11 12 | 
             
                  xml = make_xml('ConsoleCommandRequest', {})
         | 
| 12 13 | 
             
                  cmd = REXML::Element.new('Command')
         | 
| @@ -26,6 +27,7 @@ module Nexpose | |
| 26 27 | 
             
                # Obtain system data, such as total RAM, free RAM, total disk space,
         | 
| 27 28 | 
             
                # free disk space, CPU speed, number of CPU cores, and other vital
         | 
| 28 29 | 
             
                # information.
         | 
| 30 | 
            +
                #
         | 
| 29 31 | 
             
                def system_information
         | 
| 30 32 | 
             
                  r = execute(make_xml('SystemInformationRequest', {}))
         | 
| 31 33 |  | 
| @@ -42,6 +44,7 @@ module Nexpose | |
| 42 44 |  | 
| 43 45 | 
             
                # Induce the application to retrieve required updates and restart
         | 
| 44 46 | 
             
                # if necessary.
         | 
| 47 | 
            +
                #
         | 
| 45 48 | 
             
                def start_update
         | 
| 46 49 | 
             
                  execute(make_xml('StartUpdateRequest', {})).success
         | 
| 47 50 | 
             
                end
         | 
| @@ -52,6 +55,7 @@ module Nexpose | |
| 52 55 | 
             
                # shuts down as part of the restart process, it terminates any active
         | 
| 53 56 | 
             
                # connections. Therefore, the application cannot issue a response when it
         | 
| 54 57 | 
             
                # restarts.
         | 
| 58 | 
            +
                #
         | 
| 55 59 | 
             
                def restart
         | 
| 56 60 | 
             
                  execute(make_xml('RestartRequest', {})).success
         | 
| 57 61 | 
             
                end
         | 
    
        data/lib/nexpose/pool.rb
    ADDED
    
    | @@ -0,0 +1,142 @@ | |
| 1 | 
            +
            module Nexpose
         | 
| 2 | 
            +
              module NexposeAPI
         | 
| 3 | 
            +
                include XMLUtils
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                # Retrieve a list of all Scan Engine Pools managed by the Security Console.
         | 
| 6 | 
            +
                #
         | 
| 7 | 
            +
                # @return [Array[EnginePoolSummary]] Array of EnginePoolSummary objects
         | 
| 8 | 
            +
                #   associated with each engine associated with this security console.
         | 
| 9 | 
            +
                #
         | 
| 10 | 
            +
                def list_engine_pools
         | 
| 11 | 
            +
                  response = execute(make_xml('EnginePoolListingRequest'), '1.2')
         | 
| 12 | 
            +
                  arr = []
         | 
| 13 | 
            +
                  if response.success
         | 
| 14 | 
            +
                    response.res.elements.each('EnginePoolListingResponse/EnginePoolSummary') do |pool|
         | 
| 15 | 
            +
                      arr << EnginePoolSummary.new(pool.attributes['id'],
         | 
| 16 | 
            +
                                                   pool.attributes['name'],
         | 
| 17 | 
            +
                                                   pool.attributes['scope'])
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                  arr
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                alias_method :engine_pools, :list_engine_pools
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              # A summary of an engine pool.
         | 
| 27 | 
            +
              #
         | 
| 28 | 
            +
              class EnginePoolSummary
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                # Unique identifier of the engine pool.
         | 
| 31 | 
            +
                attr_reader :id
         | 
| 32 | 
            +
                # Name of the engine pool.
         | 
| 33 | 
            +
                attr_reader :name
         | 
| 34 | 
            +
                # Whether the engine pool has global or silo scope.
         | 
| 35 | 
            +
                attr_reader :scope
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                def initialize(id, name, scope = 'silo')
         | 
| 38 | 
            +
                  @id = id
         | 
| 39 | 
            +
                  @name = name
         | 
| 40 | 
            +
                  @scope = scope
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              # Engine pool configuration object.
         | 
| 45 | 
            +
              #
         | 
| 46 | 
            +
              class EnginePool
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                # Unique identifier of the engine pool.
         | 
| 49 | 
            +
                attr_accessor :id
         | 
| 50 | 
            +
                # Name of the engine pool.
         | 
| 51 | 
            +
                attr_accessor :name
         | 
| 52 | 
            +
                # Whether the engine pool has global or silo scope.
         | 
| 53 | 
            +
                attr_accessor :scope
         | 
| 54 | 
            +
                # Array containing (EngineSummary*) for each engine assigned to the pool.
         | 
| 55 | 
            +
                attr_accessor :engines
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                def initialize(name, scope = 'silo', id = -1)
         | 
| 58 | 
            +
                  @name, @scope, @id = name, scope, id.to_i
         | 
| 59 | 
            +
                  @engines = []
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                # Add an engine to the pool by name (not ID).
         | 
| 63 | 
            +
                #
         | 
| 64 | 
            +
                # EngineSummary objects should just be appended to the pool directly,
         | 
| 65 | 
            +
                #   e.g., pool.engines << nsc.engines.find { |e| e.name == 'Cleveland' }
         | 
| 66 | 
            +
                #
         | 
| 67 | 
            +
                # @param [String] engine_name Name used to identify a paired scan engine.
         | 
| 68 | 
            +
                #
         | 
| 69 | 
            +
                def add(engine_name)
         | 
| 70 | 
            +
                  @engines << EngineSummary.new(-1, engine_name, nil, 40814, nil)
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                # Returns detailed information about a single engine pool.
         | 
| 74 | 
            +
                #
         | 
| 75 | 
            +
                # @param [Connection] connection Connection to console where site exists.
         | 
| 76 | 
            +
                # @param [String] name The name of the engine pool.
         | 
| 77 | 
            +
                # @param [String] silo The silo of the engine pool.
         | 
| 78 | 
            +
                # @return [EnginePool] Engine pool configuration object.
         | 
| 79 | 
            +
                #
         | 
| 80 | 
            +
                def self.load(connection, name, scope = 'silo')
         | 
| 81 | 
            +
                  xml = %(<EnginePoolDetailsRequest session-id="#{connection.session_id}">)
         | 
| 82 | 
            +
                  xml << %(<EnginePool name="#{name}" scope="#{scope}"/>)
         | 
| 83 | 
            +
                  xml << '</EnginePoolDetailsRequest>'
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  r = connection.execute(xml, '1.2')
         | 
| 86 | 
            +
                  if r.success
         | 
| 87 | 
            +
                    r.res.elements.each('EnginePoolDetailsResponse/EnginePool') do |pool|
         | 
| 88 | 
            +
                      config = EnginePool.new(pool.attributes['name'],
         | 
| 89 | 
            +
                                              pool.attributes['scope'],
         | 
| 90 | 
            +
                                              pool.attributes['id'].to_i)
         | 
| 91 | 
            +
                      r.res.elements.each('EnginePoolDetailsResponse/EnginePool/EngineSummary') do |summary|
         | 
| 92 | 
            +
                        config.engines << EngineSummary.new(summary.attributes['id'].to_i,
         | 
| 93 | 
            +
                                                            summary.attributes['name'],
         | 
| 94 | 
            +
                                                            summary.attributes['address'],
         | 
| 95 | 
            +
                                                            summary.attributes['port'].to_i,
         | 
| 96 | 
            +
                                                            summary.attributes['status'],
         | 
| 97 | 
            +
                                                            summary.attributes['scope'])
         | 
| 98 | 
            +
                      end
         | 
| 99 | 
            +
                      return config
         | 
| 100 | 
            +
                    end
         | 
| 101 | 
            +
                  end
         | 
| 102 | 
            +
                  nil
         | 
| 103 | 
            +
                end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                # Save an engine pool to a security console.
         | 
| 106 | 
            +
                #
         | 
| 107 | 
            +
                # @param [Connection] connection Connection to console where site exists.
         | 
| 108 | 
            +
                #
         | 
| 109 | 
            +
                def save(connection)
         | 
| 110 | 
            +
                  request = @id > 0 ? 'EnginePoolUpdateRequest' : 'EnginePoolCreateRequest'
         | 
| 111 | 
            +
                  xml = %(<#{request} session-id="#{connection.session_id}">)
         | 
| 112 | 
            +
                  xml << '<EnginePool'
         | 
| 113 | 
            +
                  xml << %( id="#{@id}") if @id > 0
         | 
| 114 | 
            +
                  xml << %( name="#{@name}" scope="#{@scope}">)
         | 
| 115 | 
            +
                  @engines.each do |engine|
         | 
| 116 | 
            +
                    xml << %(<Engine name="#{engine.name}" />)
         | 
| 117 | 
            +
                  end
         | 
| 118 | 
            +
                  xml << '</EnginePool>'
         | 
| 119 | 
            +
                  xml << %(</#{request}>)
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                  r = connection.execute(xml, '1.2')
         | 
| 122 | 
            +
                  if r.success
         | 
| 123 | 
            +
                    r.res.elements.each(request.gsub('Request', 'Response')) do |v|
         | 
| 124 | 
            +
                      return @id = v.attributes['id'].to_i
         | 
| 125 | 
            +
                    end
         | 
| 126 | 
            +
                  end
         | 
| 127 | 
            +
                end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                # Deletes an engine pool
         | 
| 130 | 
            +
                #
         | 
| 131 | 
            +
                # @param [Connection] connection Connection to console where site exists.
         | 
| 132 | 
            +
                #
         | 
| 133 | 
            +
                def delete(connection)
         | 
| 134 | 
            +
                  xml = %(<EnginePoolDeleteRequest session-id="#{connection.session_id}">)
         | 
| 135 | 
            +
                  xml << %(<EnginePool name="#{@name}" scope="#{@scope}" />)
         | 
| 136 | 
            +
                  xml << '</EnginePoolDeleteRequest>'
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                  r = connection.execute(xml, '1.2')
         | 
| 139 | 
            +
                  r.success
         | 
| 140 | 
            +
                end
         | 
| 141 | 
            +
              end
         | 
| 142 | 
            +
            end
         | 
    
        data/lib/nexpose/report.rb
    CHANGED
    
    | @@ -6,6 +6,24 @@ module Nexpose | |
| 6 6 | 
             
              module NexposeAPI
         | 
| 7 7 | 
             
                include XMLUtils
         | 
| 8 8 |  | 
| 9 | 
            +
                # Provide a listing of all report definitions the user can access on the
         | 
| 10 | 
            +
                # Security Console.
         | 
| 11 | 
            +
                #
         | 
| 12 | 
            +
                # @return [Array[ReportConfigSummary]] List of current report configuration.
         | 
| 13 | 
            +
                #
         | 
| 14 | 
            +
                def list_reports
         | 
| 15 | 
            +
                  r = execute(make_xml('ReportListingRequest'))
         | 
| 16 | 
            +
                  reports = []
         | 
| 17 | 
            +
                  if r.success
         | 
| 18 | 
            +
                    r.res.elements.each('//ReportConfigSummary') do |report|
         | 
| 19 | 
            +
                      reports << ReportConfigSummary.parse(report)
         | 
| 20 | 
            +
                    end
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                  reports
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                alias_method :reports, :list_reports
         | 
| 26 | 
            +
             | 
| 9 27 | 
             
                # Generate a new report using the specified report definition.
         | 
| 10 28 | 
             
                def generate_report(report_id, wait = false)
         | 
| 11 29 | 
             
                  xml = make_xml('ReportGenerateRequest', { 'report-id' => report_id })
         | 
| @@ -43,65 +61,31 @@ module Nexpose | |
| 43 61 | 
             
                  history.sort { |a, b| b.generated_on <=> a.generated_on }.first
         | 
| 44 62 | 
             
                end
         | 
| 45 63 |  | 
| 46 | 
            -
                # Delete a previously generated report definition.
         | 
| 47 | 
            -
                # Also deletes any reports generated from that configuration.
         | 
| 48 | 
            -
                def delete_report_config(report_config_id)
         | 
| 49 | 
            -
                  xml = make_xml('ReportDeleteRequest', { 'reportcfg-id' => report_config_id })
         | 
| 50 | 
            -
                  execute(xml).success
         | 
| 51 | 
            -
                end
         | 
| 52 | 
            -
             | 
| 53 64 | 
             
                # Delete a previously generated report.
         | 
| 65 | 
            +
                #
         | 
| 66 | 
            +
                # @param [Fixnum] report_id ID of individual report to delete.
         | 
| 67 | 
            +
                #
         | 
| 54 68 | 
             
                def delete_report(report_id)
         | 
| 55 69 | 
             
                  xml = make_xml('ReportDeleteRequest', { 'report-id' => report_id })
         | 
| 56 70 | 
             
                  execute(xml).success
         | 
| 57 71 | 
             
                end
         | 
| 58 72 |  | 
| 59 | 
            -
                #  | 
| 60 | 
            -
                #  | 
| 61 | 
            -
                 | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
                    end
         | 
| 68 | 
            -
                  end
         | 
| 69 | 
            -
                  templates
         | 
| 70 | 
            -
                end
         | 
| 71 | 
            -
             | 
| 72 | 
            -
                alias_method :report_templates, :report_template_listing
         | 
| 73 | 
            -
             | 
| 74 | 
            -
                # Retrieve the configuration for a report template.
         | 
| 75 | 
            -
                def get_report_template(template_id)
         | 
| 76 | 
            -
                  xml = make_xml('ReportTemplateConfigRequest', { 'template-id' => template_id })
         | 
| 77 | 
            -
                  ReportTemplate.parse(execute(xml))
         | 
| 78 | 
            -
                end
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                # Provide a listing of all report definitions the user can access on the
         | 
| 81 | 
            -
                # Security Console.
         | 
| 82 | 
            -
                def report_listing
         | 
| 83 | 
            -
                  r = execute(make_xml('ReportListingRequest'))
         | 
| 84 | 
            -
                  reports = []
         | 
| 85 | 
            -
                  if r.success
         | 
| 86 | 
            -
                    r.res.elements.each('//ReportConfigSummary') do |report|
         | 
| 87 | 
            -
                      reports << ReportConfigSummary.parse(report)
         | 
| 88 | 
            -
                    end
         | 
| 89 | 
            -
                  end
         | 
| 90 | 
            -
                  reports
         | 
| 91 | 
            -
                end
         | 
| 92 | 
            -
             | 
| 93 | 
            -
                alias_method :reports, :report_listing
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                # Retrieve the configuration for a report definition.
         | 
| 96 | 
            -
                def get_report_config(report_config_id)
         | 
| 97 | 
            -
                  xml = make_xml('ReportConfigRequest', { 'reportcfg-id' => report_config_id })
         | 
| 98 | 
            -
                  ReportConfig.parse(execute(xml))
         | 
| 73 | 
            +
                # Delete a previously generated report definition.
         | 
| 74 | 
            +
                # Also deletes any reports generated from that configuration.
         | 
| 75 | 
            +
                #
         | 
| 76 | 
            +
                # @param [Fixnum] report_config_id ID of the report configuration to remove.
         | 
| 77 | 
            +
                #
         | 
| 78 | 
            +
                def delete_report_config(report_config_id)
         | 
| 79 | 
            +
                  xml = make_xml('ReportDeleteRequest', { 'reportcfg-id' => report_config_id })
         | 
| 80 | 
            +
                  execute(xml).success
         | 
| 99 81 | 
             
                end
         | 
| 100 82 | 
             
              end
         | 
| 101 83 |  | 
| 102 84 | 
             
              # Data object for report configuration information.
         | 
| 103 85 | 
             
              # Not meant for use in creating new configurations.
         | 
| 86 | 
            +
              #
         | 
| 104 87 | 
             
              class ReportConfigSummary
         | 
| 88 | 
            +
             | 
| 105 89 | 
             
                # The report definition (config) ID.
         | 
| 106 90 | 
             
                attr_reader :config_id
         | 
| 107 91 | 
             
                # The ID of the report template.
         | 
| @@ -137,8 +121,10 @@ module Nexpose | |
| 137 121 | 
             
              end
         | 
| 138 122 |  | 
| 139 123 | 
             
              # Summary of a single report.
         | 
| 124 | 
            +
              #
         | 
| 140 125 | 
             
              class ReportSummary
         | 
| 141 | 
            -
             | 
| 126 | 
            +
             | 
| 127 | 
            +
                # The ID of the generated report.
         | 
| 142 128 | 
             
                attr_reader :id
         | 
| 143 129 | 
             
                # The report definition (configuration) ID.
         | 
| 144 130 | 
             
                attr_reader :config_id
         | 
| @@ -193,6 +179,7 @@ module Nexpose | |
| 193 179 | 
             
                attr_accessor :format
         | 
| 194 180 | 
             
                attr_accessor :owner
         | 
| 195 181 | 
             
                attr_accessor :time_zone
         | 
| 182 | 
            +
                attr_accessor :language
         | 
| 196 183 |  | 
| 197 184 | 
             
                # Array of filters associated with this report.
         | 
| 198 185 | 
             
                attr_accessor :filters
         | 
| @@ -220,16 +207,17 @@ module Nexpose | |
| 220 207 | 
             
                end
         | 
| 221 208 |  | 
| 222 209 | 
             
                def to_xml
         | 
| 223 | 
            -
                  xml = % | 
| 224 | 
            -
                  xml << % | 
| 225 | 
            -
                  xml << % | 
| 210 | 
            +
                  xml = %(<AdhocReportConfig format='#{@format}' template-id='#{@template_id}')
         | 
| 211 | 
            +
                  xml << %( owner='#{@owner}') if @owner
         | 
| 212 | 
            +
                  xml << %( timezone='#{@time_zone}') if @time_zone
         | 
| 213 | 
            +
                  xml << %( language='#{@language}') if @language
         | 
| 226 214 | 
             
                  xml << '>'
         | 
| 227 215 |  | 
| 228 216 | 
             
                  xml << '<Filters>'
         | 
| 229 217 | 
             
                  @filters.each { |filter| xml << filter.to_xml }
         | 
| 230 218 | 
             
                  xml << '</Filters>'
         | 
| 231 219 |  | 
| 232 | 
            -
                  xml << % | 
| 220 | 
            +
                  xml << %(<Baseline compareTo='#{@baseline}' />) if @baseline
         | 
| 233 221 |  | 
| 234 222 | 
             
                  xml << '</AdhocReportConfig>'
         | 
| 235 223 | 
             
                end
         | 
| @@ -244,7 +232,7 @@ module Nexpose | |
| 244 232 | 
             
                # @return Report in text format except for PDF, which returns binary data.
         | 
| 245 233 | 
             
                #
         | 
| 246 234 | 
             
                def generate(connection)
         | 
| 247 | 
            -
                  xml = % | 
| 235 | 
            +
                  xml = %(<ReportAdhocGenerateRequest session-id='#{connection.session_id}'>)
         | 
| 248 236 | 
             
                  xml << to_xml
         | 
| 249 237 | 
             
                  xml << '</ReportAdhocGenerateRequest>'
         | 
| 250 238 | 
             
                  response = connection.execute(xml)
         | 
| @@ -309,7 +297,8 @@ module Nexpose | |
| 309 297 |  | 
| 310 298 | 
             
                # Retrieve the configuration for an existing report definition.
         | 
| 311 299 | 
             
                def self.load(connection, report_config_id)
         | 
| 312 | 
            -
                  connection. | 
| 300 | 
            +
                  xml = %(<ReportConfigRequest session-id='#{connection.session_id}' reportcfg-id='#{report_config_id}'/>)
         | 
| 301 | 
            +
                  ReportConfig.parse(connection.execute(xml))
         | 
| 313 302 | 
             
                end
         | 
| 314 303 |  | 
| 315 304 | 
             
                alias_method :get, :load
         | 
| @@ -319,7 +308,7 @@ module Nexpose | |
| 319 308 | 
             
                #
         | 
| 320 309 | 
             
                # Returns the new configuration.
         | 
| 321 310 | 
             
                def self.build(connection, site_id, site_name, type, format, generate_now = false)
         | 
| 322 | 
            -
                  name = % | 
| 311 | 
            +
                  name = %(#{site_name} #{type} report in #{format})
         | 
| 323 312 | 
             
                  config = ReportConfig.new(name, type, format)
         | 
| 324 313 | 
             
                  config.frequency = Frequency.new(true, false)
         | 
| 325 314 | 
             
                  config.filters << Filter.new('site', site_id)
         | 
| @@ -329,7 +318,7 @@ module Nexpose | |
| 329 318 |  | 
| 330 319 | 
             
                # Save the configuration of this report definition.
         | 
| 331 320 | 
             
                def save(connection, generate_now = false)
         | 
| 332 | 
            -
                  xml = % | 
| 321 | 
            +
                  xml = %(<ReportSaveRequest session-id='#{connection.session_id}' generate-now='#{generate_now ? 1 : 0}'>)
         | 
| 333 322 | 
             
                  xml << to_xml
         | 
| 334 323 | 
             
                  xml << '</ReportSaveRequest>'
         | 
| 335 324 | 
             
                  response = connection.execute(xml)
         | 
| @@ -351,18 +340,22 @@ module Nexpose | |
| 351 340 | 
             
                end
         | 
| 352 341 |  | 
| 353 342 | 
             
                def to_xml
         | 
| 354 | 
            -
                  xml = % | 
| 355 | 
            -
                  xml << % | 
| 343 | 
            +
                  xml = %(<ReportConfig format='#{@format}' id='#{@id}' name='#{@name}' template-id='#{@template_id}')
         | 
| 344 | 
            +
                  xml << %( owner='#{@owner}') if @owner
         | 
| 345 | 
            +
                  xml << %( timezone='#{@time_zone}') if @time_zone
         | 
| 346 | 
            +
                  xml << %( language='#{@language}') if @language
         | 
| 347 | 
            +
                  xml << '>'
         | 
| 348 | 
            +
                  xml << %(<description>#{@description}</description>) if @description
         | 
| 356 349 |  | 
| 357 350 | 
             
                  xml << '<Filters>'
         | 
| 358 351 | 
             
                  @filters.each { |filter| xml << filter.to_xml }
         | 
| 359 352 | 
             
                  xml << '</Filters>'
         | 
| 360 353 |  | 
| 361 354 | 
             
                  xml << '<Users>'
         | 
| 362 | 
            -
                  @users.each { |user| xml << % | 
| 355 | 
            +
                  @users.each { |user| xml << %(<user id='#{user}' />) }
         | 
| 363 356 | 
             
                  xml << '</Users>'
         | 
| 364 357 |  | 
| 365 | 
            -
                  xml << % | 
| 358 | 
            +
                  xml << %(<Baseline compareTo='#{@baseline}' />) if @baseline
         | 
| 366 359 | 
             
                  xml << @frequency.to_xml if @frequency
         | 
| 367 360 | 
             
                  xml << @delivery.to_xml if @delivery
         | 
| 368 361 | 
             
                  xml << @db_export.to_xml if @db_export
         | 
| @@ -412,7 +405,9 @@ module Nexpose | |
| 412 405 | 
             
              # or raw_xml. If the vuln-status filter is not included in the configuration,
         | 
| 413 406 | 
             
              # all the vulnerability test results (including invulnerable instances) are
         | 
| 414 407 | 
             
              # exported by default in csv and raw_xml reports.
         | 
| 408 | 
            +
              #
         | 
| 415 409 | 
             
              class Filter
         | 
| 410 | 
            +
             | 
| 416 411 | 
             
                # The ID of the specific site, group, device, or scan.
         | 
| 417 412 | 
             
                # For scan, this can also be "last" for the most recently run scan.
         | 
| 418 413 | 
             
                # For vuln-status, the ID can have one of the following values:
         | 
| @@ -430,7 +425,7 @@ module Nexpose | |
| 430 425 | 
             
                end
         | 
| 431 426 |  | 
| 432 427 | 
             
                def to_xml
         | 
| 433 | 
            -
                  % | 
| 428 | 
            +
                  %(<filter id='#{@id}' type='#{@type}' />)
         | 
| 434 429 | 
             
                end
         | 
| 435 430 |  | 
| 436 431 | 
             
                def self.parse(xml)
         | 
| @@ -443,7 +438,9 @@ module Nexpose | |
| 443 438 | 
             
              end
         | 
| 444 439 |  | 
| 445 440 | 
             
              # Data object associated with when a report is generated.
         | 
| 441 | 
            +
              #
         | 
| 446 442 | 
             
              class Frequency
         | 
| 443 | 
            +
             | 
| 447 444 | 
             
                # Will the report be generated after a scan completes (true),
         | 
| 448 445 | 
             
                # or is it ad hoc/scheduled (false).
         | 
| 449 446 | 
             
                attr_accessor :after_scan
         | 
| @@ -459,7 +456,7 @@ module Nexpose | |
| 459 456 | 
             
                end
         | 
| 460 457 |  | 
| 461 458 | 
             
                def to_xml
         | 
| 462 | 
            -
                  xml = % | 
| 459 | 
            +
                  xml = %(<Generate after-scan='#{@after_scan ? 1 : 0}' schedule='#{@scheduled ? 1 : 0}'>)
         | 
| 463 460 | 
             
                  xml << @schedule.to_xml if @schedule
         | 
| 464 461 | 
             
                  xml << '</Generate>'
         | 
| 465 462 | 
             
                end
         | 
| @@ -483,7 +480,9 @@ module Nexpose | |
| 483 480 | 
             
              end
         | 
| 484 481 |  | 
| 485 482 | 
             
              # Data object for configuration of where a report is stored or delivered.
         | 
| 483 | 
            +
              #
         | 
| 486 484 | 
             
              class Delivery
         | 
| 485 | 
            +
             | 
| 487 486 | 
             
                # Whether to store report on server.
         | 
| 488 487 | 
             
                attr_accessor :store_on_server
         | 
| 489 488 | 
             
                # Directory location to store report in (for non-default storage).
         | 
| @@ -499,8 +498,8 @@ module Nexpose | |
| 499 498 |  | 
| 500 499 | 
             
                def to_xml
         | 
| 501 500 | 
             
                  xml = '<Delivery>'
         | 
| 502 | 
            -
                  xml << % | 
| 503 | 
            -
                  xml << % | 
| 501 | 
            +
                  xml << %(<Storage storeOnServer='#{@store_on_server ? 1 : 0}'>)
         | 
| 502 | 
            +
                  xml << %(<location>#{@location}</location>) if @location
         | 
| 504 503 | 
             
                  xml << '</Storage>'
         | 
| 505 504 | 
             
                  xml << @email.to_xml if @email
         | 
| 506 505 | 
             
                  xml << '</Delivery>'
         | 
| @@ -526,7 +525,9 @@ module Nexpose | |
| 526 525 | 
             
              end
         | 
| 527 526 |  | 
| 528 527 | 
             
              # Configuration structure for database exporting of reports.
         | 
| 528 | 
            +
              #
         | 
| 529 529 | 
             
              class DBExport
         | 
| 530 | 
            +
             | 
| 530 531 | 
             
                # The DB type to export to.
         | 
| 531 532 | 
             
                attr_accessor :type
         | 
| 532 533 | 
             
                # Credentials needed to export to the specified database.
         | 
| @@ -540,10 +541,10 @@ module Nexpose | |
| 540 541 | 
             
                end
         | 
| 541 542 |  | 
| 542 543 | 
             
                def to_xml
         | 
| 543 | 
            -
                  xml = % | 
| 544 | 
            +
                  xml = %(<DBExport type='#{@type}'>)
         | 
| 544 545 | 
             
                  xml << @credentials.to_xml if @credentials
         | 
| 545 546 | 
             
                  @parameters.each_pair do |name, value|
         | 
| 546 | 
            -
                    xml << % | 
| 547 | 
            +
                    xml << %(<param name='#{name}'>#{value}</param>)
         | 
| 547 548 | 
             
                  end
         | 
| 548 549 | 
             
                  xml << '</DBExport>'
         | 
| 549 550 | 
             
                end
         | 
| @@ -566,7 +567,9 @@ module Nexpose | |
| 566 567 | 
             
              # The user_id, password and realm attributes should ONLY be used
         | 
| 567 568 | 
             
              # if a security blob cannot be generated and the data is being
         | 
| 568 569 | 
             
              # transmitted/stored using external encryption (e.g., HTTPS).
         | 
| 570 | 
            +
              #
         | 
| 569 571 | 
             
              class ExportCredential
         | 
| 572 | 
            +
             | 
| 570 573 | 
             
                # Security blob for exporting to a database.
         | 
| 571 574 | 
             
                attr_accessor :credential
         | 
| 572 575 | 
             
                attr_accessor :user_id
         | 
| @@ -580,9 +583,9 @@ module Nexpose | |
| 580 583 |  | 
| 581 584 | 
             
                def to_xml
         | 
| 582 585 | 
             
                  xml = '<credentials'
         | 
| 583 | 
            -
                  xml << % | 
| 584 | 
            -
                  xml << % | 
| 585 | 
            -
                  xml << % | 
| 586 | 
            +
                  xml << %( userid='#{@user_id}') if @user_id
         | 
| 587 | 
            +
                  xml << %( password='#{@password}') if @password
         | 
| 588 | 
            +
                  xml << %( realm='#{@realm}') if @realm
         | 
| 586 589 | 
             
                  xml << '>'
         | 
| 587 590 | 
             
                  xml << @credential if @credential
         | 
| 588 591 | 
             
                  xml << '</credentials>'
         | 
| @@ -600,213 +603,4 @@ module Nexpose | |
| 600 603 | 
             
                  nil
         | 
| 601 604 | 
             
                end
         | 
| 602 605 | 
             
              end
         | 
| 603 | 
            -
             | 
| 604 | 
            -
              # Data object for report template summary information.
         | 
| 605 | 
            -
              # Not meant for use in creating new templates.
         | 
| 606 | 
            -
              class ReportTemplateSummary
         | 
| 607 | 
            -
                # The ID of the report template.
         | 
| 608 | 
            -
                attr_reader :id
         | 
| 609 | 
            -
                # The name of the report template.
         | 
| 610 | 
            -
                attr_reader :name
         | 
| 611 | 
            -
                # One of: data|document. With a data template, you can export
         | 
| 612 | 
            -
                # comma-separated value (CSV) files with vulnerability-based data.
         | 
| 613 | 
            -
                # With a document template, you can create PDF, RTF, HTML, or XML reports
         | 
| 614 | 
            -
                # with asset-based information.
         | 
| 615 | 
            -
                attr_reader :type
         | 
| 616 | 
            -
                # The visibility (scope) of the report template. One of: global|silo
         | 
| 617 | 
            -
                attr_reader :scope
         | 
| 618 | 
            -
                # Whether the report template is built-in, and therefore cannot be modified.
         | 
| 619 | 
            -
                attr_reader :built_in
         | 
| 620 | 
            -
                # Description of the report template.
         | 
| 621 | 
            -
                attr_reader :description
         | 
| 622 | 
            -
             | 
| 623 | 
            -
                def initialize(id, name, type, scope, built_in, description)
         | 
| 624 | 
            -
                  @id = id
         | 
| 625 | 
            -
                  @name = name
         | 
| 626 | 
            -
                  @type = type
         | 
| 627 | 
            -
                  @scope = scope
         | 
| 628 | 
            -
                  @built_in = built_in
         | 
| 629 | 
            -
                  @description = description
         | 
| 630 | 
            -
                end
         | 
| 631 | 
            -
             | 
| 632 | 
            -
                def self.parse(xml)
         | 
| 633 | 
            -
                  description = nil
         | 
| 634 | 
            -
                  xml.elements.each('description') { |desc| description = desc.text }
         | 
| 635 | 
            -
                  ReportTemplateSummary.new(xml.attributes['id'],
         | 
| 636 | 
            -
                                            xml.attributes['name'],
         | 
| 637 | 
            -
                                            xml.attributes['type'],
         | 
| 638 | 
            -
                                            xml.attributes['scope'],
         | 
| 639 | 
            -
                                            xml.attributes['builtin'] == '1',
         | 
| 640 | 
            -
                                            description)
         | 
| 641 | 
            -
                end
         | 
| 642 | 
            -
              end
         | 
| 643 | 
            -
             | 
| 644 | 
            -
              # Definition object for a report template.
         | 
| 645 | 
            -
              class ReportTemplate
         | 
| 646 | 
            -
                # The ID of the report template.
         | 
| 647 | 
            -
                attr_accessor :id
         | 
| 648 | 
            -
                # The name of the report template.
         | 
| 649 | 
            -
                attr_accessor :name
         | 
| 650 | 
            -
                # With a data template, you can export comma-separated value (CSV) files
         | 
| 651 | 
            -
                # with vulnerability-based data. With a document template, you can create
         | 
| 652 | 
            -
                # PDF, RTF, HTML, or XML reports with asset-based information. When you
         | 
| 653 | 
            -
                # retrieve a report template, the type will always be visible even though
         | 
| 654 | 
            -
                # type is implied. When ReportTemplate is sent as a request, and the type
         | 
| 655 | 
            -
                # attribute is not provided, the type attribute defaults to document,
         | 
| 656 | 
            -
                # allowing for backward compatibility with existing API clients.
         | 
| 657 | 
            -
                attr_accessor :type
         | 
| 658 | 
            -
                # The visibility (scope) of the report template.
         | 
| 659 | 
            -
                # One of: global|silo
         | 
| 660 | 
            -
                attr_accessor :scope
         | 
| 661 | 
            -
                # The report template is built-in, and cannot be modified.
         | 
| 662 | 
            -
                attr_accessor :built_in
         | 
| 663 | 
            -
                # Description of this report template.
         | 
| 664 | 
            -
                attr_accessor :description
         | 
| 665 | 
            -
             | 
| 666 | 
            -
                # Array of report sections.
         | 
| 667 | 
            -
                attr_accessor :sections
         | 
| 668 | 
            -
                # Map of report properties.
         | 
| 669 | 
            -
                attr_accessor :properties
         | 
| 670 | 
            -
                # Array of report attributes, in the order they will be present in a report.
         | 
| 671 | 
            -
                attr_accessor :attributes
         | 
| 672 | 
            -
                # Display asset names with IPs.
         | 
| 673 | 
            -
                attr_accessor :show_device_names
         | 
| 674 | 
            -
             | 
| 675 | 
            -
                def initialize(name, type = 'document', id = -1, scope = 'silo', built_in = false)
         | 
| 676 | 
            -
                  @name = name
         | 
| 677 | 
            -
                  @type = type
         | 
| 678 | 
            -
                  @id = id
         | 
| 679 | 
            -
                  @scope = scope
         | 
| 680 | 
            -
                  @built_in = built_in
         | 
| 681 | 
            -
             | 
| 682 | 
            -
                  @sections = []
         | 
| 683 | 
            -
                  @properties = {}
         | 
| 684 | 
            -
                  @attributes = []
         | 
| 685 | 
            -
                  @show_device_names = false
         | 
| 686 | 
            -
                end
         | 
| 687 | 
            -
             | 
| 688 | 
            -
                # Save the configuration for a report template.
         | 
| 689 | 
            -
                def save(connection)
         | 
| 690 | 
            -
                  xml = %Q{<ReportTemplateSaveRequest session-id='#{connection.session_id}' scope='#{@scope}'>}
         | 
| 691 | 
            -
                  xml << to_xml
         | 
| 692 | 
            -
                  xml << '</ReportTemplateSaveRequest>'
         | 
| 693 | 
            -
                  response = connection.execute(xml)
         | 
| 694 | 
            -
                  if response.success
         | 
| 695 | 
            -
                    @id = response.attributes['template-id']
         | 
| 696 | 
            -
                  end
         | 
| 697 | 
            -
                end
         | 
| 698 | 
            -
             | 
| 699 | 
            -
                def delete(connection)
         | 
| 700 | 
            -
                  xml = %Q{<ReportTemplateDeleteRequest session-id='#{connection.session_id}' template-id='#{@id}'>}
         | 
| 701 | 
            -
                  xml << '</ReportTemplateDeleteRequest>'
         | 
| 702 | 
            -
                  response = connection.execute(xml)
         | 
| 703 | 
            -
                  if response.success
         | 
| 704 | 
            -
                    @id = response.attributes['template-id']
         | 
| 705 | 
            -
                  end
         | 
| 706 | 
            -
                end
         | 
| 707 | 
            -
             | 
| 708 | 
            -
                # Retrieve the configuration for a report template.
         | 
| 709 | 
            -
                def self.load(connection, template_id)
         | 
| 710 | 
            -
                  connection.get_report_template(template_id)
         | 
| 711 | 
            -
                end
         | 
| 712 | 
            -
             | 
| 713 | 
            -
                alias_method :get, :load
         | 
| 714 | 
            -
             | 
| 715 | 
            -
                include Sanitize
         | 
| 716 | 
            -
             | 
| 717 | 
            -
                def to_xml
         | 
| 718 | 
            -
                  xml = %Q{<ReportTemplate id='#{@id}' name='#{@name}' type='#{@type}'}
         | 
| 719 | 
            -
                  xml << %Q{ scope='#{@scope}'} if @scope
         | 
| 720 | 
            -
                  xml << %Q{ builtin='#{@built_in}'} if @built_in
         | 
| 721 | 
            -
                  xml << '>'
         | 
| 722 | 
            -
                  xml << %Q{<description>#{@description}</description>} if @description
         | 
| 723 | 
            -
             | 
| 724 | 
            -
                  unless @attributes.empty?
         | 
| 725 | 
            -
                    xml << '<ReportAttributes>'
         | 
| 726 | 
            -
                    @attributes.each do |attr|
         | 
| 727 | 
            -
                      xml << %Q(<ReportAttribute name='#{attr}'/>)
         | 
| 728 | 
            -
                    end
         | 
| 729 | 
            -
                    xml << '</ReportAttributes>'
         | 
| 730 | 
            -
                  end
         | 
| 731 | 
            -
             | 
| 732 | 
            -
                  unless @sections.empty?
         | 
| 733 | 
            -
                    xml << '<ReportSections>'
         | 
| 734 | 
            -
                    properties.each_pair do |name, value|
         | 
| 735 | 
            -
                      xml << %Q{<property name='#{name}'>#{replace_entities(value)}</property>}
         | 
| 736 | 
            -
                    end
         | 
| 737 | 
            -
                    @sections.each { |section| xml << section.to_xml }
         | 
| 738 | 
            -
                    xml << '</ReportSections>'
         | 
| 739 | 
            -
                  end
         | 
| 740 | 
            -
             | 
| 741 | 
            -
                  xml << %Q{<Settings><showDeviceNames enabled='#{@show_device_names ? 1 : 0}' /></Settings>}
         | 
| 742 | 
            -
                  xml << '</ReportTemplate>'
         | 
| 743 | 
            -
                end
         | 
| 744 | 
            -
             | 
| 745 | 
            -
                def self.parse(xml)
         | 
| 746 | 
            -
                  xml.res.elements.each('//ReportTemplate') do |tmp|
         | 
| 747 | 
            -
                    template = ReportTemplate.new(tmp.attributes['name'],
         | 
| 748 | 
            -
                                                  tmp.attributes['type'],
         | 
| 749 | 
            -
                                                  tmp.attributes['id'],
         | 
| 750 | 
            -
                                                  tmp.attributes['scope'] || 'silo',
         | 
| 751 | 
            -
                                                  tmp.attributes['builtin'])
         | 
| 752 | 
            -
                    tmp.elements.each('//description') do |desc|
         | 
| 753 | 
            -
                      template.description = desc.text
         | 
| 754 | 
            -
                    end
         | 
| 755 | 
            -
             | 
| 756 | 
            -
                    tmp.elements.each('//ReportAttributes/ReportAttribute') do |attr|
         | 
| 757 | 
            -
                      template.attributes << attr.attributes['name']
         | 
| 758 | 
            -
                    end
         | 
| 759 | 
            -
             | 
| 760 | 
            -
                    tmp.elements.each('//ReportSections/property') do |property|
         | 
| 761 | 
            -
                      template.properties[property.attributes['name']] = property.text
         | 
| 762 | 
            -
                    end
         | 
| 763 | 
            -
             | 
| 764 | 
            -
                    tmp.elements.each('//ReportSection') do |section|
         | 
| 765 | 
            -
                      template.sections << Section.parse(section)
         | 
| 766 | 
            -
                    end
         | 
| 767 | 
            -
             | 
| 768 | 
            -
                    tmp.elements.each('//showDeviceNames') do |show|
         | 
| 769 | 
            -
                      template.show_device_names = show.attributes['enabled'] == '1'
         | 
| 770 | 
            -
                    end
         | 
| 771 | 
            -
             | 
| 772 | 
            -
                    return template
         | 
| 773 | 
            -
                  end
         | 
| 774 | 
            -
                  nil
         | 
| 775 | 
            -
                end
         | 
| 776 | 
            -
              end
         | 
| 777 | 
            -
             | 
| 778 | 
            -
              # Section specific content to include in a report template.
         | 
| 779 | 
            -
              class Section
         | 
| 780 | 
            -
                # Name of the report section.
         | 
| 781 | 
            -
                attr_accessor :name
         | 
| 782 | 
            -
                # Map of properties specific to the report section.
         | 
| 783 | 
            -
                attr_accessor :properties
         | 
| 784 | 
            -
             | 
| 785 | 
            -
                def initialize(name)
         | 
| 786 | 
            -
                  @name = name
         | 
| 787 | 
            -
                  @properties = {}
         | 
| 788 | 
            -
                end
         | 
| 789 | 
            -
             | 
| 790 | 
            -
                include Sanitize
         | 
| 791 | 
            -
             | 
| 792 | 
            -
                def to_xml
         | 
| 793 | 
            -
                  xml = %Q{<ReportSection name='#{@name}'>}
         | 
| 794 | 
            -
                  properties.each_pair do |name, value|
         | 
| 795 | 
            -
                    xml << %Q{<property name='#{name}'>#{replace_entities(value)}</property>}
         | 
| 796 | 
            -
                  end
         | 
| 797 | 
            -
                  xml << '</ReportSection>'
         | 
| 798 | 
            -
                end
         | 
| 799 | 
            -
             | 
| 800 | 
            -
                def self.parse(xml)
         | 
| 801 | 
            -
                  name = xml.attributes['name']
         | 
| 802 | 
            -
                  xml.elements.each("//ReportSection[@name='#{name}']") do |elem|
         | 
| 803 | 
            -
                    section = Section.new(name)
         | 
| 804 | 
            -
                    elem.elements.each("//ReportSection[@name='#{name}']/property") do |property|
         | 
| 805 | 
            -
                      section.properties[property.attributes['name']] = property.text
         | 
| 806 | 
            -
                    end
         | 
| 807 | 
            -
                    return section
         | 
| 808 | 
            -
                  end
         | 
| 809 | 
            -
                  nil
         | 
| 810 | 
            -
                end
         | 
| 811 | 
            -
              end
         | 
| 812 606 | 
             
            end
         |