Project

General

Profile

« Previous | Next » 

Revision dfc48308

Added by Marc Dequènes over 15 years ago

  • ID dfc483086769ea56e5da789007c7d31c5d3c5a76

[evol] reorganized CommandParser, and improved messages and error handling

View differences:

postman
#Socket.gethostname
class CommandParser
def self.run(order)
result_list = []
order.commands.each do |cmd|
logger.info "Executing command: #{cmd}"
begin
result_list << execute_cmd(order.user, cmd, order.refs)
rescue
logger.info "Command failed: " + $!
module CyborgHood
class CommandParser
def self.run(order)
result_list = []
order.commands.each do |cmdstr|
logger.info "Executing command: #{cmdstr}"
begin
result = execute_cmd(order.user, cmdstr, order.refs)
if result.nil?
result = OpenStruct.new
result.cmd = cmdstr
result.ok = false
result.message = "Command not recognized."
result.refs = nil
end
rescue CyberError => e
result = OpenStruct.new
result.cmd = cmdstr
result.ok = false
result.message = e.message.capitalize + "."
result.refs = nil
rescue
logger.warn "Command crashed: " + $!
result = OpenStruct.new
result.cmd = cmdstr
result.ok = false
result.message = "Internal error. Administrator is warned."
result.refs = nil
end
tag = result.ok ? "SUCCESS" :"FAILURE"
logger.debug "Command result: [#{tag}] #{result.message}"
result_list << result
end
result_list
end
result_list
end
private
private
def self.execute_cmd(user, cmdstr, refs)
cmdline = Shellwords.shellwords(cmdstr)
subsys = cmdline.shift
def self.execute_cmd(user, cmdstr, refs)
cmdline = Shellwords.shellwords(cmdstr)
subsys = cmdline.shift
result = OpenStruct.new
result.cmd = cmdstr
ok = true
case subsys.upcase
when "DNS"
case cmdline.shift.upcase
when "INFO"
if cmdline.empty?
result = OpenStruct.new
result.cmd = cmdstr
result.ok = false
ok = true
case subsys.upcase
when "DNS"
return if cmdline.empty?
case cmdline.shift.upcase
when "INFO"
return unless cmdline.empty?
list = CyborgHood::DnsDomain.find_by_manager(user)
txt_list = list.collect{|z| z.cn }.sort.join(", ")
logger.info "User is manager of the following zones: " + txt_list
result.message = "You are manager of the following zones: " + txt_list
else
ok = false
end
when "GET"
case cmdline.shift.upcase
when "ZONE"
zone = cmdline.shift.downcase
dom = CyborgHood::DnsDomain.new(zone)
logger.info "User requesting zone content for '#{zone}'"
if dom.hosted?
if dom.managed_by? user
logger.info "User is manager of the zone"
srv_dns = CyborgHood::Services::DNS.new(zone)
result.message = "Requested zone content attached."
zone_ref = {:content => srv_dns.read_zone, :filename => "dnszone_#{zone}.txt"}.to_ostruct
result.refs = [zone_ref]
else
logger.info "User is not allowed to manage the zone"
result.ok = true
result.message = "You are manager of the following zones: #{txt_list}."
when "GET"
return if cmdline.empty?
case cmdline.shift.upcase
when "ZONE"
return if cmdline.empty?
zone = cmdline.shift.downcase
dom = CyborgHood::DnsDomain.new(zone)
unless dom.hosted?
result.message = "This zone is not hosted here."
return result
end
unless dom.managed_by? user
result.message = "You are not allowed to manage this zone."
return result
end
else
logger.info "Zone not hosted"
result.message "This zone is not hosted here."
srv_dns = CyborgHood::Services::DNS.new(zone)
result.ok = true
result.message = "Requested zone content attached."
zone_ref = {:content => srv_dns.read_zone, :filename => "dnszone_#{zone}.txt"}.to_ostruct
result.refs = [zone_ref]
end
else
ok = false
end
when "SET"
case cmdline.shift.upcase
when "ZONE"
zone = cmdline.shift.downcase
dom = CyborgHood::DnsDomain.new(zone)
logger.info "User requesting zone content for '#{zone}'"
if dom.hosted?
if dom.managed_by? user
logger.info "User is manager of the zone"
srv_dns = CyborgHood::Services::DNS.new(zone)
content_ref = cmdline.shift.downcase
if content_ref =~ /^@(\d+)$/
part_ref = $1.to_i
if (1..refs.size).include? part_ref
part = refs[part_ref]
if part.content_type == "text/plain"
f = Tempfile.new(zone)
f.write(part.body)
f.close
logger.debug "Created temporary zone file '#{f.path}'"
srv_dns = CyborgHood::Services::DNS.new(zone)
current_serial = srv_dns.serial
logger.debug "Current serial: #{current_serial}"
result = srv_dns.check_zone_file(f.path)
if result.ok
logger.debug "New serial: #{result.serial}"
# allow new serial or missing serial (to allow creating a new zone or replacing a broken zone)
if current_serial.nil? or result.serial > current_serial
begin
srv_dns.write_zone_from_file(f.path)
f.close!
logger.info "zone changed"
if srv_dns.reload_zone
logger.info "zone reloaded"
else
logger.info "zone reload failed, replacing old content"
srv_dns.replace_zone_with_backup
result.message = "Internal error."
return result
end
rescue
logger.debug "Writing zone file failed"
raise
ensure
f.close!
end
else
logger.info "zone serial is not superior to current serial"
result.message = "Zone serial is not superior to current serial."
f.close!
return result
end
else
logger.info "new zone file is invalid"
result.message = "invalid zone data"
f.close!
return result
end
f.close!
else
logger.info "attachment for zone is not plain text"
result.message = "Attachment has wrong type."
return result
end
else
logger.info "attachement for zone not found"
result.message = "Attachment number not found."
return result
end
when "SET"
return if cmdline.empty?
case cmdline.shift.upcase
when "ZONE"
return if cmdline.empty?
zone = cmdline.shift.downcase
dom = CyborgHood::DnsDomain.new(zone)
unless dom.hosted?
result.message = "This zone is not hosted here."
return result
end
unless dom.managed_by? user
result.message = "You are not allowed to manage this zone."
return result
end
srv_dns = CyborgHood::Services::DNS.new(zone)
return if cmdline.empty?
content_ref = cmdline.shift.downcase
return unless content_ref =~ /^@(\d+)$/
part_ref = $1.to_i
unless (1..refs.size).include? part_ref
result.message = "Attachment number not found."
return result
end
part = refs[part_ref]
unless part.content_type == "text/plain"
result.message = "Attachment has wrong content-type."
return result
end
f = Tempfile.new(zone)
f.write(part.body)
f.close
logger.debug "Created temporary zone file '#{f.path}'"
srv_dns = CyborgHood::Services::DNS.new(zone)
current_serial = srv_dns.serial
logger.debug "Current serial: #{current_serial}"
dns_result = srv_dns.check_zone_file(f.path)
unless dns_result.ok
result.message = "Invalid zone data."
f.close!
return result
end
logger.debug "New serial: #{dns_result.serial}"
# allow new serial or missing serial (to allow creating a new zone or replacing a broken zone)
unless current_serial.nil? or dns_result.serial > current_serial
result.message = "Zone serial is not superior to current serial."
f.close!
return result
end
begin
srv_dns.write_zone_from_file(f.path)
logger.debug "zone changed"
if srv_dns.reload_zone
logger.debug "zone reloaded"
result.ok = true
result.message = "Zone updated."
else
ok = false
logger.warn "zone reload failed, replacing old content"
srv_dns.replace_zone_with_backup
result.message = "Internal error. Administrator is warned."
end
else
logger.info "User is not allowed to manage the zone"
result.message = "You are not allowed to manage this zone."
rescue
logger.warn "Writing zone file failed"
raise
ensure
f.close!
end
else
logger.info "Zone not hosted"
result.message "This zone is not hosted here."
end
else
ok = false
end
else
ok = false
end
else
ok = false
end
if not ok
result.message = "Command not recognized"
result.refs = nil
logger.info "Command not recognized: #{cmdstr}"
if result.message.nil?
# here fall lost souls
nil
else
result
end
end
result
end
end
# imap.store(message_id, "+FLAGS", [:Deleted])
# imap.expunge()
module CyborgHood
# not yet ready to be a real Cyborg
class Postman #< Cyborg
def initialize

Also available in: Unified diff