module SELinux
  # Represents a SELinux type of file, `.te` type. This class is able to parse
  # and obtain module name and version on the given file.
  class File
    attr_accessor :version, :module_name, :content

    # Class constructor. Saves the file conents on a instance variable.
    #   +content+  File.open results from a `.te` file;
    def initialize(content = nil)
      raise 'No SELinux content informed!' if content.nil? || content.empty?

      @content = content
      @version = nil
      @module_name = nil

      parse
    end

    # Reads `.te` file contents line-by-line, keeping a counter to track line
    # numbers and only the first 20% of the file will be considered, using
    # SELinux conventions.
    def parse
      # reading about twenty percente of the file lenght
      read_line_limit = ((@content.length * 2) / 10).ceil + 1

      line_number = 1
      @content.each_line do |line|
        break if line_number >= read_line_limit
        line.chomp

        # extracting version and module name
        if (match = line.match(/^module\s+(\w+)\s+([\d\.\-]+);/))
          @module_name, @version = match.captures
        end

        break if @version && @module_name
        line_number += 1
      end
    end
  end
end

module SELinux
  # Represents a SELinux type of file, `.te` type. This class is able to parse
  # and obtain module name and version on the given file.
  class File
    attr_accessor :version, :module_name, :content

    # Class constructor. Saves the file conents on a instance variable.
    #   +content+  File.open results from a `.te` file;
    def initialize(content = nil)
      raise 'No SELinux content informed!' if content.nil? || content.empty?

      @content = content
      @version = nil
      @module_name = nil

      parse
    end

    # Reads `.te` file contents line-by-line, keeping a counter to track line
    # numbers and only the first 20% of the file will be considered, using
    # SELinux conventions.
    def parse
      # reading about twenty percente of the file lenght
      read_line_limit = ((@content.length * 2) / 10).ceil + 1

      line_number = 1
      @content.each_line do |line|
        break if line_number >= read_line_limit
        line.chomp

        # extracting version and module name
        if (match = line.match(/^module\s+([\w_-]+)\s+([\d\.\-]+);/))
          @module_name, @version = match.captures
        end

        break if @version && @module_name
        line_number += 1
      end
    end
  end
end

Allow "-" and "_" for module names
Allow "-" and "_" for module names

Without this change, it will force the module to be installed on every run which
slows client runs considerably if you have multiple modules you add.

This patch is the same as noted in this PR [1].

[1] https://github.com/chef-cookbooks/selinux/pull/61

Signed-off-by: Lance Albertson <3161cdc7bf197e4c3a35b9cbe358c79910f27e90@osuosl.org>
