\FF\D8\FF\E0\00JFIF\00\00\00d\00d\00\00\FF\FE\00\border bs:0 bc:#000000 ps:0 pc:#ffffff es:0 ec:#000000 ck:feee6c715d26fd9f38b0ca4278c05026\FF\DB\00C\00P7<F<2PFAFZUP_xxnnx\F5\AF\B9\91\C8\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\DB\00CUZZxix‚\EB\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\C0\00\00b\00d\00\FF\C4\00\00\00\00\00\00\00\00\00\00\00\00\00\00\FF\C4\00\00\00\00\00\00\00\00\00\00\001A!Q\FF\C4\00\00\00\00\00\00\00\00\00\00\00\00\00\FF\C4\00\00\00\00\00\00\00\00\00\00!1AQ\FF\DA\00\00\00?\00\F6\00\00\00\00\00\00\00\00\00\00\A0\00\00\C5\CF\F8\E7Ó\FCjD~\B9^\AD\%\B3]\D8cs-\BBs,-\A0\00"\80\00%\B83rÏ^K~F\A4ea\00E\00\C6\EE=u\B1\9B\D1\00@\00r\BE8\F9:\FE5#.M\00\E7\CB\C9q\CBq\D6\F2\BE\B7\C7>\C9n5×\D6?\BDê\9Ds\EBp\9F[`8m\B7)o\B5\E8\E6I\99\FE3]]A2\BA\8Cw\D6E\93\\DEv\C8\009\F2\F1NI?uc\\F5\EA\96k\xN<~buv\EA\C8\D7	\8B\84\CEcxI\BBg\AE\9E=\D6+n\EC\80\C8A\8C\AE\EB\CF\D5\DA\E9"2\A4\B9j5\EB\F3W\B63\96\B30Yu\DA\FC8\ED\DF\E7Ms\FB\F1\8E\B3\FA\EA\E8\E6(\883zs\F2_\8DFk\8Bh
\00\8C\DCw\D3R\B5+6X\BA\B2\C4j\AB0\B4\FCMw\C2I\8E\9B\E3\A9~9u\FA\D3l\80\C8%p\EE\FDn2€
\00$\FEj\C4e\A9\DB\~\95\A7\A5\80EK\BB\8DDsP\00@@AD'k\CF\E8\DB\D2(\80\9AK\D3\85\D6lb\F2\BA\8C*\80\00)\95
59\A3R:\F3\CE"\B6\80\88\00\00i1u4ê\E9\F2á\A6\A2\FACM\93WMb*\E0*\00\00\00\00\00(\A8\80\00\00\80\00\00\00\00\00\00\00\00\00\FF\D9<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>C///</title>
</head>
require "inspec/resources/command"

