Revision 2f1c6b5b
Added by Marc Dequènes over 14 years ago
- ID 2f1c6b5bfb3ebbadde902db6e5d540530976de36
bin/postman | ||
---|---|---|
|
||
|
||
module CyborgHood
|
||
# example for specific validation rules of the bot-specific config file
|
||
#class Config
|
||
# protected
|
||
# class PostmanValidator < CyborgHoodValidator
|
||
# def validate_hook_in(value, rule, path, msg_list)
|
||
# msg_list << "Youhou !!!"
|
||
# end
|
||
# end
|
||
#end
|
||
|
||
module PostmanHome
|
||
include I18nTranslation
|
||
bindtextdomain("cyborghood_postman", {:path => Config::L10N_DIR, :charset => "UTF-8"})
|
data/cyborghood/default_config/global.yaml | ||
---|---|---|
---
|
||
log:
|
||
console_level: normal
|
||
debug:
|
||
flags: []
|
||
contact: {}
|
||
i18n: {}
|
||
ldap:
|
||
host: localhost
|
||
port: 389
|
||
scope: sub
|
data/cyborghood/default_config/postman.yaml | ||
---|---|---|
---
|
||
imap:
|
||
host: localhost
|
||
min_check_interval: 600
|
||
mail:
|
||
smtp_server: localhost
|
||
smtp_port: 25
|
||
max_drift_time: 3600
|
||
dns: {}
|
data/cyborghood/schema/global.yaml | ||
---|---|---|
---
|
||
type: map
|
||
mapping:
|
||
"log":
|
||
type: map
|
||
mapping:
|
||
"path": {type: str, required: yes, name: LogPath}
|
||
"console_level": {type: str, enum: [quiet, normal, verbose]}
|
||
"debug":
|
||
type: map
|
||
mapping:
|
||
"flags":
|
||
type: seq
|
||
sequence:
|
||
- {type: str, enum: [debug_nomaildeletion, debug_ignorereplay, debug_imapverbose]}
|
||
"contact":
|
||
type: map
|
||
mapping:
|
||
"name": {type: str}
|
||
"email": {type: str}
|
||
"url": {type: str}
|
||
"i18n":
|
||
type: map
|
||
mapping:
|
||
"restricted_language_set":
|
||
type: seq
|
||
sequence:
|
||
- type: str
|
||
# temporary location
|
||
"ldap":
|
||
type: map
|
||
required: true
|
||
name: LdapMapping
|
||
mapping:
|
||
=:
|
||
type: any
|
||
|
data/cyborghood/schema/postman.yaml | ||
---|---|---|
---
|
||
type: map
|
||
mapping:
|
||
"imap":
|
||
type: map
|
||
mapping:
|
||
"host": {type: str}
|
||
"ca_cert": {type: str}
|
||
"login": {type: str, required: yes}
|
||
"passwd": {type: str, required: yes}
|
||
"min_check_interval": {type: int}
|
||
"mail":
|
||
type: map
|
||
mapping:
|
||
"from_address": {type: str}
|
||
"smtp_server": {type: str}
|
||
"smtp_port": {type: int}
|
||
"organization": {type: str}
|
||
"key_id": {type: str, required: yes}
|
||
"key_passphrase": {type: str, required: yes}
|
||
"max_drift_time": {type: int}
|
||
"dns":
|
||
type: map
|
||
mapping:
|
||
"master_zone_pattern": {type: str, required: yes}
|
lib/cyborghood.rb | ||
---|---|---|
|
||
$KCODE = 'UTF8'
|
||
require 'jcode'
|
||
require 'pp'
|
||
require 'cyborghood/base/config'
|
||
require 'cyborghood/base/info'
|
||
require 'cyborghood/base/lang_additions'
|
lib/cyborghood/base/config.rb | ||
---|---|---|
#++
|
||
|
||
require 'singleton'
|
||
require 'yaml'
|
||
require 'cyborghood/base/config_setup'
|
||
require 'yaml'
|
||
require 'kwalify'
|
||
|
||
module CyborgHood
|
||
class Config
|
||
... | ... | |
|
||
def self.load(name = nil)
|
||
# load all config parts
|
||
config = fetch_config
|
||
g_config_raw = load_config_raw()
|
||
g_def = parse('config', 'global', g_config_raw)
|
||
g_default_config = load_default_config()
|
||
config = merge_into_default_config(g_default_config, g_def)
|
||
|
||
unless name.nil?
|
||
config_spc = fetch_config(name)
|
||
config = merge_configs(config, config_spc) if config_spc
|
||
config_spc_raw = load_config_raw(name)
|
||
spc_def = parse('config', name, config_spc_raw)
|
||
default_config_spc = load_default_config(name)
|
||
spc_config = merge_into_default_config(default_config_spc, spc_def)
|
||
|
||
config = merge_into_default_config(config, spc_config)
|
||
end
|
||
|
||
# create config object for easier access
|
||
... | ... | |
end
|
||
end
|
||
|
||
private
|
||
protected
|
||
|
||
def self.merge_into_default_config(conf_default, conf)
|
||
new_conf = conf_default.dup
|
||
conf.each_pair do |k, v|
|
||
if conf_default.has_key?(k) and conf_default[k].is_a?(Hash) and v.is_a?(Hash)
|
||
new_conf[k] = merge_into_default_config(conf_default[k], v)
|
||
elsif conf_default.has_key?(k) and conf_default[k].is_a?(Hash) and v.nil?
|
||
new_conf[k] = conf_default[k]
|
||
else
|
||
new_conf[k] = v
|
||
end
|
||
end
|
||
return new_conf
|
||
end
|
||
|
||
def self.fetch_config(name = nil)
|
||
def self.load_config_raw(name = nil)
|
||
begin
|
||
if name.nil?
|
||
filename = CONFFILE_GLOBAL
|
||
else
|
||
filename = sprintf(CONFFILE_BOT, name)
|
||
filename = CONFFILE_BOT % name
|
||
end
|
||
filepath = File.join(File.expand_path(CFG_DIR), filename)
|
||
str = File.read(filepath)
|
||
YAML.load(str)
|
||
File.read(filepath)
|
||
rescue
|
||
logger.fatal "Problems fetching configuration file '" + filepath + "': " + $!
|
||
exit 1
|
||
end
|
||
end
|
||
|
||
def self.merge_configs(conf1, conf2)
|
||
new_conf = conf1.dup
|
||
conf2.each_pair do |k, v|
|
||
if conf1.has_key?(k) and conf1[k].is_a?(Hash) and v.is_a?(Hash)
|
||
new_conf[k] = merge_configs(conf1[k], v)
|
||
def self.parse(def_name, type, def_data_raw, validate = true, extra_data = nil)
|
||
schema = load_schema(type)
|
||
|
||
if validate
|
||
validator_klass = case type
|
||
when 'global'
|
||
GlobalValidator
|
||
else
|
||
new_conf[k] = v
|
||
klass_name = type.capitalize + "Validator"
|
||
if self.const_defined? klass_name
|
||
self.const_get klass_name
|
||
else
|
||
CyborgHoodValidator
|
||
end
|
||
end
|
||
validator = validator_klass.new(schema)
|
||
validator.extra_data = extra_data
|
||
else
|
||
validator = nil
|
||
end
|
||
|
||
# validate config with schema
|
||
parser = Kwalify::Yaml::Parser.new(validator)
|
||
def_data = parser.parse(def_data_raw, :filename => def_name, :untabify => true)
|
||
raise_if_validation_errors("#{type.capitalize} '#{def_name}'", parser.errors)
|
||
|
||
def_data
|
||
rescue
|
||
logger.fatal "Problems parsing %s file for '%s': %s" % [def_name, type, $!]
|
||
exit 1
|
||
end
|
||
|
||
def self.load_default_config(type = "global")
|
||
filename = File.join(DATA_DIR, "default_config", type + ".yaml")
|
||
default_config_raw = File.read(filename)
|
||
default_config = parse(':defaults:', type, default_config_raw, false)
|
||
default_config
|
||
rescue
|
||
logger.fatal "Could not load default config for '%s': %s" % [type, $!]
|
||
exit 1
|
||
end
|
||
|
||
def self.load_schema(type = "global")
|
||
schema_file = File.join(DATA_DIR, "schema", type + ".yaml")
|
||
schema = YAML.load_file(schema_file)
|
||
|
||
# validate schema
|
||
metavalidator = Kwalify::MetaValidator.instance
|
||
errors = metavalidator.validate(schema)
|
||
raise_if_validation_errors("'#{type}' schema", errors)
|
||
|
||
schema
|
||
rescue
|
||
logger.fatal "Could not load schema for '%s': %s" % [type, $!]
|
||
exit 1
|
||
end
|
||
|
||
protected
|
||
|
||
class CyborgHoodValidator < Kwalify::Validator
|
||
attr_accessor :extra_data
|
||
|
||
## hook method called by Validator#validate()
|
||
def validate_hook(value, rule, path, errors)
|
||
msg_list = []
|
||
|
||
validate_hook_in(value, rule, path, msg_list)
|
||
|
||
msg_list.each do |msg|
|
||
errors << Kwalify::ValidationError.new(msg, path)
|
||
end
|
||
end
|
||
|
||
def validate_hook_in(value, rule, path, msg_list)
|
||
end
|
||
end
|
||
|
||
class GlobalValidator < CyborgHoodValidator
|
||
def validate_hook_in(value, rule, path, msg_list)
|
||
case rule.name
|
||
when 'LogPath'
|
||
unless File.directory? value
|
||
msg_list << "Log path must be an existing directory"
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
def self.raise_if_validation_errors(name, errors)
|
||
if errors and not errors.empty?
|
||
err_msg = []
|
||
for e in errors
|
||
err_msg << "[#{e.path}] #{e.message}"
|
||
end
|
||
logger.fatal "%s is not valid:\n%s" % [name, err_msg.join("\n")]
|
||
exit 1
|
||
end
|
||
return new_conf
|
||
end
|
||
end
|
||
end
|
lib/cyborghood/base/language.rb | ||
---|---|---|
list = ['en'] + Dir.new(Config::L10N_DIR).select{|d| File.directory?(File.join(Config::L10N_DIR, d)) and d[0..0] != "." }
|
||
# local admin can restrict available languages
|
||
# (may be useful if l10n is partial due to third party plugins)
|
||
list = list & @config.i18n.restricted_language_set if @config.i18n and @config.i18n.restricted_language_set
|
||
list = list & @config.i18n.restricted_language_set if @config.i18n.restricted_language_set
|
||
list = ['en'] if list.empty?
|
||
list
|
||
end
|
lib/cyborghood/base/logger.rb | ||
---|---|---|
|
||
def output_level(level)
|
||
l = case level
|
||
when :verbose
|
||
when 'verbose'
|
||
Log4r::DEBUG
|
||
when :quiet
|
||
when 'quiet'
|
||
Log4r::FATAL
|
||
else # normal
|
||
Log4r::WARN
|
lib/cyborghood/cyborg.rb | ||
---|---|---|
begin
|
||
@cl = Jabber::Client.new(@jid)
|
||
@cl.allow_tls = true
|
||
@cl.ssl_capath = @config.xmpp.ssl_capath unless @config.xmpp.ssl_capath == nil
|
||
@cl.ssl_capath = @config.xmpp.ssl_capath unless @config.xmpp.ssl_capath.nil?
|
||
reconnect
|
||
rescue Jabber::ServerError => e
|
||
if e.error.type == :cancel and e.error.code == 409
|
lib/cyborghood/imap.rb | ||
---|---|---|
@available_mails = 0
|
||
@available_mails_mutex = Mutex.new
|
||
|
||
if not (@config.debug.nil? or @config.debug.flags.nil?) and @config.debug.flags.include?(:debug_imapverbose)
|
||
if @config.debug.flags.include?('debug_imapverbose')
|
||
Net::IMAP.debug = true
|
||
end
|
||
end
|
||
... | ... | |
end
|
||
|
||
def delete
|
||
if @config.debug.nil? or @config.debug.flags.nil? or not @config.debug.flags.include?(:debug_nomaildeletion)
|
||
if not @config.debug.flags.include?('debug_nomaildeletion')
|
||
@imap.store(@message_id, "+FLAGS", [:Deleted])
|
||
end
|
||
end
|
||
... | ... | |
def connect
|
||
return true if @imap
|
||
|
||
# using SSL because TLS does not work in the NET::IMAP library
|
||
# using SSL because TLS does not work in the NET::IMAP library in Ruby 1.8
|
||
# (but available in 1.9)
|
||
ssl = (not @params.ca_cert.nil?)
|
||
port = @params.port || (ssl ? 993 : 143)
|
||
check_ca = ssl
|
||
... | ... | |
begin
|
||
check_inbox(&message_handler)
|
||
# don't loop forever
|
||
return if not (@config.debug.nil? or @config.debug.flags.nil?) and @config.debug.flags.include?(:debug_nomaildeletion)
|
||
return if @config.debug.flags.include?('debug_nomaildeletion')
|
||
end while waiting_mails?
|
||
|
||
if self.capabilities.include?("IDLE")
|
lib/cyborghood/mail.rb | ||
---|---|---|
class Mail < Delegator
|
||
include I18nTranslation
|
||
|
||
DEFAULT_MAX_DRIFT_TIME = 3600
|
||
|
||
attr_accessor :user, :signature_timestamp
|
||
|
||
def initialize(msg = nil)
|
||
... | ... | |
|
||
def process
|
||
if is_marked?
|
||
if not (@config.debug.nil? or @config.debug.flags.nil?) and @config.debug.flags.include?(:debug_ignorereplay)
|
||
if @config.debug.flags.include?('debug_ignorereplay')
|
||
logger.warn "Debug: ignoring replay"
|
||
else
|
||
return MailReport.new(:error => _("Replay detected."))
|
||
... | ... | |
def deliver
|
||
check_headers
|
||
|
||
smtp_server = @config.mail.smtp_server || "localhost"
|
||
smtp_port = @config.mail.smtp_port || 25
|
||
smtp_server = @config.mail.smtp_server
|
||
smtp_port = @config.mail.smtp_port
|
||
smtp_from = @mail.from_addrs.collect{|a| a.address}.join(", ")
|
||
smtp_to = @mail.to_addrs.collect{|a| a.address}
|
||
Net::SMTP.start(smtp_server, smtp_port) do |smtp|
|
||
... | ... | |
|
||
drift = Time.new.to_i - sig_check.timestamp.to_i
|
||
logger.debug "Signature drift time: #{drift}"
|
||
unless drift.abs < (@config.mail.max_drift_time || DEFAULT_MAX_DRIFT_TIME)
|
||
unless drift.abs < @config.mail.max_drift_time
|
||
if drift > 0
|
||
return MailReport.new(:error => _("The signature was made too long ago (check your system clock). Rejected message to avoid replay attacks."), :user => user)
|
||
else
|
Also available in: Unified diff
[evol] configuration defaults and schema checking (closes 21)