schleuder 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data.tar.gz.sig +0 -0
- data/LICENSE +339 -0
- data/README +32 -0
- data/bin/schleuder +96 -0
- data/bin/schleuder-fix-gem-dependencies +30 -0
- data/bin/schleuder-init-setup +37 -0
- data/bin/schleuder-migrate-v2.1-to-v2.2 +205 -0
- data/bin/schleuder-newlist +384 -0
- data/contrib/check-expired-keys.rb +59 -0
- data/contrib/mutt-schleuder-colors.rc +10 -0
- data/contrib/mutt-schleuder-resend.vim +24 -0
- data/contrib/smtpserver.rb +76 -0
- data/ext/default-list.conf +146 -0
- data/ext/default-members.conf +7 -0
- data/ext/list.conf.example +14 -0
- data/ext/schleuder.conf +62 -0
- data/lib/schleuder.rb +49 -0
- data/lib/schleuder/archiver.rb +46 -0
- data/lib/schleuder/crypt.rb +188 -0
- data/lib/schleuder/errors.rb +5 -0
- data/lib/schleuder/list.rb +177 -0
- data/lib/schleuder/list_config.rb +146 -0
- data/lib/schleuder/log/listlogger.rb +56 -0
- data/lib/schleuder/log/outputter/emailoutputter.rb +118 -0
- data/lib/schleuder/log/outputter/metaemailoutputter.rb +50 -0
- data/lib/schleuder/log/schleuderlogger.rb +23 -0
- data/lib/schleuder/mail.rb +861 -0
- data/lib/schleuder/mailer.rb +26 -0
- data/lib/schleuder/member.rb +69 -0
- data/lib/schleuder/plugin.rb +54 -0
- data/lib/schleuder/processor.rb +363 -0
- data/lib/schleuder/schleuder_config.rb +72 -0
- data/lib/schleuder/storage.rb +84 -0
- data/lib/schleuder/utils.rb +80 -0
- data/lib/schleuder/version.rb +3 -0
- data/man/schleuder-newlist.8 +191 -0
- data/man/schleuder.8 +400 -0
- data/plugins/README +20 -0
- data/plugins/manage_keys_plugin.rb +113 -0
- data/plugins/manage_members_plugin.rb +152 -0
- data/plugins/manage_self_plugin.rb +26 -0
- data/plugins/resend_plugin.rb +35 -0
- data/plugins/version_plugin.rb +12 -0
- metadata +178 -0
- metadata.gz.sig +2 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This script checks all public keys in the keyring of the given schleuder-list
|
4
|
+
# for being expired (or otherwise unusable) and reports the output (if there
|
5
|
+
# was something found) to the list-admins.
|
6
|
+
# Key are being reported if they expire within the next 14 days.
|
7
|
+
# We suggest to run this script from cron once a week.
|
8
|
+
|
9
|
+
$VERBOSE = nil
|
10
|
+
|
11
|
+
require 'schleuder'
|
12
|
+
include Schleuder
|
13
|
+
|
14
|
+
if ARGV.size != 1
|
15
|
+
puts "Usage: #{File.basename(__FILE__)} listname"
|
16
|
+
exit 1
|
17
|
+
elsif ! File.directory?(List.listdir(ARGV.first))
|
18
|
+
puts "No such list: '#{ARGV.first}'."
|
19
|
+
exit 1
|
20
|
+
end
|
21
|
+
|
22
|
+
listname = ARGV.first
|
23
|
+
Schleuder.list = List.new(listname)
|
24
|
+
|
25
|
+
now = Time.now
|
26
|
+
checkdate = now + 120960000 # two weeks
|
27
|
+
crypt = Crypt.new('')
|
28
|
+
msg = ''
|
29
|
+
unusable = []
|
30
|
+
expiring = []
|
31
|
+
|
32
|
+
crypt.list_keys.each do |key|
|
33
|
+
if (exp = key.subkeys.first.expires) > Time.utc(1971, 1, 1, 1)
|
34
|
+
# key has expiry date
|
35
|
+
if now < exp && exp < checkdate
|
36
|
+
# key expires in the near future
|
37
|
+
expdays = ((exp - now)/86400).to_i
|
38
|
+
expiring << [key, expdays]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
if not (trust = [:revoked, :expired, :disabled, :invalid].grep(key.trust)).empty?
|
43
|
+
unusable << [key, trust]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
expiring.each do |key,days|
|
48
|
+
msg << "-> Key expires in #{days} days:\n#{key.to_s}\n\n"
|
49
|
+
end
|
50
|
+
|
51
|
+
unusable.each do |key,trust|
|
52
|
+
msg << "-> Key is #{trust.join(' and ')}:\n#{key.to_s}\n"
|
53
|
+
end
|
54
|
+
|
55
|
+
unless msg.empty?
|
56
|
+
prefix = "Checking the public keys present in the keyring of list #{listname} for usability gave the following result:".fmt
|
57
|
+
Schleuder.log.notify_admin('keys', prefix + "\n\n" + msg)
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# insert "source /path/to/mutt-schleuder-colors.rc" into your muttrc
|
2
|
+
# metadata schleuder v2
|
3
|
+
color body red default "^From: .*"
|
4
|
+
color body red default "^To: .*"
|
5
|
+
color body red default "^Cc: .*"
|
6
|
+
color body red default "^Date: .*"
|
7
|
+
color body brightred default "^Enc: unenc.*"
|
8
|
+
color body red default "^Enc: enc.*"
|
9
|
+
color body brightred default "^Sig: [^G]?.*"
|
10
|
+
color body red default "^Sig: Good signature.*"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
" Reply-helper for mutt with schleuder (>= v2.0.0).
|
2
|
+
" Will insert a resend-line filled with the address from the quoted Text
|
3
|
+
" you're replying to.
|
4
|
+
function! SchleuderInsert(string)
|
5
|
+
let fromline = search('> From:', 'n')
|
6
|
+
let addr = matchstr(getline(fromline), '[^ <]*@[^ >]*')
|
7
|
+
let insline = search('^$', 'n')
|
8
|
+
" append after the first blank line
|
9
|
+
let foo = append(insline, a:string . addr)
|
10
|
+
" can't figure out how to append() a newline, so we simply add another
|
11
|
+
" empty line
|
12
|
+
return append(insline+1, '')
|
13
|
+
endfunction
|
14
|
+
|
15
|
+
function! SchleuderInsertResendEncrypted()
|
16
|
+
return SchleuderInsert('X-RESEND-ENCRYPTED-ONLY: ')
|
17
|
+
endfunction
|
18
|
+
|
19
|
+
function! SchleuderInsertResend()
|
20
|
+
return SchleuderInsert('X-RESEND: ')
|
21
|
+
endfunction
|
22
|
+
|
23
|
+
nmap ;sr :call SchleuderInsertResend()<CR>
|
24
|
+
nmap ;sc :call SchleuderInsertResendEncrypted()<CR>
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# defaults
|
4
|
+
port = 25
|
5
|
+
output = "/tmp"
|
6
|
+
|
7
|
+
def usage
|
8
|
+
file = File.basename(__FILE__)
|
9
|
+
puts "Usage: #{file} [-p portnum] { .../output_base_dir/ | .../bin/schleuder listname }"
|
10
|
+
exit 1
|
11
|
+
end
|
12
|
+
|
13
|
+
# get args
|
14
|
+
if (not ARGV.empty?) and (ARGV.first[0..0] == '-')
|
15
|
+
arg = ARGV.shift
|
16
|
+
if arg == '-p'
|
17
|
+
port = ARGV.shift.to_i
|
18
|
+
usage if port == 0 # nil or not convertable strings convert to 0
|
19
|
+
else
|
20
|
+
usage
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
output = ARGV.join(" ") || output
|
25
|
+
|
26
|
+
|
27
|
+
# run the server
|
28
|
+
require 'socket'
|
29
|
+
server = TCPServer.new("localhost", port)
|
30
|
+
|
31
|
+
def p(msg)
|
32
|
+
#puts "o:" + msg
|
33
|
+
@s.print msg + "\r\n"
|
34
|
+
end
|
35
|
+
|
36
|
+
# receive input
|
37
|
+
while (@s = server.accept)
|
38
|
+
input = ''
|
39
|
+
#p "200 OK"
|
40
|
+
p "220 localhost SMTP"
|
41
|
+
#p "Wazzup?"
|
42
|
+
begin
|
43
|
+
while i = @s.gets.chomp
|
44
|
+
#puts "i:" + i
|
45
|
+
case i[0..3].downcase
|
46
|
+
when 'ehlo', 'helo'
|
47
|
+
p "250 localhost"
|
48
|
+
when 'mail', 'rcpt', 'rset', '.'
|
49
|
+
p "250 ok"
|
50
|
+
when 'data'
|
51
|
+
p "354 go ahead"
|
52
|
+
when 'quit'
|
53
|
+
p "221 localhost"
|
54
|
+
@s.close
|
55
|
+
else
|
56
|
+
input << i + "\n"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
rescue IOError
|
60
|
+
end
|
61
|
+
# write input to #{output}
|
62
|
+
if File.directory? output
|
63
|
+
file = output + "/schleuder-#{$$}-#{Time.now.to_f}"
|
64
|
+
File.open(file, 'w') do |f|
|
65
|
+
f.puts input
|
66
|
+
end
|
67
|
+
File.chown 1000, 10, file
|
68
|
+
puts file
|
69
|
+
else
|
70
|
+
IO.popen(output, 'w') do |p|
|
71
|
+
p.puts input
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# Setting default values for lists. Each setting can be overridden by the
|
2
|
+
# list-specific config-file.
|
3
|
+
# Options are listed alphabetically and provided with the default behaviour.
|
4
|
+
# Some options that need to be set for each list individually are listed in
|
5
|
+
# list.conf.example.
|
6
|
+
#
|
7
|
+
# The configuration format is yaml (http://www.yaml.org).
|
8
|
+
#
|
9
|
+
# Be careful with changes here once lists are running! You might change
|
10
|
+
# their behaviour!
|
11
|
+
---
|
12
|
+
# Emailaddresses and key_fingerprints of the admin(s) (aka maintainer) of the
|
13
|
+
# list, which will receive errormsgs etc. Must be a non-empty array of hashes
|
14
|
+
# (:email, :key_fingerprint).
|
15
|
+
#admins:
|
16
|
+
#- email: anna@example.org
|
17
|
+
# key_fingerprint: 01234567DEADBEE01234567DEADBEEF
|
18
|
+
#- email: arthur@example.org
|
19
|
+
# key_fingerprint: DEADBEE01234567DEADBEEF01234567
|
20
|
+
#
|
21
|
+
# Only send out enrypted emails?
|
22
|
+
#send_encrypted_only: false
|
23
|
+
#
|
24
|
+
# Allow receiving unenrypted mails? If false, any other email will be bounced.
|
25
|
+
#receive_encrypted_only: false
|
26
|
+
#
|
27
|
+
# Allow receiving mails not validly signed? If false, any other email will be
|
28
|
+
# bounced.
|
29
|
+
#receive_signed_only: false
|
30
|
+
#
|
31
|
+
# Allow receiving mails that are not validly signed by a list members key? If
|
32
|
+
# true, any other email will be bounced.
|
33
|
+
#receive_authenticated_only: false
|
34
|
+
#
|
35
|
+
# Only allow mails being sent from a members address? If true, any other sending
|
36
|
+
# address will be dropped.
|
37
|
+
# NOTE: This is a very weak restriction mechanism on which you should not rely,
|
38
|
+
# as sending addresses can easily be faked! We recommend you to rather
|
39
|
+
# rely on the `receive_authenticated_only` option. Setting the
|
40
|
+
# `receive_authenticated_only` option to true, will authenticated senders
|
41
|
+
# based on the signature on the mail, which is the strongest
|
42
|
+
# authentication mechanism you can get.
|
43
|
+
# This option could be useful, if you would like to have a closed
|
44
|
+
# mailinglist, but could not yet get all members to properly use GPG.
|
45
|
+
#receive_from_member_emailaddresses_only: false
|
46
|
+
#
|
47
|
+
# Whether to accept only emails that are validly signed by a list-admin's key
|
48
|
+
# This is useful for newsletters, announce or notification lists
|
49
|
+
#receive_admin_only: false
|
50
|
+
#
|
51
|
+
# Which pgp encoding? Chose out of PLAIN (text/plain), APPL (application/pgp)
|
52
|
+
# and MIME (pgp/mime)
|
53
|
+
#default_mime: MIME
|
54
|
+
#
|
55
|
+
# Schleuder can include various metadata from the original mail. You can tweak
|
56
|
+
# Schleuder which header fields should be included.
|
57
|
+
#headers_to_meta:
|
58
|
+
#- :from
|
59
|
+
#- :to
|
60
|
+
#- :cc
|
61
|
+
#- :date
|
62
|
+
#
|
63
|
+
# Whether to keep the msgids (In-Reply-To:, References:) or not
|
64
|
+
# Schleuder will only pass valid schleuder Message-Ids, all the others
|
65
|
+
# are filtered out.
|
66
|
+
# This setting can lead to information leakage, as replies are connectable
|
67
|
+
# and a thread of (encrypted) messages can be built by an eavesdropper.
|
68
|
+
#keep_msgid: true
|
69
|
+
#
|
70
|
+
# Schleuder can be commanded to process various plugins via keywords in signed
|
71
|
+
# emails. To restrict the usage of specific keywords to the admin (some can
|
72
|
+
# cause fatal damage) list them here.
|
73
|
+
#keywords_admin_only: ['ADD-MEMBER', 'DELETE-MEMBER', 'DELETE-KEY', 'SAVE-MEMBERS', 'DEL-KEY']
|
74
|
+
#
|
75
|
+
# For keywords listed here the list-admin(s) will receive a notice whenever a
|
76
|
+
# member triggers a command with it.
|
77
|
+
#keywords_admin_notify: ['ADD-KEY']
|
78
|
+
#
|
79
|
+
# list-specific log-level: ERROR || WARN || INFO || DEBUG
|
80
|
+
#log_level: ERROR
|
81
|
+
#
|
82
|
+
# Log to SYSLOG? To enable set to true.
|
83
|
+
#log_syslog: false
|
84
|
+
#
|
85
|
+
# Log to IO (write into STDIN of another process/executable)? To enable specify
|
86
|
+
# executable with full path and optional arguments here.
|
87
|
+
# Example: /path/to/multilog tt /var/schleuderlists/listname/log/
|
88
|
+
#log_io: false
|
89
|
+
#
|
90
|
+
# Log to a file? To enable specify a filename, optionally with full path.
|
91
|
+
#log_file: false
|
92
|
+
#
|
93
|
+
# speaks for itself, no?
|
94
|
+
#public_footer:
|
95
|
+
#
|
96
|
+
# A string that the subject of every email that *is* validly signed by a
|
97
|
+
# list-member will be prefixed with (unless the string is already present in
|
98
|
+
# the subject)
|
99
|
+
#prefix: ''
|
100
|
+
#
|
101
|
+
# A string that the subject of every email that is *not* validly signed by a
|
102
|
+
# list-member will be prefixed with.
|
103
|
+
#prefix_in: ''
|
104
|
+
#
|
105
|
+
# A string that the subject of every internal email, that has been resent to
|
106
|
+
# the outside, will be prefixed with.
|
107
|
+
#prefix_out: ''
|
108
|
+
#
|
109
|
+
# Drop any bounces (incoming email not passing the receive_*_only-rules)
|
110
|
+
#bounces_drop_all: false
|
111
|
+
#
|
112
|
+
# Drop bounces if they match one of these headers. Must be a hash, keys and
|
113
|
+
# values are case insensitive.
|
114
|
+
#bounces_drop_on_headers: {'x-spam-flag' => 'yes'}
|
115
|
+
#
|
116
|
+
# Send a notice to admin(s) on bouncing or dropping
|
117
|
+
#bounces_notify_admins: true
|
118
|
+
#
|
119
|
+
# Include RFC-compliant List-* Headers into member mails
|
120
|
+
#include_list_headers: true
|
121
|
+
#
|
122
|
+
# Include OpenPGP-Header
|
123
|
+
#include_openpgp_header: true
|
124
|
+
#
|
125
|
+
# Prefered way to receive emails to note in OpenPGP-Header ('sign'|'encrypt'|'signencrypt'|'unprotected'|'none')
|
126
|
+
# 'none' to not include a preference
|
127
|
+
# default: 'signencrypt'
|
128
|
+
#openpgp_header_preference: 'signencrypt'
|
129
|
+
#
|
130
|
+
# If we want to dump the original incoming mail.
|
131
|
+
# ATTENTION: this stores the incoming e-mail on disk!
|
132
|
+
#dump_incoming_mail: false
|
133
|
+
#
|
134
|
+
# Maximum size of message allowed on the list in kilobyte. All others will be bounced.
|
135
|
+
# Default is 10MB
|
136
|
+
#max_message_size: 10240
|
137
|
+
#
|
138
|
+
# Whether to archive messages sent to list members or not.
|
139
|
+
# Setting this option to true will archive every message sent to list members
|
140
|
+
# into <listdir>/archive/$YEAR/$MONTH/$DAY/$MESSAGEID.msg
|
141
|
+
# The messages are encrypted with the lists' public key and dumped as it would
|
142
|
+
# have been handed over to the MTA.
|
143
|
+
# Beware that this will archive every communication over that list on a remote
|
144
|
+
# box amongst the matching private key and its password!
|
145
|
+
# Default: false
|
146
|
+
#archive: false
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Configuration options for individal lists.
|
2
|
+
# Options are listed alphabetically and provided with the default behaviour.
|
3
|
+
# Beyond those options listed here all options listed in default-list.conf can be specified.
|
4
|
+
#
|
5
|
+
# The configuration format is yaml (http://www.yaml.org).
|
6
|
+
---
|
7
|
+
# The emailaddress of the list. Needed to identify headers, loops and also the GnuPG key.
|
8
|
+
# Must be a valid email address.
|
9
|
+
#myaddr: list@example.org
|
10
|
+
# Realname of this list address (mainly used for GnuPG key)
|
11
|
+
#myname: The Listname
|
12
|
+
# Password for the GnuPG private key. (You're working on an encrypted filesystem, aren't you?)
|
13
|
+
# Make it long and complicated, you won't ever need to type it.
|
14
|
+
#gpg_password: "iuttIs6flewd)#misIg5drash/#tesJor:5Quej"
|
data/ext/schleuder.conf
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# Configuration options for schleuder.
|
2
|
+
# The options are sorted alphabetically and the defaults
|
3
|
+
# are provided as commented option.
|
4
|
+
# The configuration format is yaml.
|
5
|
+
---
|
6
|
+
# Outgoing SMTP host
|
7
|
+
#smtp_host: localhost
|
8
|
+
#
|
9
|
+
# Outgoing SMTP port
|
10
|
+
#smtp_port: 25
|
11
|
+
#
|
12
|
+
# Set the type of a key we might create for new lists.
|
13
|
+
#gpg_key_type: RSA
|
14
|
+
#
|
15
|
+
# Set the length of a key we might create for new lists.
|
16
|
+
#gpg_key_length: 2048
|
17
|
+
#
|
18
|
+
# Set the type of the subkey of a key we might create
|
19
|
+
# for new lists.
|
20
|
+
#gpg_subkey_type: RSA
|
21
|
+
#
|
22
|
+
# Set the length of the subkey of a key we might create
|
23
|
+
# for new lists.
|
24
|
+
#gpg_subkey_length: 2048
|
25
|
+
#
|
26
|
+
# Name of the per list config file.
|
27
|
+
#lists_configfile: list.conf
|
28
|
+
#
|
29
|
+
# Per list logfile name. Will be written into the directory
|
30
|
+
# of the list.
|
31
|
+
#lists_logfile: list.log
|
32
|
+
#
|
33
|
+
# Name of the per list file containing all members and their
|
34
|
+
# options.
|
35
|
+
#lists_memberfile: members.conf
|
36
|
+
#
|
37
|
+
# Where we find the global options for all lists.
|
38
|
+
# Note: the following notion isn't valid. You have
|
39
|
+
# to provide a fully qualified path.
|
40
|
+
#lists_default_conf: conf_dir + '/default-list.conf'
|
41
|
+
#
|
42
|
+
# Location of the various schleuderlists' directory.
|
43
|
+
#lists_dir: /var/schleuderlists
|
44
|
+
#
|
45
|
+
# Location of the global logfile.
|
46
|
+
#log_file: /var/log/schleuder/schleuder.log
|
47
|
+
#
|
48
|
+
# Global schleuder log level, might change after the list config
|
49
|
+
# have been read.
|
50
|
+
# Possible values: ERROR || WARN || INFO || DEBUG
|
51
|
+
#log_level: ERROR
|
52
|
+
#
|
53
|
+
# Location of schleuder plugins. Note: the following notion
|
54
|
+
# isn't valid. You have to provide a fully qualified path.
|
55
|
+
#plugins_dir = schleuder_base + '/plugins'
|
56
|
+
#
|
57
|
+
# The super administrator of this schleuder installation. This
|
58
|
+
# address will receive all notices which can'tbe delivered to a certain list
|
59
|
+
# admin. It will also be used as sender for emails to list-admins and thus
|
60
|
+
# receive their bounces and be seen in public.
|
61
|
+
#superadminaddr: root@localhost
|
62
|
+
|
data/lib/schleuder.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# third party
|
2
|
+
|
3
|
+
errmsg = "For use with ruby v%s %s is required!\nPlease run schleuder-fix-gem-dependencies to fix this!"
|
4
|
+
if RUBY_VERSION =~ /1.8/
|
5
|
+
require 'rubygems'
|
6
|
+
begin
|
7
|
+
require 'tmail'
|
8
|
+
rescue LoadError
|
9
|
+
$stderr.puts errmsg % %w(1.8, tmail \(preferably v1.2.3.1\))
|
10
|
+
exit 1
|
11
|
+
end
|
12
|
+
else
|
13
|
+
begin
|
14
|
+
gem 'actionmailer', '=2.3.14'
|
15
|
+
require 'action_mailer'
|
16
|
+
rescue LoadError
|
17
|
+
$stderr.puts errmsg % %w(1.9, actionmailer-2.3.14)
|
18
|
+
exit 1
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
gem 'gpgme', '=1.0.8'
|
23
|
+
require 'gpgme'
|
24
|
+
|
25
|
+
require 'net/smtp'
|
26
|
+
require 'log4r'
|
27
|
+
require 'log4r/outputter/emailoutputter'
|
28
|
+
require 'log4r/outputter/fileoutputter'
|
29
|
+
require 'filemagic/ext'
|
30
|
+
|
31
|
+
# internal requires
|
32
|
+
$:.unshift File.dirname(__FILE__)
|
33
|
+
require 'schleuder/errors'
|
34
|
+
require 'schleuder/utils'
|
35
|
+
require 'schleuder/crypt'
|
36
|
+
require 'schleuder/storage'
|
37
|
+
require 'schleuder/list_config'
|
38
|
+
require 'schleuder/list'
|
39
|
+
require 'schleuder/mailer'
|
40
|
+
require 'schleuder/mail'
|
41
|
+
require 'schleuder/member'
|
42
|
+
require 'schleuder/plugin'
|
43
|
+
require 'schleuder/schleuder_config'
|
44
|
+
require 'schleuder/log/outputter/emailoutputter'
|
45
|
+
require 'schleuder/log/outputter/metaemailoutputter'
|
46
|
+
require 'schleuder/log/schleuderlogger'
|
47
|
+
require 'schleuder/log/listlogger'
|
48
|
+
require 'schleuder/archiver'
|
49
|
+
require 'schleuder/processor'
|