#!/usr/bin/ruby=begin 1) Configure the Conf module Details: General::WZD_ROOT - Where is your wzdftpd server installed. For Linux users: If wzdftpd binary is located in /sbin then set this to "" Approve::TAG_FORMAT - Always use $who to denote "the approver"=endmodule Conf class General WZD_ROOT = "/opt/wzdftpd" end class Approve TAG_FORMAT = "[Approved.by.$who]" endend=begin 2) chmod +x this file and put it in wzdftpd's bin dir 3) add in wzd.cfg: under [events]: approvescript = MKDIR /opt/wzdftpd/bin/approve.rb check under [custom_commands]: site_approve = /opt/wzdftpd/bin/approve.rb add \"%username\" site_delapproved = /opt/wzdftpd/bin/approve.rb del site_listapproved = /opt/wzdftpd/bin/approve.rb list=endclass Approve def initialize @approvelog = Logfiles::Approvelog.new("g-approve.log") if ARGV[0] == "add" then new_approve elsif ARGV[0] == "del" then delete_entry elsif ARGV[0] == "list" then list_approved elsif ARGV[0] == "check" then check_upload end end def new_approve what = "\"#{ARGV[2..-1].join("\s")}\"" who = ARGV[1] if !what.include?("\s") then @approvelog.append(what, who) else puts "200 ERROR » Please do not use spaces in your approve statement" end end def delete_entry what = "\"#{ARGV[1..-1].join("\s")}\"" @approvelog.remove_line(what) end def list_approved @approvelog.list end def check_upload newdir = ARGV[1].split(/\/|\\/).last # assuming path from wzd dont end with \ or / approvelist = @approvelog.get_approved approvelist.each { |line| approved_dir = line.split.first who = line.split.last if approved_dir == newdir then release = Dirs::Release.new(ARGV[1]) release.tag_approved(who) @approvelog.remove_line(approved_dir) break end } endendmodule Logfiles class Logfile def initialize(name) @filename = name @abs_name = abs_path(name).to_s + name.to_s if !(File.exist?(@abs_name)) then begin new_file = File.new(@abs_name, File::CREAT) new_file.chmod 0666 puts "200 CREATED » #{name}" append_errorlog("Created #{name}") rescue Errno::EACCES errstr = "Insufficient rights, cannot create \"#{@filename}\"" puts "200 ERROR » #{errstr}" append_errorlog(errstr) Process.exit rescue Errno::ENOENT errstr = "The directory \"#{Conf::General::WZD_ROOT}\" does not exist" puts "200 ERROR » #{errstr}" append_errorlog(errstr) Process.exit end end end def list file = open_file("r") file.each { |line| puts "200 #{line}" } file.close end def abs_name return @abs_name end def filename return @filename end def append(event, line) if !line.match(/^".*"$/).nil? then file = open_file("a") event.upcase! # ensure allcaps time = Time.now.strftime("%b %d %H:%M:%S") file.puts("#{time} #{event} #{line}") file.close else errstr = "Missing double quotes. Caller must assure messages are correctly formated for: #{@filename}" puts "200 ERROR » #{errstr}" append_errorlog(errstr) end end ## override this whenever possible to make it more specific/safe ## cant seem to find a way to force implemenation like abstract in java def remove_line(what) file = open_file("r+") output = Array.new regstring = "(.*" + what + ".*)" reg = Regexp.new(regstring) removed_something = false file.each { |line| if reg.match(line).nil? then output << line else puts "200 REMOVED » \"#{$1}\" from \"#{@filename}\"" removed_something = true end } if !removed_something then puts "200 ERROR » \"#{what}\" was not found in #{@filename}" end file.pos = 0 file.print output file.truncate(file.pos) file.close end private def append_errorlog(line) errorlog = Errorlog.new("g-error.log") errorlog.append(line) end def open_file(mode) begin file = File.open(@abs_name, mode) return file rescue Errno::EACCES errstr = "Insufficient rights, cannot open \"#{@filename}\"" puts "200 ERROR » #{errstr}" append_errorlog(errstr) Process.exit rescue Errno::ENOENT errstr = "Could not find \"#{@filename}\"" puts "200 ERROR » #{errstr}" append_errorlog(errstr) Process.exit end end def abs_path(filename) if Conf::General::WZD_ROOT.include? "\\" then #system is windows if Conf::General::WZD_ROOT.match('.*\\\$') then path = Conf::General::WZD_ROOT.to_s + "logs\\" else path = Conf::General::WZD_ROOT.to_s + "\\logs\\" end elsif Conf::General::WZD_ROOT.include? "/" then #system is linux if Conf::General::WZD_ROOT.match('.*/$') then path = Conf::General::WZD_ROOT.to_s + "var/log/wzdftpd/" else path = Conf::General::WZD_ROOT.to_s + "/var/log/wzdftpd/" end else errstr = "Unable to determine host system type for \"#{Conf::General::WZD_ROOT}\"" puts "200 ERROR » #{errstr}" append_errorlog(errstr) Process.exit end return path end end class Wzdlog < Logfile def initialize @filename = "wzd.log" @abs_name = abs_path(@filename).to_s + @filename.to_s if !(File.exist?(@abs_name)) then errstr = "Configuration error, cannot find \"#{@filename}\"" puts "200 ERROR » #{errstr}" append_errorlog(errstr) Process.exit end end def remove_line errstr = "Removing lines from \"#{@filename}\" is strictly not permitted" puts "200 ERROR » #{errstr}" append_errorlog(errstr) Process.exit end end class Approvelog < Logfile def append(what, who) if !what.match(/^".*"$/).nil? || !who.match(/^".*"$/).nil? then wzdlog = Wzdlog.new file = open_file("a") time = Time.now.to_i.to_s file.puts("#{time} #{what} #{who}") wzdlog.append("APPROVE", "#{what} #{who}") file.close puts "200 APPROVED » #{what.tr('"', '')}" else errstr = "Missing double quotes. Caller must assure messages are correctly formated for: #{@filename}" puts "200 ERROR » #{errstr}" append_errorlog(errstr) end end def list file = open_file("r") lines = file.readlines if !lines.empty? then regstring = '(\d+)\s(".*")\s(".*")' reg = Regexp.new(regstring) lines.each { |line| if !reg.match(line).nil? then reqdate = Time.at($1.to_i).strftime("%b-%d %H:%M-%Z") puts "200 #{$2.tr('"', '')} » #{$3.tr('"', '')} » #{reqdate}" else errstr = "Possible malformed logline: #{line}" puts "200 ERROR » #{errstr}" append_errorlog(errstr) end } else puts "200 No requests have been made" end file.close end def remove_line(what) file = open_file("r+") oldlog = Oldlog.new("g-approve.old") output = Array.new regstring = '(\d+)\s("' + what + '")\s(.*)' reg = Regexp.new(regstring) removed_something = false file.each { |line| if reg.match(line).nil? then output << line else reqdate = Time.at($1.to_i).strftime("%b-%d %H:%M-%Z") oldlog.append(line) puts "200 REMOVED » \"#{$2.tr('"', '')}\" made by #{$3.tr('"', '')} on #{reqdate}" removed_something = true end } if !removed_something then puts "200 ERROR » #{what} was not found in #{@filename}" end file.pos = 0 file.print output file.truncate(file.pos) file.close end def get_approved contents = Array.new file = open_file("r") regstring = '(\d+)\s(".*")\s(".*")' reg = Regexp.new(regstring) file.each { |line| if !reg.match(line).nil? then contents << "#{$2.tr('"', '')} #{$3.tr('"', '')}" else errstr = "Possible malformed logline: #{line}" puts "200 ERROR » #{errstr}" append_errorlog(errstr) end } file.close return contents end end class Oldlog < Logfile def append(line) file = open_file("a") time = Time.now.to_i.to_s file.puts("#{time} #{line}") file.close end end class Errorlog < Logfile def remove_line error = "Removing lines from \"#{@filename}\" is strictly not permitted" puts "200 ERROR » #{errstr}" self.append(errstr) Process.exit end def append(line) file = open_file("a") time = Time.now.strftime("%b %d %H:%M:%S") file.puts("#{time} #{line}") file.close end def append_errorlog(line) self.append(line) end endendmodule Dirs class Section def initialize(path) if change_dir(path) then @path = path @dir else Process.exit end end def subdir?(look_for) if Dir.chdir(dirname) then return true ## was found and is a directory else return false end end def tag_approved(release, who) if change_dir(release) then if windows_paths? then release = @path + "\\" + release else release = @path + "/" + release end relle = Release.new(release) relle.tag_approved(who) else Process.exit end end private def windows_paths? if @path.include?("/") then return false elsif @path.include?("\\") then return true else errstr = "ERROR » Cant determine system type for \"#{dirname}\", no slashes" puts "200 #{errstr.to_s}" append_errorlog(errstr) Process.exit end end def append_errorlog(line) errorlog = Logfiles::Errorlog.new("g-error.log") errorlog.append(line) end def change_dir(dirname) begin Dir.chdir(dirname) return true rescue Errno::ENOTDIR errstr = "ERROR » Subdir \"#{dirname}\" is not a directory" puts "200 #{errstr.to_s}" append_errorlog(errstr) return false rescue Errno::ENOENT errstr = "ERROR » \"#{dirname}\" does not exist" puts "200 #{errstr.to_s}" append_errorlog(errstr) return false rescue Errno::EACCES errstr = "ERROR » Insufficient rights for entering \"#{dirname}\"" puts "200 #{errstr.to_s}" append_errorlog(errstr) return false end end def make_dir(dirname) # inside currdir begin Dir.mkdir(dirname, 666) rescue Errno::EACCES errstr = "ERROR » \"#{dirname}\" does not exist" puts "200 #{errstr.to_s}" append_errorlog(errstr) end end end class Release < Section def tag_approved(who) who = who.tr('"', '') reg = Regexp.new('\$who') tag = Conf::Approve::TAG_FORMAT.gsub!(reg, who) make_dir(tag) end endendhandler = Approve.new