at_email 0.0.1
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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +28 -0
- data/bin/at_email +24 -0
- data/lib/at_email.rb +210 -0
- data/lib/at_email/account.rb +3 -0
- data/lib/at_email/account/connection.rb +32 -0
- data/lib/at_email/config.rb +4 -0
- data/lib/at_email/config/cmd_opt_parser.rb +58 -0
- data/lib/at_email/config/config_file.rb +100 -0
- data/lib/at_email/core.rb +3 -0
- data/lib/at_email/core/default.rb +62 -0
- data/lib/at_email/tasks.rb +3 -0
- data/lib/at_email/tasks/imap_to_fs.rb +756 -0
- data/lib/at_email/threads.rb +3 -0
- data/lib/at_email/threads/thread_queue.rb +83 -0
- data/lib/at_email/version.rb +10 -0
- metadata +59 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 074b5f8e272c1f28f2fa4089e5396b13b061c1dd
|
4
|
+
data.tar.gz: f5eaf714aa99285d339078fe5ee59965ca12614c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e689e838a44d38ec50bee5c5afc6624bcefb5eb064fdc2f01231799d229bf84d8b15287d05e1cd93f84a18811da2e354672e3c8a4f5cd5d3bbc15b9e2afacd95
|
7
|
+
data.tar.gz: 83e37a70a22770e6abb9ee613aeb40af85668f196223a81f1a767b7da9af09afba065cd2cc12f13f8de24ac005a9e4cd35cd2f1957d51f607d6896f24d9e2b6b
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2018 Robin Patel
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# at_email
|
2
|
+
|
3
|
+
A project to build an e-mail management and support toolkit.
|
4
|
+
|
5
|
+
The project is currently at a very early stage and the functionality is likely to be unstable and possible destructive for the time being, I would not recommend using this software at this time. We will update this information when the software is in a more stable stage of development.
|
6
|
+
|
7
|
+
## Prerequisites
|
8
|
+
|
9
|
+
* ruby 2.3.7+
|
10
|
+
* GEM: concurrent-ruby (1.1.3)
|
11
|
+
|
12
|
+
## License
|
13
|
+
|
14
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
|
15
|
+
|
16
|
+
## Acknowledgments
|
17
|
+
|
18
|
+
* https://github.com/joeyates
|
19
|
+
|
20
|
+
## Disclaimer
|
21
|
+
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
28
|
+
SOFTWARE.
|
data/bin/at_email
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.expand_path("../lib/", __dir__))
|
4
|
+
require 'at_email'
|
5
|
+
$runtime_configure = At_email::RuntimeConfigure.new
|
6
|
+
$runtime_configure.get_app_path
|
7
|
+
$options = At_email::Config::Cmd_Opt_Parser.new(ARGV)
|
8
|
+
config_file = At_email::Config::Config_File.new
|
9
|
+
$config = config_file.get_config()
|
10
|
+
$runtime_configure.configure_logger
|
11
|
+
|
12
|
+
$logger.debug ''
|
13
|
+
$logger.warn 'Welcome to atEmail - Build: ' + At_email::VERSION + ' - PID: ' + Process.pid.to_s
|
14
|
+
$logger.debug ''
|
15
|
+
$logger.warn 'Config File: ' + $options.config_file + ' - Task Starting'
|
16
|
+
$logger.warn 'Log File: ' + $logger.log_file_default
|
17
|
+
|
18
|
+
$runtime_configure.output_config
|
19
|
+
|
20
|
+
task = At_email::Tasks::Imap_To_Fs.new()
|
21
|
+
|
22
|
+
task.execute
|
23
|
+
|
24
|
+
$logger.warn 'Config File: ' + $options.config_file + ' - Task Complete'
|
data/lib/at_email.rb
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
module At_email ; end
|
2
|
+
|
3
|
+
### libs
|
4
|
+
require 'fileutils'
|
5
|
+
require "logger"
|
6
|
+
require 'digest'
|
7
|
+
|
8
|
+
### at_email libs
|
9
|
+
require "at_email/core"
|
10
|
+
require "at_email/version"
|
11
|
+
require "at_email/config"
|
12
|
+
require "at_email/account"
|
13
|
+
require "at_email/tasks"
|
14
|
+
require "at_email/threads"
|
15
|
+
|
16
|
+
module At_email
|
17
|
+
|
18
|
+
DEFAULT_CONFIG_FILE = 'cfg/defaults/default_config.json'
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
module At_email
|
23
|
+
|
24
|
+
class At_email::At_Logger
|
25
|
+
|
26
|
+
attr_reader :log_file_default
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
|
30
|
+
filename_timestamp = Time.now.strftime("%Y%m%d_%H%M%S")
|
31
|
+
log_file_dir = $config[:output_base_dir] + '/_logs'
|
32
|
+
|
33
|
+
@log_file_default = log_file_dir + '/' + $config[:task] + '.' + $config[:account_id] + '.' + filename_timestamp + '.log'
|
34
|
+
if !Dir.exists?(log_file_dir)
|
35
|
+
FileUtils.mkdir_p log_file_dir
|
36
|
+
end
|
37
|
+
@logger_stdout = Logger.new(STDOUT)
|
38
|
+
@logger_stderr = Logger.new(STDERR)
|
39
|
+
@logger_file_default = Logger.new(@log_file_default)
|
40
|
+
@logger_stdout.datetime_format = '%Y-%m-%d %H:%M:%S'
|
41
|
+
@logger_stdout.formatter = proc do |severity, datetime, progname, msg|
|
42
|
+
"#{datetime} - " + $config[:task] + " - " + $config[:account_id] + " - #{msg}\n"
|
43
|
+
end
|
44
|
+
@logger_stderr.datetime_format = '%Y-%m-%d %H:%M:%S'
|
45
|
+
@logger_stderr.formatter = proc do |severity, datetime, progname, msg|
|
46
|
+
"#{datetime} - " + $config[:task] + " - " + $config[:account_id] + " - #{msg}\n"
|
47
|
+
end
|
48
|
+
@logger_file_default.datetime_format = '%Y-%m-%d %H:%M:%S'
|
49
|
+
@logger_file_default.formatter = proc do |severity, datetime, progname, msg|
|
50
|
+
"#{datetime} - " + $config[:task] + " - " + $config[:account_id] + " - #{msg}\n"
|
51
|
+
end
|
52
|
+
if $options.silent
|
53
|
+
@logger_stdout.level = Logger::FATAL
|
54
|
+
@logger_stderr.level = Logger::FATAL
|
55
|
+
@logger_file_default.level = Logger::FATAL
|
56
|
+
elsif $options.quiet
|
57
|
+
@logger_stdout.level = Logger::WARN
|
58
|
+
@logger_stderr.level = Logger::WARN
|
59
|
+
@logger_file_default.level = Logger::WARN
|
60
|
+
elsif $options.verbose
|
61
|
+
@logger_stdout.level = Logger::DEBUG
|
62
|
+
@logger_stderr.level = Logger::DEBUG
|
63
|
+
@logger_file_default.level = Logger::DEBUG
|
64
|
+
else
|
65
|
+
@logger_stdout.level = Logger::INFO
|
66
|
+
@logger_stderr.level = Logger::INFO
|
67
|
+
@logger_file_default.level = Logger::INFO
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def debug(event)
|
72
|
+
@logger_stdout.debug(event)
|
73
|
+
@logger_file_default.debug(event)
|
74
|
+
end
|
75
|
+
|
76
|
+
def info(event)
|
77
|
+
@logger_stdout.info(event)
|
78
|
+
@logger_file_default.info(event)
|
79
|
+
end
|
80
|
+
|
81
|
+
def warn(event)
|
82
|
+
@logger_stderr.warn(event)
|
83
|
+
@logger_file_default.warn(event)
|
84
|
+
end
|
85
|
+
|
86
|
+
def error(event)
|
87
|
+
@logger_stderr.error(event)
|
88
|
+
@logger_file_default.error(event)
|
89
|
+
end
|
90
|
+
|
91
|
+
def fatal(event)
|
92
|
+
@logger_stderr.fatal(event)
|
93
|
+
@logger_file_default.fatal(event)
|
94
|
+
end
|
95
|
+
|
96
|
+
def unknown(event)
|
97
|
+
@logger_stderr.unknown(event)
|
98
|
+
@logger_file_default.unknown(event)
|
99
|
+
end
|
100
|
+
|
101
|
+
def event(event_level, event_tag, event_data)
|
102
|
+
event_tag_formatted = get_event_tag_formatted(event_tag)
|
103
|
+
if event_tag_formatted === ''
|
104
|
+
log_string = event_data
|
105
|
+
else
|
106
|
+
log_string = event_tag_formatted + ' - ' + event_data
|
107
|
+
end
|
108
|
+
case event_level
|
109
|
+
when 'DEBUG'
|
110
|
+
$logger.debug log_string
|
111
|
+
when 'WARN'
|
112
|
+
$logger.error log_string
|
113
|
+
when 'ERROR'
|
114
|
+
$logger.fatal ''
|
115
|
+
$logger.error log_string
|
116
|
+
$logger.error ''
|
117
|
+
$logger.error 'Error at line number: ' + __LINE__.to_s + ' of file: ' + __FILE__
|
118
|
+
caller.each do |stack_line|
|
119
|
+
$logger.error ' ' + stack_line
|
120
|
+
end
|
121
|
+
$logger.error ''
|
122
|
+
when 'FATAL'
|
123
|
+
error_code = 1
|
124
|
+
$logger.fatal ''
|
125
|
+
$logger.fatal log_string
|
126
|
+
$logger.fatal ''
|
127
|
+
$logger.fatal 'Fatal Error at line number: ' + __LINE__.to_s + ' of file: ' + __FILE__
|
128
|
+
caller.each do |stack_line|
|
129
|
+
$logger.fatal ' ' + stack_line
|
130
|
+
end
|
131
|
+
$logger.fatal ''
|
132
|
+
$logger.fatal 'Exiting with error code: ' + error_code.to_s
|
133
|
+
$logger.fatal ''
|
134
|
+
puts "\n"
|
135
|
+
exit(error_code)
|
136
|
+
else
|
137
|
+
$logger.info log_string
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def get_event_tag_formatted(event_tag)
|
142
|
+
event_tag_formatted = ''
|
143
|
+
if event_tag.length == 0
|
144
|
+
event_tag_formatted = ''
|
145
|
+
else
|
146
|
+
if event_tag.length <= 2
|
147
|
+
event_tag_formatted = '*' + event_tag + '*'
|
148
|
+
else
|
149
|
+
event_tag_formatted = '***** ' + event_tag + ' *****'
|
150
|
+
end
|
151
|
+
end
|
152
|
+
return event_tag_formatted
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
class At_email::RuntimeConfigure
|
158
|
+
|
159
|
+
def configure_logger
|
160
|
+
$logger = At_email::At_Logger.new()
|
161
|
+
end
|
162
|
+
|
163
|
+
def output_config
|
164
|
+
$logger.debug ''
|
165
|
+
$logger.debug 'Configuration'
|
166
|
+
$config.each do |key, value|
|
167
|
+
if key.to_s === 'password'
|
168
|
+
$logger.debug ' ' + key.to_s + ' = ' + '*' * value.to_s.length
|
169
|
+
else
|
170
|
+
$logger.debug ' ' + key.to_s + ' = ' + value.to_s
|
171
|
+
end
|
172
|
+
end
|
173
|
+
$logger.debug ''
|
174
|
+
end
|
175
|
+
|
176
|
+
def get_app_path
|
177
|
+
$app_path = File.dirname(File.expand_path(File.dirname($0)))
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
class At_email::Formatting
|
183
|
+
|
184
|
+
def initialize
|
185
|
+
end
|
186
|
+
|
187
|
+
def get_hash(data, hash_length)
|
188
|
+
if !hash_length.is_a? Numeric
|
189
|
+
$logger.event('FATAL', 'FATAL ERROR', 'hash_length variable is not numeric')
|
190
|
+
return false
|
191
|
+
end
|
192
|
+
if (hash_length > 32)
|
193
|
+
$logger.event('FATAL', 'FATAL ERROR', 'hash_length maximum limit is 32 - Requested length: ' + hash_length.to_s)
|
194
|
+
return false
|
195
|
+
end
|
196
|
+
return Digest::MD5.hexdigest(data)[0...hash_length]
|
197
|
+
end
|
198
|
+
|
199
|
+
def get_random_id(id_length)
|
200
|
+
hash = get_hash(Time.now.to_f.to_s + '-' + rand(1..1000000000000).to_s, id_length)
|
201
|
+
if hash
|
202
|
+
return hash
|
203
|
+
else
|
204
|
+
return false
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
require 'net/imap'
|
3
|
+
|
4
|
+
class At_email::Account::Imap < Net::IMAP
|
5
|
+
attr_accessor :debug
|
6
|
+
end
|
7
|
+
|
8
|
+
class At_email::Account::ImapConnection
|
9
|
+
|
10
|
+
attr_reader :imap
|
11
|
+
|
12
|
+
METADATA_ATTRIBUTES = [ 'ENVELOPE', 'FLAGS' ].freeze
|
13
|
+
REQUESTED_ATTRIBUTES = [ 'INTERNALDATE', 'RFC822', 'RFC822.SIZE' ].freeze
|
14
|
+
|
15
|
+
def initialize()
|
16
|
+
$logger.info 'Connecting to IMAP server - Host: ' + $config[:server] + ' - Port: ' + $config[:port].to_s
|
17
|
+
connect_config = {port: $config[:port], ssl: $config[:ssl]}
|
18
|
+
@imap = At_email::Account::Imap.new($config[:server], connect_config)
|
19
|
+
end
|
20
|
+
|
21
|
+
def login
|
22
|
+
$logger.info 'Logging into IMAP server - Username: ' + $config[:username]
|
23
|
+
@imap.login($config[:username], $config[:password])
|
24
|
+
end
|
25
|
+
|
26
|
+
def disconnect
|
27
|
+
$logger.debug 'Logging out from IMAP server'
|
28
|
+
@imap.logout
|
29
|
+
@imap.disconnect
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
|
2
|
+
require 'optparse'
|
3
|
+
require 'optparse/time'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'pp'
|
6
|
+
|
7
|
+
class At_email::Config::Cmd_Opt_Parser
|
8
|
+
|
9
|
+
attr_reader :config_file
|
10
|
+
attr_reader :verbose
|
11
|
+
attr_reader :quiet
|
12
|
+
attr_reader :silent
|
13
|
+
|
14
|
+
CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary]
|
15
|
+
CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }
|
16
|
+
|
17
|
+
def initialize(args)
|
18
|
+
@silent = false
|
19
|
+
@quiet = false
|
20
|
+
@verbose = false
|
21
|
+
opt_parser = OptionParser.new do |opts|
|
22
|
+
opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
|
23
|
+
opts.separator ""
|
24
|
+
opts.separator "Options:"
|
25
|
+
opts.on("-c [CONFIG FILE]", "--config-file [CONFIG FILE]", String, "Config File (JSON)") do |config_file|
|
26
|
+
@config_file = config_file
|
27
|
+
end
|
28
|
+
opts.on("-s", "--silent", "Run silently") do
|
29
|
+
@silent = true
|
30
|
+
end
|
31
|
+
opts.on("-q", "--quiet", "Run quietly") do
|
32
|
+
@quiet = true
|
33
|
+
if @silent
|
34
|
+
@silent = false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
opts.on("-v", "--verbose", "Run verbosely") do
|
38
|
+
@verbose = true
|
39
|
+
if @quiet
|
40
|
+
@quiet = false
|
41
|
+
end
|
42
|
+
if @silent
|
43
|
+
@silent = false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
47
|
+
puts opts
|
48
|
+
exit
|
49
|
+
end
|
50
|
+
opts.on_tail("--version", "Show version") do
|
51
|
+
puts At_email::VERSION
|
52
|
+
exit
|
53
|
+
end
|
54
|
+
end
|
55
|
+
opt_parser.parse!(args)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
class At_email::Config::Config_File
|
5
|
+
|
6
|
+
def get_config()
|
7
|
+
|
8
|
+
if File.exist?($options.config_file)
|
9
|
+
contents = File.read($options.config_file)
|
10
|
+
config = JSON.parse(contents, symbolize_names: true)
|
11
|
+
else
|
12
|
+
raise "Config file does not exist: " + $options.config_file
|
13
|
+
end
|
14
|
+
|
15
|
+
default_config_file_path = $app_path + '/' + At_email::DEFAULT_CONFIG_FILE
|
16
|
+
if File.exist?(default_config_file_path)
|
17
|
+
default_config_contents = File.read(default_config_file_path)
|
18
|
+
default_config = JSON.parse(default_config_contents, symbolize_names: true)
|
19
|
+
else
|
20
|
+
raise "Default config file does not exist: " + default_config_file_path
|
21
|
+
end
|
22
|
+
|
23
|
+
config.each do |key, value|
|
24
|
+
if !default_config[key]
|
25
|
+
raise 'Config Error: Property: ' + key.to_s + ' is not a valid configuration option for this system'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
default_config.each do |key, data|
|
30
|
+
if !config[key] && data[:value]
|
31
|
+
config[key] = data[:value]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
default_config.each do |key, data|
|
36
|
+
if config[key]
|
37
|
+
if data[:type]
|
38
|
+
if data[:type] === 'boolean'
|
39
|
+
if ![true, false].include? config[key]
|
40
|
+
raise 'Config Error: Property: ' + key.to_s + ' is not type: boolean - config value: ' + config[key].to_s
|
41
|
+
end
|
42
|
+
end
|
43
|
+
if data[:type] === 'numeric'
|
44
|
+
if !config[key].is_a? Numeric
|
45
|
+
raise 'Config Error: Property: ' + key.to_s + ' is not type: numeric - config value: ' + config[key].to_s
|
46
|
+
end
|
47
|
+
if data[:min_value]
|
48
|
+
if config[key] < data[:min_value]
|
49
|
+
raise 'Config Error: Property: ' + key.to_s + ' is below minimum value: ' + data[:min_value].to_s + ' - config value: ' + config[key].to_s
|
50
|
+
end
|
51
|
+
end
|
52
|
+
if data[:max_value]
|
53
|
+
if config[key] > data[:max_value]
|
54
|
+
raise 'Config Error: Property: ' + key.to_s + ' is above maximum value: ' + data[:max_value].to_s + ' - config value: ' + config[key].to_s
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
if data[:type] === 'string'
|
59
|
+
if !config[key].is_a? String
|
60
|
+
raise 'Config Error: Property: ' + key.to_s + ' is not type: string - value: ' + config[key].to_s
|
61
|
+
end
|
62
|
+
if data[:min_length]
|
63
|
+
if config[key].length < data[:min_length]
|
64
|
+
raise 'Config Error: Property: ' + key.to_s + ' is below minimum lenth: ' + data[:min_length].to_s + ' - config value: ' + config[key].to_s
|
65
|
+
end
|
66
|
+
end
|
67
|
+
if data[:max_length]
|
68
|
+
if config[key].length > data[:max_length]
|
69
|
+
raise 'Config Error: Property: ' + key.to_s + ' is above minimum lenth: ' + data[:max_length].to_s + ' - config value: ' + config[key].to_s
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
if data[:type] === 'path'
|
74
|
+
if data[:path_type]
|
75
|
+
if data[:path_type] === 'dir'
|
76
|
+
if !Dir.exists?(config[key].to_s)
|
77
|
+
raise 'Config Error: Property: ' + key.to_s + ' is not a directory path - config value: ' + config[key].to_s
|
78
|
+
end
|
79
|
+
end
|
80
|
+
if data[:path_type] === 'file'
|
81
|
+
if !File.exists?(config[key].to_s)
|
82
|
+
raise 'Config Error: Property: ' + key.to_s + ' is not a file path - config value: ' + config[key].to_s
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
output = {}
|
92
|
+
config.sort_by { |k, v| k }.each do |key, value|
|
93
|
+
output[key] = value
|
94
|
+
end
|
95
|
+
|
96
|
+
return output
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|