require "genZPK/version" require 'genZPK/templates' require 'tempfile' require 'nokogiri' require 'highline/import' # Defines a not_nil? method for all objects # @return [Boolean] the truth value associated with the nil state class Object def not_nil? !nil? end end module GenZPK # Returns the path to the zdpack executable if it can find it, or nil otherwise. # @return [String] The path to zdpack or nil if unable to find it def getZdpack if File.exists? '/usr/local/zend/bin/zdpack' '/usr/local/zend/bin/zdpack' else nil end end # Returns the path to the given executable if it can find it, or nil otherwise. # @return [String] The path to the executable or nil if unable to find it def executablePath (executable=String.new) # Assume the string is a path if it has a '/' in it if executable.include? '/' if File.exists? executable executable else nil end else # Assume the executable is in the PATH if a full path is not passed whichOut = `which #{executable}`.chomp! # Check to see if the output matches the error signifying that a path wasn't found. if whichOut =~ /\/usr\/bin\/which: no (.*) in \(.*\)/ nil else # It found it! Woo hoo! if File.exists? whichOut whichOut else nil end end end end # Get the path to the system text editor specified in the EDITOR env. variable. # If not defined, default to nano and then vi. # @return [String] The path to the executable def getEditor # Check if EDITOR is not defined if ENV['EDITOR'].nil? # It's not start nano and return the path to it. # If you can't find it, try vi. ['nano', 'vi'].each do |x| editor = executablePath x if not editor.nil? return editor end end # Couldn't find vi or nano. Raise an exception for the user to deal with. raise "Valid text editor could not be found. Please specify one in the EDITOR environment variable and/or check your PATH." # It is, so lets use it. else # Get the path to the specified editor editor = executablePath ENV['EDITOR'] # If the path was found, return it. if not editor.nil? editor else # It wasn't found so cycle through nano and vi like above ['nano', 'vi'].each do |x| editor = executablePath x if not editor.nil? return editor end end # Still couldn't find an editor. Raise an exception. raise "Valid text editor could not be found. Please specify one in the EDITOR environment variable and/or check your PATH." end end end def yesno(prompt = 'Continue?', default = true) a = '' s = default ? '[Y/n]' : '[y/N]' d = default ? 'y' : 'n' until %w[y n].include? a a = ask("#{prompt} #{s} ") { |q| q.limit = 1; q.case = :downcase } a = d if a.length == 0 end a == 'y' end # Requires that some condition be true or otherwise display the given message and exit. # @param [Boolean] condition the truth value of the condition # @param [String] the message to display on failure of the condition # @example Require a condition # requireCondition File.exists?("foo.bar"), "The file \"foo.bar\" doesn't exist. Exiting.... def requireCondition(condition, message) if not condition puts message exit -1 end end # Configures genZPK checks, definitions, and subdomain checks bia a user config file. # If the necessary files and paths do not exist, doConfigure will create them. # If the config files do exist, then a their contents will be loaded to a temporary file # for the user to edit. All configurations will be schema checked and the user must correct any # issues for the changes to be saved. def doConfigure # Check if the .genZPK folder exists in the user's home directory and create it if it doesn't. if not File.exists?(File.expand_path '~/.genZPK') FileUtils.mkpath(File.expand_path '~/.genZPK') end # Check if the .genZPK/checks.xml file exists and create it if it doesn't. if not File.exists?(File.expand_path '~/.genZPK/checks.xml') File.new(File.expand_path('~/.genZPK/checks.xml'), 'w') end # Open the checks file for reading checksFile = File.open(File.expand_path('~/.genZPK/checks.xml'), 'r') # Open a new temporary file. By default, it is writable. tmpChecksFile = Tempfile.new 'checks' # Read the contents of the existing check file and write them to the temporary file. while buff = checksFile.read(4096) tmpChecksFile.write(buff) end # Rewind the temporary file to the begining and close the existing file. tmpChecksFile.rewind checksFile.close # Get the system editor and allow the user to modify the temporary checksa file. editor = getEditor system("#{editor} #{tmpChecksFile.path}") # This block rescues the method in case the user enters bad XML begin # Read in the file and rewind it. content = tmpChecksFile.read tmpChecksFile.rewind # Parse the content with Nokogiri. A Nokogiri::XML::SyntaxError exception is raised in the event # of invalid XML syntax. doc = Nokogiri::XML(content) { |config| config.options = Nokogiri::XML::ParseOptions::STRICT } rescue Nokogiri::XML::SyntaxError => e # If the user wants to try to correct the file if yesno("Invalid XML entered. Would you like to reopen the file?") # Loop until they fix it loop do # Allow them to edit the file system("#{editor} #{tmpChecksFile.path}") begin # read in the content of the file and rewind content = tmpChecksFile.read tmpChecksFile.rewind # Check the xml syntax doc = Nokogiri::XML(content) { |config| config.options = Nokogiri::XML::ParseOptions::STRICT } # If it got here, the syntax was good and exit the oop break rescue # If the user doesn't want to try again, exit without saving the changes if not yesno("Invalid XML entered. Would you like to reopen the file?") exit -1 end end end else # The user didn't want to fix the file. Exit. exit -1 end end # Reopen the checks config file for writing checksFile = File.open(File.expand_path('~/.genZPK/checks.xml'), 'w+') # write the contents of the temporary file to the checks file while buff = tmpChecksFile.read(4096) checksFile.write(buff) end # Close all files and delete the temporary file. checksFile.close tmpChecksFile.close tmpChecksFile.unlink end end