module Inspec
  module Utils
    module PasswdParser
      # Parse /etc/passwd files.
      #
      # @param [String] content the raw content of /etc/passwd
      # @return [Array] Collection of passwd entries
      def parse_passwd(content)
        content.to_s.split("\n").map do |line|
          next if line[0] == "#"

          parse_passwd_line(line)
        end.compact
      end

      # Parse a line of /etc/passwd
      #
      # @param [String] line a line of /etc/passwd
      # @return [Hash] Map of entries in this line
      def parse_passwd_line(line)
        x = line.split(":")
        {
          # rubocop:disable Layout/AlignHash
          "user"     => x[0],
          "password" => x[1],
          "uid"      => x[2],
          "gid"      => x[3],
          "desc"     => x[4],
          "home"     => x[5],
          "shell"    => x[6],
        }
      end
    end

    module CommentParser
      # Parse a line with a command. For example: `a = b   # comment`.
      # Retrieves the actual content.
      #
      # @param [String] raw the content lines you want to be parsed
      # @param [Hash] opts optional configuration
      # @return [Array] contains the actual line and the position of the line end
      def parse_comment_line(raw, opts)
        idx_nl = raw.index("\n")
        idx_comment = raw.index(opts[:comment_char])
        idx_nl = raw.length if idx_nl.nil?
        idx_comment = idx_nl + 1 if idx_comment.nil?
        line = ""

        # is a comment inside this line
        if idx_comment < idx_nl && idx_comment != 0
          line = raw[0..(idx_comment - 1)]
          # in case we don't allow comments at the end
          # of an assignment/statement, ignore it and fall
          # back to treating this as a regular line
          if opts[:standalone_comments] && !is_empty_line(line)
            line = raw[0..(idx_nl - 1)]
          end
        # if there is no comment in this line
        elsif idx_comment > idx_nl && idx_nl != 0
          line = raw[0..(idx_nl - 1)]
        end
        [line, idx_nl]
      end
    end

    module LinuxMountParser
      # this parses the output of mount command (only tested on linux)
      # this method expects only one line of the mount output
      def parse_mount_options(mount_line, compatibility = false)
        if includes_whitespaces?(mount_line)
          # Device-/Sharenames and Mountpoints including whitespaces require special treatment:
          # We use the keyword ' type ' to split up and rebuild the desired array of fields
          type_split = mount_line.split(" type ")
          fs_path = type_split[0]
          other_opts = type_split[1]
          fs, path = fs_path.match(%r{^(.+?)\son\s(/.+?)$}).captures
          mount = [fs, "on", path, "type"]
          mount.concat(other_opts.scan(/\S+/))
        else
          # ... otherwise we just split the fields by whitespaces
          mount = mount_line.scan(/\S+/)
        end

        # parse device and type
        mount_options    = { device: mount[0], type: mount[4] }

        if compatibility == false
          # parse options as array
          mount_options[:options] = mount[5].gsub(/\(|\)/, "").split(",")
        else
          Inspec.deprecate(:mount_parser_serverspec_compat, "Parsing mount options in this fashion is deprecated")
          mount_options[:options] = {}
          mount[5].gsub(/\(|\)/, "").split(",").each do |option|
            name, val = option.split("=")
            if val.nil?
              val = true
            elsif val =~ /^\d+$/
              # parse numbers
              val = val.to_i
            end
            mount_options[:options][name.to_sym] = val
          end
        end

        mount_options
      end

      # Device-/Sharename or Mountpoint includes whitespaces?
      def includes_whitespaces?(mount_line)
        ws = mount_line.match(/^(.+)\son\s(.+)\stype\s.*$/)
        ws.captures[0].include?(" ") || ws.captures[1].include?(" ")
      end
    end

    module BsdMountParser
      # this parses the output of mount command (only tested on freebsd)
      # this method expects only one line of the mount output
      def parse_mount_options(mount_line, _compatibility = false)
        return {} if mount_line.nil? || mount_line.empty?

        mount = mount_line.chomp.split(" ", 4)
        options = mount[3].tr("()", "").split(", ")

        # parse device and type
        { device: mount[0], type: options.shift, options: options }
      end
    end

    module SolarisNetstatParser
      # takes this as a input and parses the values
      # UDP: IPv4
      #    Local Address        Remote Address      State
      # -------------------- -------------------- ----------
      #       *.*                                 Unbound
      def parse_netstat(content) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
        return [] if content.nil? || content.empty?

        protocol = nil
        column_widths = nil
        ports = []
        cache_name_line = nil

        content.each_line do |line|
          # find header, its delimiter
          if line =~ /TCP:|UDP:|SCTP:/
            # get protocol
            protocol = line.split(":")[0].chomp.strip.downcase

            # determine version tcp, tcp6, udp, udp6
            proto_version = line.split(":")[1].chomp.strip
            protocol += "6" if proto_version == "IPv6"

            # reset names cache
            column_widths = nil
            cache_name_line = nil
            names = nil
          # calulate width of a column based on the horizontal line
          elsif line =~ /^[- ]+$/
            column_widths = columns(line)
          # parse header values from line
          elsif column_widths.nil? && !line.nil?
            # we do not know the width at this point of time, therefore we need to cache
            cache_name_line = line
          # content line
          elsif !column_widths.nil? && !line.nil? && !line.chomp.empty?
            # default row
            port = split_columns(column_widths, line).to_a.map { |v| v.chomp.strip }

            # parse the header names
            # TODO: names should be optional
            names = split_columns(column_widths, cache_name_line).to_a.map { |v| v.chomp.strip.downcase.tr(" ", "-").gsub(/[^\w-]/, "_") }
            info = {
              "protocol" => protocol.downcase,
            }

            # generate hash for each line and use the names as keys
            names.each_index do |i|
              info[names[i]] = port[i] if i != 0
            end

            ports.push(info)
          end
        end
        ports
      end

      private

      # takes a line like "-------------------- -------------------- ----------"
      # as input and calculates the length of each column
      def columns(line)
        # find all columns
        m = line.scan(/-+/)
        # calculate the length each column
        m.map { |x| x.length } # rubocop:disable Style/SymbolProc
      end

      # takes a line and the width of the columns to extract the values
      def split_columns(columns, line)
        # generate regex based on columns
        sep = '\\s'
        length = columns.length
        arr = columns.map.with_index do |x, i|
          reg = "(.{#{x}})#{sep}" # add seperator between columns
          reg = "(.{,#{x}})#{sep}" if i == length - 2 # make the pre-last one optional
          reg = "(.{,#{x}})" if i == length - 1 # use , to say max value
          reg
        end
        # extracts the columns
        line.match(Regexp.new(arr.join))
      end
    end

    # This parser for xinetd (extended Internet daemon) configuration files
    module XinetdParser
      def xinetd_include_dir(dir)
        return [] if dir.nil?

        unless inspec.file(dir).directory?
          raise Inspec::Exceptions::ResourceSkipped, "Can't find folder: #{dir}"
        end

        files = inspec.command("find #{dir} -type f").stdout.split("\n")
        files.map { |file| parse_xinetd(read_content