Revision dfc48308
Added by Marc Dequènes over 15 years ago
- ID dfc483086769ea56e5da789007c7d31c5d3c5a76
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
[evol] reorganized CommandParser, and improved messages and error handling