<commit_before>require 'nmap/host'
require 'nmap/scanner'
require 'nmap/scan'

require 'nokogiri'
require 'enumerator'

module Nmap
  class XML

    include Enumerable

    # Path of the Nmap XML scan file
    attr_reader :path

    #
    # Creates a new XML object.
    #
    # @param [String] path
    #   The path to the Nmap XML scan file.
    #
    # @yield [xml]
    #   If a block is given, it will be passed the new XML object.
    #
    # @yieldparam [XML] xml
    #   The newly created XML object.
    #
    def initialize(path,&block)
      @path = File.expand_path(path)
      @doc = Nokogiri::XML(File.new(@path))

      block.call(self) if block
    end

    #
    # Parses the scanner information.
    #
    # @return [Scanner]
    #   The scanner that was used and generated the scan file.
    #
    def scanner
      @scanner ||= Scanner.new(
        @doc.root['scanner'],
        @doc.root['version'],
        @doc.root['args']
      )
    end

    #
    # Parses the XML scan file version.
    #
    # @return [String]
    #   The version of the XML scan file.
    #
    def version
      @version ||= @doc.root['xmloutputversion']
    end

    #
    # Parses the scan information.
    #
    # @return [Array<Scan>]
    #   The scan information.
    #
    def scan_info
      @doc.xpath("/nmaprun/scaninfo").map do |scaninfo|
        Scan.new(
          scaninfo['type'].to_sym,
          scaninfo['protocol'].to_sym,
          scaninfo['services'].split(',').map { |ports|
            if ports.include?('-')
              Range.new(*(ports.split('-',2)))
            else
              ports.to_i
            end
          }
        )
      end
    end

    #
    # Parses the verbose level.
    #
    # @return [Integer]
    #   The verbose level.
    #
    def verbose
      @verbose ||= @doc.at("verbose/@level").inner_text.to_i
    end

    #
    # Parses the debugging level.
    #
    # @return [Integer]
    #   The debugging level.
    #
    def debugging
      @debugging ||= @doc.at("debugging/@level").inner_text.to_i
    end

    #
    # Parses the hosts in the scan.
    #
    # @yield [host]
    #   Each host will be passed to a given block.
    #
    # @yieldparam [Host] host
    #   A host in the scan.
    #
    # @return [XML]
    #   The XML object.
    #
    def each_host(&block)
      @doc.xpath("/nmaprun/host").each do |host|
        block.call(Host.new(host)) if block
      end

      return self
    end

    #
    # Parses the hosts in the scan.
    #
    # @return [Array<Host>]
    #   The hosts in the scan.
    #
    def hosts
      Enumerator.new(self,:each_host).to_a
    end

    #
    # Parses the hosts that were found to be up during the scan.
    #
    # @yield [host]
    #   Each host will be passed to a given block.
    #
    # @yieldparam [Host] host
    #   A host in the scan.
    #
    # @return [XML]
    #   The XML parser.
    #
    def each_up_host(&block)
      @doc.xpath("/nmaprun/host[status[@state='up']]").each do |host|
        Host.new(host,&block)<commit_msg>Use single-quotes where possible.<commit_after>require 'nmap/host'
require 'nmap/scanner'
require 'nmap/scan'

require 'nokogiri'
require 'enumerator'

module Nmap
  class XML

    include Enumerable

    # Path of the Nmap XML scan file
    attr_reader :path

    #
    # Creates a new XML object.
    #
    # @param [String] path
    #   The path to the Nmap XML scan file.
    #
    # @yield [xml]
    #   If a block is given, it will be passed the new XML object.
    #
    # @yieldparam [XML] xml
    #   The newly created XML object.
    #
    def initialize(path,&block)
      @path = File.expand_path(path)
      @doc = Nokogiri::XML(File.new(@path))

      block.call(self) if block
    end

    #
    # Parses the scanner information.
    #
    # @return [Scanner]
    #   The scanner that was used and generated the scan file.
    #
    def scanner
      @scanner ||= Scanner.new(
        @doc.root['scanner'],
        @doc.root['version'],
        @doc.root['args']
      )
    end

    #
    # Parses the XML scan file version.
    #
    # @return [String]
    #   The version of the XML scan file.
    #
    def version
      @version ||= @doc.root['xmloutputversion']
    end

    #
    # Parses the scan information.
    #
    # @return [Array<Scan>]
    #   The scan information.
    #
    def scan_info
      @doc.xpath('/nmaprun/scaninfo').map do |scaninfo|
        Scan.new(
          scaninfo['type'].to_sym,
          scaninfo['protocol'].to_sym,
          scaninfo['services'].split(',').map { |ports|
            if ports.include?('-')
              Range.new(*(ports.split('-',2)))
            else
              ports.to_i
            end
          }
        )
      end
    end

    #
    # Parses the verbose level.
    #
    # @return [Integer]
    #   The verbose level.
    #
    def verbose
      @verbose ||= @doc.at('verbose/@level').inner_text.to_i
    end

    #
    # Parses the debugging level.
    #
    # @return [Integer]
    #   The debugging level.
    #
    def debugging
      @debugging ||= @doc.at('debugging/@level').inner_text.to_i
    end

    #
    # Parses the hosts in the scan.
    #
    # @yield [host]
    #   Each host will be passed to a given block.
    #
    # @yieldparam [Host] host
    #   A host in the scan.
    #
    # @return [XML]
    #   The XML object.
    #
    def each_host(&block)
      @doc.xpath('/nmaprun/host').each do |host|
        block.call(Host.new(host)) if block
      end

      return self
    end

    #
    # Parses the hosts in the scan.
    #
    # @return [Array<Host>]
    #   The hosts in the scan.
    #
    def hosts
      Enumerator.new(self,:each_host).to_a
    end

    #
    # Parses the hosts that were found to be up during the scan.
    #
    # @yield [host]
    #   Each host will be passed to a given block.
    #
    # @yieldparam [Host] host
    #   A host in the scan.
    #
    # @return [XML]
    #   The XML parser.
    #
    def each_up_host(&block)
      @doc.xpath("/nmaprun/host[status[@state='up']]").each do |host|
        Host.new(host,&block)
{'fraction_non_alphanumeric': 0.1202884300229433, 'fraction_numerical': 0.00032776138970829236, 'mean_word_length': 1.78675799086758, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1149396', 'n_tokens_mistral': 2085, 'n_tokens_neox': 2015, 'n_words': 550}