aspera-cli 4.24.1 → 4.25.0.pre
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +1064 -745
- data/CONTRIBUTING.md +43 -100
- data/README.md +1281 -720
- data/bin/ascli +20 -1
- data/bin/asession +23 -27
- data/lib/aspera/agent/base.rb +10 -21
- data/lib/aspera/agent/connect.rb +2 -3
- data/lib/aspera/agent/desktop.rb +2 -2
- data/lib/aspera/agent/direct.rb +49 -32
- data/lib/aspera/agent/factory.rb +31 -0
- data/lib/aspera/api/aoc.rb +134 -76
- data/lib/aspera/api/cos_node.rb +3 -2
- data/lib/aspera/api/faspex.rb +213 -0
- data/lib/aspera/api/node.rb +107 -94
- data/lib/aspera/ascmd.rb +1 -2
- data/lib/aspera/ascp/installation.rb +73 -58
- data/lib/aspera/ascp/management.rb +119 -23
- data/lib/aspera/assert.rb +39 -11
- data/lib/aspera/cli/error.rb +4 -2
- data/lib/aspera/cli/extended_value.rb +91 -67
- data/lib/aspera/cli/formatter.rb +62 -27
- data/lib/aspera/cli/hints.rb +8 -0
- data/lib/aspera/cli/info.rb +4 -4
- data/lib/aspera/cli/main.rb +76 -84
- data/lib/aspera/cli/manager.rb +352 -248
- data/lib/aspera/cli/plugins/alee.rb +5 -4
- data/lib/aspera/cli/plugins/aoc.rb +175 -195
- data/lib/aspera/cli/plugins/ats.rb +4 -4
- data/lib/aspera/cli/plugins/base.rb +343 -0
- data/lib/aspera/cli/plugins/basic_auth.rb +45 -0
- data/lib/aspera/cli/plugins/config.rb +283 -269
- data/lib/aspera/cli/plugins/console.rb +27 -22
- data/lib/aspera/cli/plugins/cos.rb +3 -3
- data/lib/aspera/cli/plugins/factory.rb +78 -0
- data/lib/aspera/cli/plugins/faspex.rb +49 -46
- data/lib/aspera/cli/plugins/faspex5.rb +113 -225
- data/lib/aspera/cli/plugins/faspio.rb +19 -18
- data/lib/aspera/cli/plugins/httpgw.rb +14 -13
- data/lib/aspera/cli/plugins/node.rb +162 -149
- data/lib/aspera/cli/plugins/oauth.rb +48 -0
- data/lib/aspera/cli/plugins/orchestrator.rb +129 -45
- data/lib/aspera/cli/plugins/preview.rb +30 -50
- data/lib/aspera/cli/plugins/server.rb +21 -21
- data/lib/aspera/cli/plugins/shares.rb +45 -47
- data/lib/aspera/cli/sync_actions.rb +50 -39
- data/lib/aspera/cli/transfer_agent.rb +35 -49
- data/lib/aspera/cli/transfer_progress.rb +6 -6
- data/lib/aspera/cli/version.rb +3 -3
- data/lib/aspera/cli/wizard.rb +70 -55
- data/lib/aspera/colors.rb +6 -0
- data/lib/aspera/command_line_builder.rb +59 -61
- data/lib/aspera/command_line_converter.rb +2 -1
- data/lib/aspera/coverage.rb +2 -2
- data/lib/aspera/data_repository.rb +1 -1
- data/lib/aspera/environment.rb +51 -41
- data/lib/aspera/faspex_gw.rb +7 -5
- data/lib/aspera/faspex_postproc.rb +1 -1
- data/lib/aspera/keychain/factory.rb +1 -2
- data/lib/aspera/keychain/macos_security.rb +1 -1
- data/lib/aspera/log.rb +37 -9
- data/lib/aspera/markdown.rb +31 -0
- data/lib/aspera/nagios.rb +7 -6
- data/lib/aspera/oauth/base.rb +25 -28
- data/lib/aspera/oauth/factory.rb +9 -9
- data/lib/aspera/oauth/url_json.rb +2 -1
- data/lib/aspera/oauth/web.rb +2 -2
- data/lib/aspera/preview/file_types.rb +23 -37
- data/lib/aspera/products/connect.rb +7 -6
- data/lib/aspera/products/desktop.rb +1 -4
- data/lib/aspera/products/other.rb +9 -1
- data/lib/aspera/products/transferd.rb +0 -1
- data/lib/aspera/rest.rb +168 -113
- data/lib/aspera/rest_error_analyzer.rb +4 -4
- data/lib/aspera/ssh.rb +7 -4
- data/lib/aspera/ssl.rb +41 -0
- data/lib/aspera/sync/args.schema.yaml +46 -3
- data/lib/aspera/sync/conf.schema.yaml +307 -123
- data/lib/aspera/sync/database.rb +2 -1
- data/lib/aspera/sync/operations.rb +135 -79
- data/lib/aspera/temp_file_manager.rb +17 -5
- data/lib/aspera/transfer/error.rb +16 -7
- data/lib/aspera/transfer/parameters.rb +35 -22
- data/lib/aspera/transfer/resumer.rb +74 -0
- data/lib/aspera/transfer/spec.rb +5 -5
- data/lib/aspera/transfer/spec.schema.yaml +170 -59
- data/lib/aspera/transfer/spec_doc.rb +49 -43
- data/lib/aspera/uri_reader.rb +2 -2
- data/lib/aspera/web_auth.rb +6 -6
- data/lib/transferd_pb.rb +2 -2
- data.tar.gz.sig +0 -0
- metadata +26 -11
- metadata.gz.sig +0 -0
- data/lib/aspera/cli/basic_auth_plugin.rb +0 -43
- data/lib/aspera/cli/plugin.rb +0 -333
- data/lib/aspera/cli/plugin_factory.rb +0 -81
- data/lib/aspera/resumer.rb +0 -77
- data/lib/aspera/transfer/error_info.rb +0 -91
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# cspell:ignore initdemo genkey pubkey asperasoft filelists
|
|
4
|
-
require 'aspera/cli/
|
|
4
|
+
require 'aspera/cli/plugins/basic_auth'
|
|
5
|
+
require 'aspera/cli/plugins/factory'
|
|
5
6
|
require 'aspera/cli/extended_value'
|
|
6
7
|
require 'aspera/cli/special_values'
|
|
7
8
|
require 'aspera/cli/version'
|
|
@@ -9,9 +10,10 @@ require 'aspera/cli/formatter'
|
|
|
9
10
|
require 'aspera/cli/info'
|
|
10
11
|
require 'aspera/cli/transfer_progress'
|
|
11
12
|
require 'aspera/cli/wizard'
|
|
13
|
+
require 'aspera/cli/sync_actions'
|
|
12
14
|
require 'aspera/ascp/installation'
|
|
15
|
+
require 'aspera/sync/operations'
|
|
13
16
|
require 'aspera/products/transferd'
|
|
14
|
-
require 'aspera/transfer/error_info'
|
|
15
17
|
require 'aspera/transfer/parameters'
|
|
16
18
|
require 'aspera/transfer/spec'
|
|
17
19
|
require 'aspera/transfer/spec_doc'
|
|
@@ -28,6 +30,7 @@ require 'aspera/oauth/jwt'
|
|
|
28
30
|
require 'aspera/log'
|
|
29
31
|
require 'aspera/assert'
|
|
30
32
|
require 'aspera/oauth'
|
|
33
|
+
require 'aspera/ssl'
|
|
31
34
|
require 'openssl'
|
|
32
35
|
require 'open3'
|
|
33
36
|
require 'date'
|
|
@@ -36,93 +39,36 @@ require 'erb'
|
|
|
36
39
|
module Aspera
|
|
37
40
|
module Cli
|
|
38
41
|
module Plugins
|
|
39
|
-
#
|
|
40
|
-
class Config <
|
|
41
|
-
|
|
42
|
-
ASPERA_HOME_FOLDER_NAME = '.aspera'
|
|
43
|
-
# default config file
|
|
44
|
-
DEFAULT_CONFIG_FILENAME = 'config.yaml'
|
|
45
|
-
# reserved preset names
|
|
46
|
-
CONF_PRESET_CONFIG = 'config'
|
|
47
|
-
CONF_PRESET_VERSION = 'version'
|
|
48
|
-
CONF_PRESET_DEFAULTS = 'default'
|
|
49
|
-
CONF_PRESET_GLOBAL = 'global_common_defaults'
|
|
50
|
-
# special name to identify value of default
|
|
51
|
-
GLOBAL_DEFAULT_KEYWORD = 'GLOBAL'
|
|
52
|
-
CONF_GLOBAL_SYM = :config
|
|
53
|
-
# folder containing custom plugins in user's config folder
|
|
54
|
-
ASPERA_PLUGINS_FOLDERNAME = 'plugins'
|
|
55
|
-
PERSISTENCY_FOLDER = 'persist_store'
|
|
56
|
-
ASPERA = 'aspera'
|
|
57
|
-
SERVER_COMMAND = 'server'
|
|
58
|
-
DIR_SDK = 'sdk'
|
|
59
|
-
DEMO_SERVER = 'demo'
|
|
60
|
-
DEMO_PRESET = 'demoserver' # cspell: disable-line
|
|
61
|
-
EMAIL_TEST_TEMPLATE = <<~END_OF_TEMPLATE
|
|
62
|
-
From: <%=from_name%> <<%=from_email%>>
|
|
63
|
-
To: <<%=to%>>
|
|
64
|
-
Subject: #{Info::GEM_NAME} email test
|
|
65
|
-
|
|
66
|
-
This email was sent to test #{Info::CMD_NAME}.
|
|
67
|
-
END_OF_TEMPLATE
|
|
68
|
-
# special extended values
|
|
69
|
-
EXTEND_PRESET = :preset
|
|
70
|
-
EXTEND_VAULT = :vault
|
|
71
|
-
PRESET_DIG_SEPARATOR = '.'
|
|
72
|
-
DEFAULT_CHECK_NEW_VERSION_DAYS = 7
|
|
73
|
-
COFFEE_IMAGE_URL = 'https://enjoyjava.com/wp-content/uploads/2018/01/How-to-make-strong-coffee.jpg'
|
|
74
|
-
GEM_CHECK_DATE_FMT = '%Y/%m/%d'
|
|
75
|
-
# for testing only
|
|
76
|
-
SELF_SIGNED_CERT = OpenSSL::SSL.const_get(:enon_yfirev.to_s.upcase.reverse) # cspell: disable-line
|
|
77
|
-
CONF_OVERVIEW_KEYS = %w[preset parameter value].freeze
|
|
78
|
-
SMTP_CONF_PARAMS = %i[server tls ssl port domain username password from_name from_email].freeze
|
|
79
|
-
private_constant :DEFAULT_CONFIG_FILENAME,
|
|
80
|
-
:CONF_PRESET_CONFIG,
|
|
81
|
-
:CONF_PRESET_VERSION,
|
|
82
|
-
:CONF_PRESET_DEFAULTS,
|
|
83
|
-
:CONF_PRESET_GLOBAL,
|
|
84
|
-
:ASPERA_PLUGINS_FOLDERNAME,
|
|
85
|
-
:ASPERA,
|
|
86
|
-
:DEMO_SERVER,
|
|
87
|
-
:DEMO_PRESET,
|
|
88
|
-
:EMAIL_TEST_TEMPLATE,
|
|
89
|
-
:EXTEND_PRESET,
|
|
90
|
-
:EXTEND_VAULT,
|
|
91
|
-
:DEFAULT_CHECK_NEW_VERSION_DAYS,
|
|
92
|
-
:SERVER_COMMAND,
|
|
93
|
-
:PRESET_DIG_SEPARATOR,
|
|
94
|
-
:COFFEE_IMAGE_URL,
|
|
95
|
-
:SELF_SIGNED_CERT,
|
|
96
|
-
:PERSISTENCY_FOLDER,
|
|
97
|
-
:CONF_OVERVIEW_KEYS,
|
|
98
|
-
:SMTP_CONF_PARAMS
|
|
42
|
+
# Manage the CLI config file
|
|
43
|
+
class Config < Base
|
|
44
|
+
include SyncActions
|
|
99
45
|
|
|
100
46
|
class << self
|
|
101
|
-
#
|
|
47
|
+
# Folder containing plugins in the gem's main folder
|
|
102
48
|
def gem_plugins_folder
|
|
103
49
|
File.dirname(File.expand_path(__FILE__))
|
|
104
50
|
end
|
|
105
51
|
|
|
106
52
|
# @return main folder where code is, i.e. .../lib
|
|
107
|
-
#
|
|
53
|
+
# Go up as many times as englobing modules (not counting class, as it is a file)
|
|
108
54
|
def gem_src_root
|
|
109
55
|
# Module.nesting[2] is Cli::Plugins
|
|
110
56
|
File.expand_path(Module.nesting[2].to_s.gsub('::', '/').gsub(%r{[^/]+}, '..'), gem_plugins_folder)
|
|
111
57
|
end
|
|
112
58
|
|
|
113
|
-
#
|
|
59
|
+
# Deep clone hash so that it does not get modified in case of display and secret hide
|
|
114
60
|
def deep_clone(val)
|
|
115
61
|
return Marshal.load(Marshal.dump(val))
|
|
116
62
|
end
|
|
117
63
|
|
|
118
|
-
# return product family folder (~/.aspera)
|
|
64
|
+
# @return product family folder (~/.aspera)
|
|
119
65
|
def module_family_folder
|
|
120
66
|
user_home_folder = Dir.home
|
|
121
67
|
Aspera.assert(Dir.exist?(user_home_folder), type: Cli::Error){"Home folder does not exist: #{user_home_folder}. Check your user environment."}
|
|
122
68
|
return File.join(user_home_folder, ASPERA_HOME_FOLDER_NAME)
|
|
123
69
|
end
|
|
124
70
|
|
|
125
|
-
# return
|
|
71
|
+
# @return [String] Product config folder (~/.aspera/<name>)
|
|
126
72
|
def default_app_main_folder(app_name:)
|
|
127
73
|
Aspera.assert_type(app_name, String)
|
|
128
74
|
Aspera.assert(!app_name.empty?)
|
|
@@ -131,7 +77,7 @@ module Aspera
|
|
|
131
77
|
end
|
|
132
78
|
|
|
133
79
|
def initialize(**_)
|
|
134
|
-
#
|
|
80
|
+
# We need to defer parsing of options until we have the config file, so we can use @extend with @preset
|
|
135
81
|
super
|
|
136
82
|
@use_plugin_defaults = true
|
|
137
83
|
@config_presets = nil
|
|
@@ -147,96 +93,79 @@ module Aspera
|
|
|
147
93
|
@option_cache_tokens = true
|
|
148
94
|
@main_folder = nil
|
|
149
95
|
@option_config_file = nil
|
|
150
|
-
#
|
|
96
|
+
# Store is used for ruby https (OpenSSL::X509::Store)
|
|
151
97
|
@certificate_store = nil
|
|
152
|
-
#
|
|
98
|
+
# Paths are used for ascp
|
|
153
99
|
@certificate_paths = nil
|
|
154
100
|
@progress_bar = nil
|
|
155
|
-
#
|
|
101
|
+
# Option to set main folder
|
|
156
102
|
options.declare(
|
|
157
103
|
:home, 'Home folder for tool',
|
|
158
104
|
handler: {o: self, m: :main_folder},
|
|
159
|
-
types: String,
|
|
160
105
|
default: self.class.default_app_main_folder(app_name: Info::CMD_NAME)
|
|
161
106
|
)
|
|
162
107
|
options.parse_options!
|
|
163
108
|
Log.log.debug{"#{Info::CMD_NAME} folder: #{@main_folder}"}
|
|
164
|
-
#
|
|
109
|
+
# Data persistency manager, created by config plugin, set for global object
|
|
165
110
|
context.persistency = PersistencyFolder.new(File.join(@main_folder, PERSISTENCY_FOLDER))
|
|
166
|
-
#
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
#
|
|
111
|
+
# Set folders for plugin lookup
|
|
112
|
+
Plugins::Factory.instance.add_lookup_folder(self.class.gem_plugins_folder)
|
|
113
|
+
Plugins::Factory.instance.add_lookup_folder(File.join(@main_folder, ASPERA_PLUGINS_FOLDERNAME))
|
|
114
|
+
# Option to set config file
|
|
170
115
|
options.declare(
|
|
171
116
|
:config_file, 'Path to YAML file with preset configuration',
|
|
172
117
|
handler: {o: self, m: :option_config_file},
|
|
173
118
|
default: File.join(@main_folder, DEFAULT_CONFIG_FILENAME)
|
|
174
119
|
)
|
|
175
120
|
options.parse_options!
|
|
176
|
-
#
|
|
121
|
+
# Read config file (set @config_presets)
|
|
177
122
|
read_config_file
|
|
178
|
-
#
|
|
179
|
-
ExtendedValue.instance.
|
|
180
|
-
ExtendedValue.instance.
|
|
181
|
-
|
|
123
|
+
# Add preset handler (needed for smtp)
|
|
124
|
+
ExtendedValue.instance.on(EXTEND_PRESET){ |v| preset_by_name(v)}
|
|
125
|
+
ExtendedValue.instance.on(EXTEND_VAULT){ |v| vault_value(v)}
|
|
126
|
+
ExtendedValue.instance.on(EXTEND_ARGS){ |v| options.args_as_extended(v)}
|
|
127
|
+
# Load defaults before it can be overridden
|
|
182
128
|
add_plugin_default_preset(CONF_GLOBAL_SYM)
|
|
183
|
-
#
|
|
129
|
+
# Vault options
|
|
184
130
|
options.declare(:secret, 'Secret for access keys')
|
|
185
|
-
options.declare(:vault, 'Vault for secrets',
|
|
131
|
+
options.declare(:vault, 'Vault for secrets', allowed: Hash)
|
|
186
132
|
options.declare(:vault_password, 'Vault password')
|
|
187
133
|
options.parse_options!
|
|
188
|
-
#
|
|
189
|
-
|
|
190
|
-
#
|
|
191
|
-
options.declare(:no_default, 'Do not load default configuration for plugin',
|
|
134
|
+
# Declare generic plugin options only after handlers are declared
|
|
135
|
+
Base.declare_options(options)
|
|
136
|
+
# Configuration options
|
|
137
|
+
options.declare(:no_default, 'Do not load default configuration for plugin', allowed: Allowed::TYPES_NONE, short: 'N'){@use_plugin_defaults = false}
|
|
192
138
|
options.declare(:preset, 'Load the named option preset from current config file', short: 'P', handler: {o: self, m: :option_preset})
|
|
193
|
-
options.declare(:version_check_days, 'Period in days to check new version (zero to disable)',
|
|
139
|
+
options.declare(:version_check_days, 'Period in days to check new version (zero to disable)', allowed: Allowed::TYPES_INTEGER, default: DEFAULT_CHECK_NEW_VERSION_DAYS)
|
|
194
140
|
options.declare(:plugin_folder, 'Folder where to find additional plugins', handler: {o: self, m: :option_plugin_folder})
|
|
195
|
-
#
|
|
141
|
+
# Declare wizard options
|
|
196
142
|
@wizard = Wizard.new(self, @main_folder)
|
|
197
143
|
# Transfer SDK options
|
|
198
|
-
options.declare(:ascp_path, 'Ascp: Path to ascp', handler: {o: Ascp::Installation.instance, m: :ascp_path})
|
|
199
|
-
options.declare(:use_product, 'Ascp: Use ascp from specified product', handler: {o: self, m: :option_use_product})
|
|
200
144
|
options.declare(:sdk_url, 'Ascp: URL to get Aspera Transfer Executables', default: SpecialValues::DEF)
|
|
201
|
-
options.
|
|
202
|
-
|
|
203
|
-
options.declare(:
|
|
204
|
-
|
|
205
|
-
options.declare(:
|
|
145
|
+
options.parse_options!
|
|
146
|
+
set_sdk_dir
|
|
147
|
+
options.declare(:ascp_path, 'Ascp: Path to ascp (or product with "product:")', handler: {o: Ascp::Installation.instance, m: :ascp_path}, default: "#{Ascp::Installation::USE_PRODUCT_PREFIX}#{Ascp::Installation::FIRST_FOUND}")
|
|
148
|
+
options.declare(:locations_url, 'Ascp: URL to get download locations of Aspera Transfer Daemon', handler: {o: Ascp::Installation.instance, m: :transferd_urls})
|
|
149
|
+
options.declare(:sdk_folder, 'Ascp: SDK installation folder path', handler: {o: Products::Transferd, m: :sdk_directory})
|
|
150
|
+
options.declare(:progress_bar, 'Display progress bar', allowed: Allowed::TYPES_BOOLEAN, default: Environment.terminal?)
|
|
151
|
+
# Email options
|
|
152
|
+
options.declare(:smtp, 'Email: SMTP configuration', allowed: Hash)
|
|
206
153
|
options.declare(:notify_to, 'Email: Recipient for notification of transfers')
|
|
207
154
|
options.declare(:notify_template, 'Email: ERB template for notification of transfers')
|
|
208
155
|
# HTTP options
|
|
209
|
-
options.declare(:insecure, 'HTTP/S: Do not validate any certificate',
|
|
210
|
-
options.declare(:ignore_certificate, 'HTTP/S: Do not validate certificate for these URLs',
|
|
211
|
-
options.declare(:warn_insecure, 'HTTP/S: Issue a warning if certificate is ignored',
|
|
212
|
-
options.declare(:cert_stores, 'HTTP/S: List of folder with trusted certificates',
|
|
213
|
-
options.declare(:http_options, 'HTTP/S: Options for HTTP/S socket',
|
|
214
|
-
options.declare(:http_proxy, 'HTTP/S: URL for proxy with optional credentials',
|
|
215
|
-
options.declare(:cache_tokens, 'Save and reuse OAuth tokens',
|
|
156
|
+
options.declare(:insecure, 'HTTP/S: Do not validate any certificate', allowed: Allowed::TYPES_BOOLEAN, handler: {o: self, m: :option_insecure}, default: false)
|
|
157
|
+
options.declare(:ignore_certificate, 'HTTP/S: Do not validate certificate for these URLs', allowed: [Array, NilClass], handler: {o: self, m: :option_ignore_cert_host_port})
|
|
158
|
+
options.declare(:warn_insecure, 'HTTP/S: Issue a warning if certificate is ignored', allowed: Allowed::TYPES_BOOLEAN, handler: {o: self, m: :option_warn_insecure_cert}, default: true)
|
|
159
|
+
options.declare(:cert_stores, 'HTTP/S: List of folder with trusted certificates', allowed: Allowed::TYPES_STRING_ARRAY, handler: {o: self, m: :trusted_cert_locations})
|
|
160
|
+
options.declare(:http_options, 'HTTP/S: Options for HTTP/S socket', allowed: Hash, handler: {o: self, m: :option_http_options}, default: {})
|
|
161
|
+
options.declare(:http_proxy, 'HTTP/S: URL for proxy with optional credentials', handler: {o: self, m: :option_http_proxy})
|
|
162
|
+
options.declare(:cache_tokens, 'Save and reuse OAuth tokens', allowed: Allowed::TYPES_BOOLEAN, handler: {o: self, m: :option_cache_tokens})
|
|
216
163
|
options.declare(:fpac, 'Proxy auto configuration script')
|
|
217
|
-
options.declare(:proxy_credentials, 'HTTP proxy credentials for fpac: user, password',
|
|
164
|
+
options.declare(:proxy_credentials, 'HTTP proxy credentials for fpac: user, password', allowed: [Array, NilClass])
|
|
218
165
|
options.parse_options!
|
|
219
166
|
@progress_bar = TransferProgress.new if options.get_option(:progress_bar)
|
|
220
|
-
# Check SDK folder is set or not, for compatibility, we check in two places
|
|
221
|
-
sdk_dir = Products::Transferd.sdk_directory rescue nil
|
|
222
|
-
if sdk_dir.nil?
|
|
223
|
-
@sdk_default_location = true
|
|
224
|
-
Log.log.debug('SDK folder is not set, checking default')
|
|
225
|
-
# new location
|
|
226
|
-
sdk_dir = self.class.default_app_main_folder(app_name: DIR_SDK)
|
|
227
|
-
Log.log.debug{"checking: #{sdk_dir}"}
|
|
228
|
-
if !Dir.exist?(sdk_dir)
|
|
229
|
-
Log.log.debug{"not exists: #{sdk_dir}"}
|
|
230
|
-
# former location
|
|
231
|
-
former_sdk_folder = File.join(self.class.default_app_main_folder(app_name: Info::CMD_NAME), DIR_SDK)
|
|
232
|
-
Log.log.debug{"checking: #{former_sdk_folder}"}
|
|
233
|
-
sdk_dir = former_sdk_folder if Dir.exist?(former_sdk_folder)
|
|
234
|
-
end
|
|
235
|
-
Log.log.debug{"using: #{sdk_dir}"}
|
|
236
|
-
Products::Transferd.sdk_directory = sdk_dir
|
|
237
|
-
end
|
|
238
167
|
pac_script = options.get_option(:fpac)
|
|
239
|
-
#
|
|
168
|
+
# Create PAC executor
|
|
240
169
|
if !pac_script.nil?
|
|
241
170
|
@pac_exec = ProxyAutoConfig.new(pac_script).register_uri_generic
|
|
242
171
|
proxy_user_pass = options.get_option(:proxy_credentials)
|
|
@@ -249,27 +178,58 @@ module Aspera
|
|
|
249
178
|
RestParameters.instance.user_agent = Info::CMD_NAME
|
|
250
179
|
RestParameters.instance.progress_bar = @progress_bar
|
|
251
180
|
RestParameters.instance.session_cb = lambda{ |http_session| update_http_session(http_session)}
|
|
252
|
-
|
|
181
|
+
# Check http options that are global
|
|
182
|
+
keys_to_delete = []
|
|
183
|
+
@option_http_options.each do |k, v|
|
|
253
184
|
method = "#{k}=".to_sym
|
|
254
|
-
RestParameters.instance.
|
|
255
|
-
|
|
185
|
+
if RestParameters.instance.respond_to?(method)
|
|
186
|
+
keys_to_delete.push(k)
|
|
187
|
+
RestParameters.instance.send(method, v)
|
|
188
|
+
elsif k.eql?('ssl_options')
|
|
189
|
+
keys_to_delete.push(k)
|
|
190
|
+
Aspera::SSL.option_list = v
|
|
191
|
+
elsif OAuth::Factory.instance.parameters.key?(k.to_sym)
|
|
192
|
+
keys_to_delete.push(k)
|
|
193
|
+
OAuth::Factory.instance.parameters[k.to_sym] = v
|
|
194
|
+
end
|
|
256
195
|
end
|
|
196
|
+
keys_to_delete.each{ |k| @option_http_options.delete(k)}
|
|
257
197
|
OAuth::Factory.instance.persist_mgr = persistency if @option_cache_tokens
|
|
258
|
-
OAuth::Web.
|
|
198
|
+
OAuth::Web.additional_info = "#{Info::CMD_NAME} v#{Cli::VERSION}"
|
|
259
199
|
Transfer::Parameters.file_list_folder = File.join(@main_folder, 'filelists')
|
|
260
200
|
RestErrorAnalyzer.instance.log_file = File.join(@main_folder, 'rest_exceptions.log')
|
|
261
|
-
#
|
|
201
|
+
# Register aspera REST call error handlers
|
|
262
202
|
RestErrorsAspera.register_handlers
|
|
263
203
|
end
|
|
264
204
|
|
|
265
205
|
attr_accessor :main_folder, :option_cache_tokens, :option_insecure, :option_warn_insecure_cert, :option_http_options
|
|
266
206
|
attr_reader :option_ignore_cert_host_port, :progress_bar
|
|
267
207
|
|
|
268
|
-
|
|
269
|
-
|
|
208
|
+
def set_sdk_dir
|
|
209
|
+
# Check SDK folder is set or not, for compatibility, we check in two places
|
|
210
|
+
sdk_dir = Products::Transferd.sdk_directory rescue nil
|
|
211
|
+
if sdk_dir.nil?
|
|
212
|
+
@sdk_default_location = true
|
|
213
|
+
Log.log.debug('SDK folder is not set, checking default')
|
|
214
|
+
# New location
|
|
215
|
+
sdk_dir = self.class.default_app_main_folder(app_name: TRANSFERD_APP_NAME)
|
|
216
|
+
Log.log.debug{"Checking: #{sdk_dir}"}
|
|
217
|
+
if !Dir.exist?(sdk_dir)
|
|
218
|
+
Log.log.debug{"No such folder: #{sdk_dir}"}
|
|
219
|
+
# Former location
|
|
220
|
+
former_sdk_folder = File.join(self.class.default_app_main_folder(app_name: Info::CMD_NAME), TRANSFERD_APP_NAME)
|
|
221
|
+
Log.log.debug{"Checking: #{former_sdk_folder}"}
|
|
222
|
+
sdk_dir = former_sdk_folder if Dir.exist?(former_sdk_folder)
|
|
223
|
+
end
|
|
224
|
+
Log.log.debug{"Using: #{sdk_dir}"}
|
|
225
|
+
Products::Transferd.sdk_directory = sdk_dir
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Add files, folders or default locations to the certificate store
|
|
230
|
+
# @param path_list [Array<String>] List of paths to add
|
|
270
231
|
# @return the list of paths
|
|
271
232
|
def trusted_cert_locations=(path_list)
|
|
272
|
-
path_list = [path_list] unless path_list.is_a?(Array)
|
|
273
233
|
Aspera.assert_type(path_list, Array){'cert locations'}
|
|
274
234
|
if @certificate_store.nil?
|
|
275
235
|
Log.log.debug('Creating SSL Cert store')
|
|
@@ -300,6 +260,7 @@ module Aspera
|
|
|
300
260
|
pp = Dir.entries(p)
|
|
301
261
|
.map{ |e| File.realpath(File.join(p, e))}
|
|
302
262
|
.select{ |entry| File.file?(entry)}
|
|
263
|
+
.select{ |entry| CERT_EXT.any?{ |ext| entry.end_with?(ext)}}
|
|
303
264
|
end
|
|
304
265
|
@certificate_paths.concat(pp)
|
|
305
266
|
end
|
|
@@ -307,14 +268,14 @@ module Aspera
|
|
|
307
268
|
@certificate_paths.uniq!
|
|
308
269
|
end
|
|
309
270
|
|
|
310
|
-
#
|
|
271
|
+
# @return only files
|
|
311
272
|
def trusted_cert_locations
|
|
312
273
|
locations = @certificate_paths
|
|
313
274
|
if locations.nil?
|
|
314
|
-
#
|
|
315
|
-
self.trusted_cert_locations = SpecialValues::DEF
|
|
275
|
+
# Compute default locations
|
|
276
|
+
self.trusted_cert_locations = [SpecialValues::DEF]
|
|
316
277
|
locations = @certificate_paths
|
|
317
|
-
#
|
|
278
|
+
# Restore defaults
|
|
318
279
|
@certificate_paths = @certificate_store = nil
|
|
319
280
|
end
|
|
320
281
|
return locations
|
|
@@ -357,7 +318,7 @@ module Aspera
|
|
|
357
318
|
return ignore_cert
|
|
358
319
|
end
|
|
359
320
|
|
|
360
|
-
#
|
|
321
|
+
# Called every time a new REST HTTP session is opened to set user-provided options
|
|
361
322
|
# @param http_session [Net::HTTP] the newly created HTTP/S session object
|
|
362
323
|
def update_http_session(http_session)
|
|
363
324
|
http_session.set_debug_output(LineLogger.new(:trace2)) if Log.instance.logger.trace2?
|
|
@@ -367,38 +328,12 @@ module Aspera
|
|
|
367
328
|
Log.log.debug{"Using cert store #{http_session.cert_store} (#{@certificate_store})"} unless http_session.cert_store.nil?
|
|
368
329
|
@option_http_options.each do |k, v|
|
|
369
330
|
method = "#{k}=".to_sym
|
|
370
|
-
#
|
|
331
|
+
# Check if accessor is a method of Net::HTTP
|
|
371
332
|
# continue_timeout= read_timeout= write_timeout=
|
|
372
333
|
if http_session.respond_to?(method)
|
|
373
334
|
http_session.send(method, v)
|
|
374
|
-
elsif k.eql?('ssl_options')
|
|
375
|
-
# NOTE: here is a hack that allows setting SSLContext options
|
|
376
|
-
Aspera.assert_type(v, Array){'ssl_options'}
|
|
377
|
-
# more dynamic method, but more complex:
|
|
378
|
-
# Net::HTTP::SSL_ATTRIBUTES.push(:options) unless Net::HTTP::SSL_ATTRIBUTES.include?(:options)
|
|
379
|
-
# Net::HTTP::SSL_IVNAMES.push(:@options) unless Net::HTTP::SSL_IVNAMES.include?(:@options)
|
|
380
|
-
# Start with default options
|
|
381
|
-
ssl_options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options]
|
|
382
|
-
v.each do |opt|
|
|
383
|
-
case opt
|
|
384
|
-
when Integer
|
|
385
|
-
ssl_options = opt
|
|
386
|
-
when String
|
|
387
|
-
name = "OP_#{opt.start_with?('-') ? opt[1..] : opt}".upcase
|
|
388
|
-
raise Cli::BadArgument, "No such ssl_option: #{name}, use one of: #{OpenSSL::SSL.constants.grep(/^OP_/).map{ |c| c.to_s.sub(/^OP_/, '')}.join(', ')}" if !OpenSSL::SSL.const_defined?(name)
|
|
389
|
-
if opt.start_with?('-')
|
|
390
|
-
ssl_options &= ~OpenSSL::SSL.const_get(name)
|
|
391
|
-
else
|
|
392
|
-
ssl_options |= OpenSSL::SSL.const_get(name)
|
|
393
|
-
end
|
|
394
|
-
else
|
|
395
|
-
Aspera.error_unexpected_value(opt.class.name){'Expected String or Integer in ssl_options'}
|
|
396
|
-
end
|
|
397
|
-
end
|
|
398
|
-
# http_session.instance_variable_set(:@options, ssl_options)
|
|
399
|
-
OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options] = ssl_options
|
|
400
335
|
else
|
|
401
|
-
Log.log.error{"
|
|
336
|
+
Log.log.error{"Unknown HTTP session attribute: #{k}"}
|
|
402
337
|
end
|
|
403
338
|
end
|
|
404
339
|
end
|
|
@@ -426,35 +361,35 @@ module Aspera
|
|
|
426
361
|
end
|
|
427
362
|
|
|
428
363
|
def periodic_check_newer_gem_version
|
|
429
|
-
#
|
|
364
|
+
# Get verification period
|
|
430
365
|
delay_days = options.get_option(:version_check_days, mandatory: true).to_i
|
|
431
|
-
#
|
|
366
|
+
# Check only if not zero day
|
|
432
367
|
return if delay_days.eql?(0)
|
|
433
|
-
#
|
|
368
|
+
# Get last date from persistency
|
|
434
369
|
last_check_array = []
|
|
435
370
|
check_date_persist = PersistencyActionOnce.new(
|
|
436
371
|
manager: persistency,
|
|
437
372
|
data: last_check_array,
|
|
438
373
|
id: 'version_last_check'
|
|
439
374
|
)
|
|
440
|
-
#
|
|
375
|
+
# Get persisted date or nil
|
|
441
376
|
current_date = Date.today
|
|
442
377
|
last_check_days = (current_date - Date.strptime(last_check_array.first, GEM_CHECK_DATE_FMT)) rescue nil
|
|
443
378
|
Log.log.debug{"gem check new version: #{delay_days}, #{last_check_days}, #{current_date}, #{last_check_array}"}
|
|
444
379
|
return if !last_check_days.nil? && last_check_days < delay_days
|
|
445
|
-
#
|
|
380
|
+
# Generate timestamp
|
|
446
381
|
last_check_array[0] = current_date.strftime(GEM_CHECK_DATE_FMT)
|
|
447
382
|
check_date_persist.save
|
|
448
|
-
#
|
|
383
|
+
# Compare this version and the one on internet
|
|
449
384
|
check_data = check_gem_version
|
|
450
385
|
Log.log.warn do
|
|
451
386
|
"A new version is available: #{check_data[:latest]}. You have #{check_data[:current]}. Upgrade with: gem update #{check_data[:name]}"
|
|
452
387
|
end if check_data[:need_update]
|
|
453
388
|
end
|
|
454
389
|
|
|
455
|
-
#
|
|
390
|
+
# Loads default parameters of plugin if no -P parameter
|
|
456
391
|
# and if there is a section defined for the plugin in the "default" section
|
|
457
|
-
#
|
|
392
|
+
# Try to find: conf[conf["default"][plugin_str]]
|
|
458
393
|
# @param plugin_name_sym : symbol for plugin name
|
|
459
394
|
def add_plugin_default_preset(plugin_name_sym)
|
|
460
395
|
default_config_name = get_plugin_default_config_name(plugin_name_sym)
|
|
@@ -463,7 +398,7 @@ module Aspera
|
|
|
463
398
|
return
|
|
464
399
|
end
|
|
465
400
|
|
|
466
|
-
#
|
|
401
|
+
# Get the default global preset, or set default one
|
|
467
402
|
def global_default_preset
|
|
468
403
|
result = get_plugin_default_config_name(CONF_GLOBAL_SYM)
|
|
469
404
|
if result.nil?
|
|
@@ -491,7 +426,7 @@ module Aspera
|
|
|
491
426
|
param_name = param_name.to_s
|
|
492
427
|
selected_preset = @config_presets[preset]
|
|
493
428
|
if selected_preset.nil?
|
|
494
|
-
Log.log.debug{"
|
|
429
|
+
Log.log.debug{"Unknown preset name: #{preset}, initializing"}
|
|
495
430
|
selected_preset = @config_presets[preset] = {}
|
|
496
431
|
end
|
|
497
432
|
Aspera.assert_type(selected_preset, Hash){"#{preset}.#{param_name}"}
|
|
@@ -500,15 +435,15 @@ module Aspera
|
|
|
500
435
|
Log.log.warn{"keeping same value for #{preset}: #{param_name}: #{param_value}"}
|
|
501
436
|
return
|
|
502
437
|
end
|
|
503
|
-
Log.log.warn{"overwriting value: #{selected_preset[param_name]}"}
|
|
438
|
+
Log.log.warn{"overwriting value for #{param_name}: #{selected_preset[param_name]}"}
|
|
504
439
|
end
|
|
505
440
|
selected_preset[param_name] = param_value
|
|
506
441
|
formatter.display_status("Updated: #{preset}: #{param_name} <- #{param_value}")
|
|
507
442
|
nil
|
|
508
443
|
end
|
|
509
444
|
|
|
510
|
-
#
|
|
511
|
-
#
|
|
445
|
+
# Set parameter and value in global config
|
|
446
|
+
# Creates one if none already created
|
|
512
447
|
# @return preset name that contains global default
|
|
513
448
|
def set_global_default(key, value)
|
|
514
449
|
set_preset_key(global_default_preset, key, value)
|
|
@@ -523,35 +458,26 @@ module Aspera
|
|
|
523
458
|
# @return copy of the hash from name (also expands possible includes)
|
|
524
459
|
def preset_by_name(config_name, include_path = [])
|
|
525
460
|
raise Cli::Error, 'loop in include' if include_path.include?(config_name)
|
|
526
|
-
include_path = include_path.clone #
|
|
461
|
+
include_path = include_path.clone # Avoid messing up if there are multiple branches
|
|
527
462
|
current = @config_presets
|
|
528
463
|
config_name.split(PRESET_DIG_SEPARATOR).each do |name|
|
|
529
464
|
Aspera.assert_type(current, Hash, type: Cli::Error){"sub key: #{include_path}"}
|
|
530
465
|
include_path.push(name)
|
|
531
466
|
current = current[name]
|
|
532
|
-
raise Cli::Error, "
|
|
467
|
+
raise Cli::Error, "Unknown config preset: #{include_path}" if current.nil?
|
|
533
468
|
end
|
|
534
469
|
current = self.class.deep_clone(current) unless current.is_a?(String)
|
|
535
|
-
return ExtendedValue.instance.evaluate(current)
|
|
536
|
-
end
|
|
537
|
-
|
|
538
|
-
def option_use_product=(value)
|
|
539
|
-
Ascp::Installation.instance.use_ascp_from_product(value)
|
|
540
|
-
end
|
|
541
|
-
|
|
542
|
-
def option_use_product
|
|
543
|
-
'write-only option, see value of ascp_path'
|
|
470
|
+
return ExtendedValue.instance.evaluate(current, context: 'preset')
|
|
544
471
|
end
|
|
545
472
|
|
|
546
473
|
def option_plugin_folder=(value)
|
|
547
|
-
|
|
548
|
-
value
|
|
549
|
-
|
|
550
|
-
value.each{ |f| PluginFactory.instance.add_lookup_folder(f)}
|
|
474
|
+
value = [value] unless value.is_a?(Array)
|
|
475
|
+
Aspera.assert_array_all(value, String){'plugin folder(s)'}
|
|
476
|
+
value.each{ |f| Plugins::Factory.instance.add_lookup_folder(f)}
|
|
551
477
|
end
|
|
552
478
|
|
|
553
479
|
def option_plugin_folder
|
|
554
|
-
return
|
|
480
|
+
return Plugins::Factory.instance.lookup_folders
|
|
555
481
|
end
|
|
556
482
|
|
|
557
483
|
def option_preset; 'write-only option'; end
|
|
@@ -571,14 +497,14 @@ module Aspera
|
|
|
571
497
|
JSON.generate(@config_presets).hash
|
|
572
498
|
end
|
|
573
499
|
|
|
574
|
-
#
|
|
500
|
+
# Read config file and validate format
|
|
575
501
|
def read_config_file
|
|
576
502
|
Log.log.debug{"config file is: #{@option_config_file}".red}
|
|
577
|
-
#
|
|
503
|
+
# Files search for configuration, by default the one given by user
|
|
578
504
|
search_files = [@option_config_file]
|
|
579
|
-
#
|
|
505
|
+
# Find first existing file (or nil)
|
|
580
506
|
conf_file_to_load = search_files.find{ |f| File.exist?(f)}
|
|
581
|
-
#
|
|
507
|
+
# If no file found, create default config
|
|
582
508
|
if conf_file_to_load.nil?
|
|
583
509
|
Log.log.warn{"No config file found. New configuration file: #{@option_config_file}"}
|
|
584
510
|
@config_presets = {CONF_PRESET_CONFIG => {CONF_PRESET_VERSION => 'new file'}}
|
|
@@ -591,16 +517,16 @@ module Aspera
|
|
|
591
517
|
files_to_copy = []
|
|
592
518
|
Log.dump(:available_presets, @config_presets, level: :trace1)
|
|
593
519
|
Aspera.assert_type(@config_presets, Hash){'config file YAML'}
|
|
594
|
-
#
|
|
520
|
+
# Check there is at least the config section
|
|
595
521
|
Aspera.assert(@config_presets.key?(CONF_PRESET_CONFIG)){"Cannot find key: #{CONF_PRESET_CONFIG}"}
|
|
596
522
|
version = @config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]
|
|
597
523
|
raise Error, 'No version found in config section.' if version.nil?
|
|
598
524
|
Log.log.debug{"conf version: #{version}"}
|
|
599
525
|
# VVV if there are any conversion needed, those happen here.
|
|
600
|
-
#
|
|
526
|
+
# Fix bug in 4.4 (creating key "true" in "default" preset)
|
|
601
527
|
@config_presets[CONF_PRESET_DEFAULTS].delete(true) if @config_presets[CONF_PRESET_DEFAULTS].is_a?(Hash)
|
|
602
528
|
# ^^^ Place new compatibility code before this line
|
|
603
|
-
#
|
|
529
|
+
# Set version to current
|
|
604
530
|
@config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION] = Cli::VERSION
|
|
605
531
|
unless files_to_copy.empty?
|
|
606
532
|
Log.log.warn('Copying referenced files')
|
|
@@ -615,7 +541,7 @@ module Aspera
|
|
|
615
541
|
rescue StandardError => e
|
|
616
542
|
Log.log.debug{"-> #{e.class.name} : #{e}"}
|
|
617
543
|
if File.exist?(@option_config_file)
|
|
618
|
-
#
|
|
544
|
+
# Then there is a problem with that file.
|
|
619
545
|
new_name = "#{@option_config_file}.pre#{Cli::VERSION}.manual_conversion_needed"
|
|
620
546
|
File.rename(@option_config_file, new_name)
|
|
621
547
|
Log.log.warn{"Renamed config file to #{new_name}."}
|
|
@@ -674,13 +600,13 @@ module Aspera
|
|
|
674
600
|
when :show
|
|
675
601
|
return Main.result_text(Ascp::Installation.instance.path(:ascp))
|
|
676
602
|
when :info
|
|
677
|
-
#
|
|
603
|
+
# Collect info from ascp executable
|
|
678
604
|
data = Ascp::Installation.instance.ascp_info
|
|
679
|
-
#
|
|
680
|
-
data['ts'] = transfer.
|
|
681
|
-
#
|
|
605
|
+
# Add command line transfer spec
|
|
606
|
+
data['ts'] = transfer.user_transfer_spec
|
|
607
|
+
# Add keys
|
|
682
608
|
DataRepository::ELEMENTS.each_with_object(data){ |i, h| h[i.to_s] = DataRepository.instance.item(i)}
|
|
683
|
-
#
|
|
609
|
+
# Declare those as secrets
|
|
684
610
|
SecretHider::ADDITIONAL_KEYS_TO_HIDE.concat(DataRepository::ELEMENTS.map(&:to_s))
|
|
685
611
|
return Main.result_single_object(data)
|
|
686
612
|
when :products
|
|
@@ -691,17 +617,17 @@ module Aspera
|
|
|
691
617
|
when :use
|
|
692
618
|
default_product = options.get_next_argument('product name')
|
|
693
619
|
Ascp::Installation.instance.use_ascp_from_product(default_product)
|
|
694
|
-
set_global_default(:ascp_path, Ascp::Installation
|
|
620
|
+
set_global_default(:ascp_path, "#{Ascp::Installation::USE_PRODUCT_PREFIX}#{default_product}")
|
|
695
621
|
return Main.result_nothing
|
|
696
622
|
end
|
|
697
623
|
when :install
|
|
698
|
-
#
|
|
699
|
-
Products::Transferd.sdk_directory = self.class.default_app_main_folder(app_name:
|
|
624
|
+
# Reset to default location, if older default was used
|
|
625
|
+
Products::Transferd.sdk_directory = self.class.default_app_main_folder(app_name: TRANSFERD_APP_NAME) if @sdk_default_location
|
|
700
626
|
version = options.get_next_argument('transferd version', mandatory: false)
|
|
701
627
|
n, v = Ascp::Installation.instance.install_sdk(url: options.get_option(:sdk_url, mandatory: true), version: version)
|
|
702
628
|
return Main.result_status("Installed #{n} version #{v}")
|
|
703
629
|
when :spec
|
|
704
|
-
fields, data = Transfer::SpecDoc.man_table(Formatter)
|
|
630
|
+
fields, data = Transfer::SpecDoc.man_table(Formatter, include_option: true)
|
|
705
631
|
return Main.result_object_list(data, fields: fields.map(&:to_s))
|
|
706
632
|
when :schema
|
|
707
633
|
schema = Transfer::Spec::SCHEMA.merge({'$comment'=>'DO NOT EDIT, this file was generated from the YAML.'})
|
|
@@ -711,7 +637,7 @@ module Aspera
|
|
|
711
637
|
return Main.result_single_object(schema)
|
|
712
638
|
when :errors
|
|
713
639
|
error_data = []
|
|
714
|
-
|
|
640
|
+
Ascp::Management::ERRORS.each_pair do |code, prop|
|
|
715
641
|
error_data.push(code: code, mnemonic: prop[:c], retry: prop[:r], info: prop[:a])
|
|
716
642
|
end
|
|
717
643
|
return Main.result_object_list(error_data)
|
|
@@ -724,8 +650,8 @@ module Aspera
|
|
|
724
650
|
command = options.get_next_command(%i[list install])
|
|
725
651
|
case command
|
|
726
652
|
when :install
|
|
727
|
-
#
|
|
728
|
-
Products::Transferd.sdk_directory = self.class.default_app_main_folder(app_name:
|
|
653
|
+
# Reset to default location, if older default was used
|
|
654
|
+
Products::Transferd.sdk_directory = self.class.default_app_main_folder(app_name: TRANSFERD_APP_NAME) if @sdk_default_location
|
|
729
655
|
version = options.get_next_argument('transferd version', mandatory: false)
|
|
730
656
|
n, v = Ascp::Installation.instance.install_sdk(url: options.get_option(:sdk_url, mandatory: true), version: version)
|
|
731
657
|
return Main.result_status("Installed #{n} version #{v}")
|
|
@@ -740,9 +666,9 @@ module Aspera
|
|
|
740
666
|
Aspera.error_unreachable_line
|
|
741
667
|
end
|
|
742
668
|
|
|
743
|
-
#
|
|
669
|
+
# Legacy actions available globally
|
|
744
670
|
PRESET_GBL_ACTIONS = %i[list overview lookup secure].freeze
|
|
745
|
-
#
|
|
671
|
+
# Operations requiring that preset exists
|
|
746
672
|
PRESET_EXIST_ACTIONS = %i[show delete get unset].freeze
|
|
747
673
|
# require id
|
|
748
674
|
PRESET_INSTANCE_ACTIONS = %i[initialize update ask set].concat(PRESET_EXIST_ACTIONS).freeze
|
|
@@ -752,13 +678,13 @@ module Aspera
|
|
|
752
678
|
action = options.get_next_command(PRESET_ALL_ACTIONS) if action.nil?
|
|
753
679
|
name = instance_identifier if name.nil? && PRESET_INSTANCE_ACTIONS.include?(action)
|
|
754
680
|
name = global_default_preset if name.eql?(GLOBAL_DEFAULT_KEYWORD)
|
|
755
|
-
#
|
|
681
|
+
# Those operations require existing option
|
|
756
682
|
raise "no such preset: #{name}" if PRESET_EXIST_ACTIONS.include?(action) && !@config_presets.key?(name)
|
|
757
683
|
case action
|
|
758
684
|
when :list
|
|
759
685
|
return Main.result_value_list(@config_presets.keys, name: 'name')
|
|
760
686
|
when :overview
|
|
761
|
-
#
|
|
687
|
+
# Display process modifies the value (hide secrets): we do not want to save removed secrets
|
|
762
688
|
data = self.class.deep_clone(@config_presets)
|
|
763
689
|
formatter.hide_secrets(data)
|
|
764
690
|
result = []
|
|
@@ -778,7 +704,7 @@ module Aspera
|
|
|
778
704
|
value = @config_presets[name][param_name]
|
|
779
705
|
raise "no such option in preset #{name} : #{param_name}" if value.nil?
|
|
780
706
|
case value
|
|
781
|
-
when Numeric, String then return Main.result_text(ExtendedValue.instance.evaluate(value.to_s))
|
|
707
|
+
when Numeric, String then return Main.result_text(ExtendedValue.instance.evaluate(value.to_s, context: 'preset'))
|
|
782
708
|
end
|
|
783
709
|
return Main.result_single_object(value)
|
|
784
710
|
when :unset
|
|
@@ -807,12 +733,12 @@ module Aspera
|
|
|
807
733
|
options.ask_missing_mandatory = true
|
|
808
734
|
@config_presets[name] ||= {}
|
|
809
735
|
options.get_next_argument('option names', multiple: true).each do |option_name|
|
|
810
|
-
option_value = options.get_interactive(option_name,
|
|
736
|
+
option_value = options.get_interactive(option_name, check_option: true)
|
|
811
737
|
@config_presets[name][option_name] = option_value
|
|
812
738
|
end
|
|
813
739
|
return Main.result_status("Updated: #{name}")
|
|
814
740
|
when :lookup
|
|
815
|
-
|
|
741
|
+
BasicAuth.declare_options(options)
|
|
816
742
|
url = options.get_option(:url, mandatory: true)
|
|
817
743
|
user = options.get_option(:username, mandatory: true)
|
|
818
744
|
result = lookup_preset(url: url, username: user)
|
|
@@ -863,6 +789,7 @@ module Aspera
|
|
|
863
789
|
coffee
|
|
864
790
|
image
|
|
865
791
|
ascp
|
|
792
|
+
sync
|
|
866
793
|
transferd
|
|
867
794
|
email_test
|
|
868
795
|
smtp_settings
|
|
@@ -880,7 +807,7 @@ module Aspera
|
|
|
880
807
|
def execute_action
|
|
881
808
|
action = options.get_next_command(ACTIONS)
|
|
882
809
|
case action
|
|
883
|
-
when :preset #
|
|
810
|
+
when :preset # Newer syntax
|
|
884
811
|
return execute_preset
|
|
885
812
|
when :open
|
|
886
813
|
Environment.instance.open_editor(@option_config_file.to_s)
|
|
@@ -890,12 +817,12 @@ module Aspera
|
|
|
890
817
|
section = "##{section}" unless section.nil?
|
|
891
818
|
Environment.instance.open_uri("#{Info::DOC_URL}#{section}")
|
|
892
819
|
return Main.result_nothing
|
|
893
|
-
when :genkey #
|
|
820
|
+
when :genkey # Generate new rsa key
|
|
894
821
|
private_key_path = options.get_next_argument('private key file path')
|
|
895
822
|
private_key_length = options.get_next_argument('size in bits', mandatory: false, validation: Integer, default: OAuth::Jwt::DEFAULT_PRIV_KEY_LENGTH)
|
|
896
823
|
OAuth::Jwt.generate_rsa_private_key(path: private_key_path, length: private_key_length)
|
|
897
824
|
return Main.result_status("Generated #{private_key_length} bit RSA key: #{private_key_path}")
|
|
898
|
-
when :pubkey #
|
|
825
|
+
when :pubkey # Get pub key
|
|
899
826
|
private_key_pem = options.get_next_argument('private key PEM value')
|
|
900
827
|
return Main.result_text(OpenSSL::PKey::RSA.new(private_key_pem).public_key.to_s)
|
|
901
828
|
when :remote_certificate
|
|
@@ -911,7 +838,7 @@ module Aspera
|
|
|
911
838
|
when :name
|
|
912
839
|
return Main.result_text(remote_chain.first.subject.to_a.find{ |name, _, _| name == 'CN'}[1])
|
|
913
840
|
end
|
|
914
|
-
when :echo #
|
|
841
|
+
when :echo # Display the content of a value given on command line
|
|
915
842
|
return Main.result_auto(options.get_next_argument('value', validation: nil))
|
|
916
843
|
when :download
|
|
917
844
|
file_url = options.get_next_argument('source URL').chomp
|
|
@@ -929,20 +856,20 @@ module Aspera
|
|
|
929
856
|
return Main.result_object_list(OAuth::Factory.instance.persisted_tokens)
|
|
930
857
|
when :show
|
|
931
858
|
data = OAuth::Factory.instance.get_token_info(instance_identifier)
|
|
932
|
-
raise Cli::Error, '
|
|
859
|
+
raise Cli::Error, 'Unknown identifier' if data.nil?
|
|
933
860
|
return Main.result_single_object(data)
|
|
934
861
|
end
|
|
935
862
|
when :plugins
|
|
936
863
|
case options.get_next_command(%i[list create])
|
|
937
864
|
when :list
|
|
938
865
|
result = []
|
|
939
|
-
|
|
940
|
-
plugin_class =
|
|
866
|
+
Plugins::Factory.instance.plugin_list.each do |name|
|
|
867
|
+
plugin_class = Plugins::Factory.instance.plugin_class(name)
|
|
941
868
|
result.push({
|
|
942
869
|
plugin: name,
|
|
943
870
|
detect: Formatter.tick(plugin_class.respond_to?(:detect)),
|
|
944
|
-
wizard: Formatter.tick(plugin_class.
|
|
945
|
-
path:
|
|
871
|
+
wizard: Formatter.tick(plugin_class.method_defined?(:wizard)),
|
|
872
|
+
path: Plugins::Factory.instance.plugin_source(name)
|
|
946
873
|
})
|
|
947
874
|
end
|
|
948
875
|
return Main.result_object_list(result, fields: %w[plugin detect wizard path])
|
|
@@ -951,25 +878,27 @@ module Aspera
|
|
|
951
878
|
destination_folder = options.get_next_argument('folder', mandatory: false) || File.join(@main_folder, ASPERA_PLUGINS_FOLDERNAME)
|
|
952
879
|
plugin_file = File.join(destination_folder, "#{plugin_name}.rb")
|
|
953
880
|
content = <<~END_OF_PLUGIN_CODE
|
|
954
|
-
require 'aspera/cli/
|
|
881
|
+
require 'aspera/cli/plugins/base'
|
|
955
882
|
module Aspera
|
|
956
883
|
module Cli
|
|
957
884
|
module Plugins
|
|
958
|
-
class #{plugin_name.
|
|
885
|
+
class #{plugin_name.snake_to_capital} < Base
|
|
959
886
|
ACTIONS=[]
|
|
960
|
-
def execute_action
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
887
|
+
def execute_action
|
|
888
|
+
return Main.result_status('You called plugin #{plugin_name}')
|
|
889
|
+
end
|
|
890
|
+
end
|
|
891
|
+
end
|
|
892
|
+
end
|
|
893
|
+
end
|
|
965
894
|
END_OF_PLUGIN_CODE
|
|
966
895
|
File.write(plugin_file, content)
|
|
967
896
|
return Main.result_status("Created #{plugin_file}")
|
|
968
897
|
end
|
|
969
898
|
when :detect, :wizard
|
|
970
|
-
#
|
|
899
|
+
# Interactive mode
|
|
971
900
|
options.ask_missing_mandatory = true
|
|
972
|
-
#
|
|
901
|
+
# Detect plugins by url and optional query
|
|
973
902
|
apps = @wizard.identify_plugins_for_url.freeze
|
|
974
903
|
return Main.result_object_list(apps) if action.eql?(:detect)
|
|
975
904
|
return @wizard.find(apps)
|
|
@@ -979,6 +908,17 @@ module Aspera
|
|
|
979
908
|
return Main.result_image(options.get_next_argument('image URI or blob'))
|
|
980
909
|
when :ascp
|
|
981
910
|
execute_action_ascp
|
|
911
|
+
when :sync
|
|
912
|
+
case options.get_next_command(%i[spec admin translate])
|
|
913
|
+
when :spec
|
|
914
|
+
fields, data = Transfer::SpecDoc.man_table(Formatter, include_option: true, agent_columns: false, schema: Sync::Operations::CONF_SCHEMA)
|
|
915
|
+
return Main.result_object_list(data, fields: fields.map(&:to_s))
|
|
916
|
+
when :admin
|
|
917
|
+
return execute_sync_admin
|
|
918
|
+
when :translate
|
|
919
|
+
return Main.result_single_object(Sync::Operations.args_to_conf(options.get_next_argument('async arguments', multiple: true)))
|
|
920
|
+
else Aspera.error_unreachable_line
|
|
921
|
+
end
|
|
982
922
|
when :transferd
|
|
983
923
|
execute_action_transferd
|
|
984
924
|
when :gem
|
|
@@ -986,6 +926,7 @@ module Aspera
|
|
|
986
926
|
when :path then return Main.result_text(self.class.gem_src_root)
|
|
987
927
|
when :version then return Main.result_text(Cli::VERSION)
|
|
988
928
|
when :name then return Main.result_text(Info::GEM_NAME)
|
|
929
|
+
else Aspera.error_unreachable_line
|
|
989
930
|
end
|
|
990
931
|
when :folder
|
|
991
932
|
return Main.result_text(@main_folder)
|
|
@@ -997,7 +938,7 @@ module Aspera
|
|
|
997
938
|
when :smtp_settings
|
|
998
939
|
return Main.result_single_object(email_settings)
|
|
999
940
|
when :proxy_check
|
|
1000
|
-
#
|
|
941
|
+
# Ensure fpac was provided
|
|
1001
942
|
options.get_option(:fpac, mandatory: true)
|
|
1002
943
|
server_url = options.get_next_argument('server url')
|
|
1003
944
|
return Main.result_text(@pac_exec.get_proxies(server_url))
|
|
@@ -1035,11 +976,11 @@ module Aspera
|
|
|
1035
976
|
# @return [Hash] email server setting with defaults if not defined
|
|
1036
977
|
def email_settings
|
|
1037
978
|
smtp = options.get_option(:smtp, mandatory: true)
|
|
1038
|
-
#
|
|
979
|
+
# Change keys from string into symbol
|
|
1039
980
|
smtp = smtp.symbolize_keys
|
|
1040
981
|
unsupported = smtp.keys - SMTP_CONF_PARAMS
|
|
1041
982
|
raise Cli::Error, "Unsupported SMTP parameter: #{unsupported.join(', ')}, use: #{SMTP_CONF_PARAMS.join(', ')}" unless unsupported.empty?
|
|
1042
|
-
#
|
|
983
|
+
# Defaults
|
|
1043
984
|
# smtp[:ssl] = nil (false)
|
|
1044
985
|
smtp[:tls] = !smtp[:ssl] unless smtp.key?(:tls)
|
|
1045
986
|
smtp[:port] ||= if smtp[:tls]
|
|
@@ -1052,7 +993,7 @@ module Aspera
|
|
|
1052
993
|
smtp[:from_email] ||= smtp[:username] if smtp.key?(:username)
|
|
1053
994
|
smtp[:from_name] ||= smtp[:from_email].sub(/@.*$/, '').gsub(/[^a-zA-Z]/, ' ').capitalize if smtp.key?(:username)
|
|
1054
995
|
smtp[:domain] ||= smtp[:from_email].sub(/^.*@/, '') if smtp.key?(:from_email)
|
|
1055
|
-
#
|
|
996
|
+
# Check minimum required
|
|
1056
997
|
%i[server port domain].each do |n|
|
|
1057
998
|
Aspera.assert(smtp.key?(n)){"Missing mandatory smtp parameter: #{n}"}
|
|
1058
999
|
end
|
|
@@ -1060,8 +1001,8 @@ module Aspera
|
|
|
1060
1001
|
return smtp
|
|
1061
1002
|
end
|
|
1062
1003
|
|
|
1063
|
-
#
|
|
1064
|
-
# @param email_template_default [String] default template, can be
|
|
1004
|
+
# Send email using ERB template
|
|
1005
|
+
# @param email_template_default [String] default template, can be overridden by option
|
|
1065
1006
|
# @param values [Hash] values to be used in template, keys with default: to, from_name, from_email
|
|
1066
1007
|
def send_email_template(email_template_default: nil, values: {})
|
|
1067
1008
|
values[:to] ||= options.get_option(:notify_to, mandatory: true)
|
|
@@ -1074,14 +1015,14 @@ module Aspera
|
|
|
1074
1015
|
end
|
|
1075
1016
|
start_options = [mail_conf[:domain]]
|
|
1076
1017
|
start_options.push(mail_conf[:username], mail_conf[:password], :login) if mail_conf.key?(:username) && mail_conf.key?(:password)
|
|
1077
|
-
#
|
|
1018
|
+
# Create a binding with only variables defined in values
|
|
1078
1019
|
template_binding = Environment.empty_binding
|
|
1079
|
-
#
|
|
1020
|
+
# Add variables to binding
|
|
1080
1021
|
values.each do |k, v|
|
|
1081
1022
|
Aspera.assert_type(k, Symbol)
|
|
1082
1023
|
template_binding.local_variable_set(k, v)
|
|
1083
1024
|
end
|
|
1084
|
-
#
|
|
1025
|
+
# Execute template
|
|
1085
1026
|
msg_with_headers = ERB.new(notify_template).result(template_binding)
|
|
1086
1027
|
Log.dump(:msg_with_headers, msg_with_headers)
|
|
1087
1028
|
require 'net/smtp'
|
|
@@ -1095,7 +1036,7 @@ module Aspera
|
|
|
1095
1036
|
end
|
|
1096
1037
|
|
|
1097
1038
|
# Save current configuration to config file
|
|
1098
|
-
# return true if file was saved
|
|
1039
|
+
# @return true if file was saved
|
|
1099
1040
|
def save_config_file_if_needed
|
|
1100
1041
|
raise Error, 'no configuration loaded' if @config_presets.nil?
|
|
1101
1042
|
current_checksum = config_checksum
|
|
@@ -1109,29 +1050,35 @@ module Aspera
|
|
|
1109
1050
|
return true
|
|
1110
1051
|
end
|
|
1111
1052
|
|
|
1112
|
-
#
|
|
1113
|
-
#
|
|
1053
|
+
# @return [String] name if config_presets has default
|
|
1054
|
+
# @return nil if there is no config or bypass default params
|
|
1114
1055
|
def get_plugin_default_config_name(plugin_name_sym)
|
|
1115
1056
|
Aspera.assert(!@config_presets.nil?){'config_presets shall be defined'}
|
|
1116
1057
|
if !@use_plugin_defaults
|
|
1117
1058
|
Log.log.debug('skip default config')
|
|
1118
1059
|
return
|
|
1119
1060
|
end
|
|
1120
|
-
if
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1061
|
+
if !@config_presets.key?(CONF_PRESET_DEFAULTS)
|
|
1062
|
+
Log.log.debug('No default section')
|
|
1063
|
+
return
|
|
1064
|
+
end
|
|
1065
|
+
Aspera.assert_type(@config_presets[CONF_PRESET_DEFAULTS], Hash){'default section'}
|
|
1066
|
+
if !@config_presets[CONF_PRESET_DEFAULTS].key?(plugin_name_sym.to_s)
|
|
1067
|
+
Log.log.debug("No default for #{plugin_name_sym}")
|
|
1068
|
+
return
|
|
1069
|
+
end
|
|
1070
|
+
default_config_name = @config_presets[CONF_PRESET_DEFAULTS][plugin_name_sym.to_s]
|
|
1071
|
+
if !@config_presets.key?(default_config_name)
|
|
1072
|
+
Log.log.error do
|
|
1073
|
+
"Default config name [#{default_config_name}] specified for plugin [#{plugin_name_sym}], but it does not exist in config file.\n" \
|
|
1074
|
+
"Please fix the issue: either create preset with one parameter:\n" \
|
|
1075
|
+
"#{Info::CMD_NAME} config id #{default_config_name} init @json:'{}'\n" \
|
|
1076
|
+
"or remove default:\n#{Info::CMD_NAME} config id default remove #{plugin_name_sym}"
|
|
1130
1077
|
end
|
|
1131
|
-
raise Cli::Error, "
|
|
1132
|
-
return default_config_name
|
|
1078
|
+
raise Cli::Error, "No such preset: #{default_config_name}"
|
|
1133
1079
|
end
|
|
1134
|
-
|
|
1080
|
+
Aspera.assert_type(@config_presets[default_config_name], Hash, type: Cli::Error){'preset type'}
|
|
1081
|
+
return default_config_name
|
|
1135
1082
|
end
|
|
1136
1083
|
|
|
1137
1084
|
# @return [Hash] result of execution of vault command
|
|
@@ -1163,7 +1110,7 @@ module Aspera
|
|
|
1163
1110
|
def vault_value(name)
|
|
1164
1111
|
m = name.split('.')
|
|
1165
1112
|
raise BadArgument, 'vault name shall match <name>.<param>' unless m.length.eql?(2)
|
|
1166
|
-
#
|
|
1113
|
+
# This raise exception if label not found:
|
|
1167
1114
|
info = vault.get(label: m[0])
|
|
1168
1115
|
value = info[m[1].to_sym]
|
|
1169
1116
|
raise "no such entry value: #{m[1]}" if value.nil?
|
|
@@ -1184,12 +1131,12 @@ module Aspera
|
|
|
1184
1131
|
)
|
|
1185
1132
|
end
|
|
1186
1133
|
|
|
1187
|
-
#
|
|
1134
|
+
# Artificially raise an exception for tests
|
|
1188
1135
|
def execute_test
|
|
1189
1136
|
case options.get_next_command(%i[throw web])
|
|
1190
1137
|
when :throw
|
|
1191
1138
|
# :type [String]
|
|
1192
|
-
#
|
|
1139
|
+
# Options
|
|
1193
1140
|
exception_class_name = options.get_next_argument('exception class name', mandatory: true)
|
|
1194
1141
|
exception_text = options.get_next_argument('exception text', mandatory: true)
|
|
1195
1142
|
type = Object.const_get(exception_class_name)
|
|
@@ -1199,7 +1146,7 @@ module Aspera
|
|
|
1199
1146
|
end
|
|
1200
1147
|
end
|
|
1201
1148
|
|
|
1202
|
-
#
|
|
1149
|
+
# Version of URL without trailing "/" and removing default port
|
|
1203
1150
|
def canonical_url(url)
|
|
1204
1151
|
url.chomp('/').sub(%r{^(https://[^/]+):443$}, '\1')
|
|
1205
1152
|
end
|
|
@@ -1207,7 +1154,7 @@ module Aspera
|
|
|
1207
1154
|
# Look for a preset that has the corresponding URL and username
|
|
1208
1155
|
# @return the first one matching
|
|
1209
1156
|
def lookup_preset(url:, username:)
|
|
1210
|
-
#
|
|
1157
|
+
# Remove extra info to maximize match
|
|
1211
1158
|
url = canonical_url(url)
|
|
1212
1159
|
Log.log.debug{"Lookup preset for #{username}@#{url}"}
|
|
1213
1160
|
@config_presets.each_value do |v|
|
|
@@ -1232,6 +1179,73 @@ module Aspera
|
|
|
1232
1179
|
end
|
|
1233
1180
|
return secret
|
|
1234
1181
|
end
|
|
1182
|
+
# Private
|
|
1183
|
+
# Folder in $HOME for application files (config, cache)
|
|
1184
|
+
ASPERA_HOME_FOLDER_NAME = '.aspera'
|
|
1185
|
+
# Default config file
|
|
1186
|
+
DEFAULT_CONFIG_FILENAME = 'config.yaml'
|
|
1187
|
+
# Reserved preset names
|
|
1188
|
+
CONF_PRESET_CONFIG = 'config'
|
|
1189
|
+
CONF_PRESET_VERSION = 'version'
|
|
1190
|
+
CONF_PRESET_DEFAULTS = 'default'
|
|
1191
|
+
CONF_PRESET_GLOBAL = 'global_common_defaults'
|
|
1192
|
+
# Special name to identify value of default
|
|
1193
|
+
GLOBAL_DEFAULT_KEYWORD = 'GLOBAL'
|
|
1194
|
+
CONF_GLOBAL_SYM = :config
|
|
1195
|
+
# Folder containing custom plugins in user's config folder
|
|
1196
|
+
ASPERA_PLUGINS_FOLDERNAME = 'plugins'
|
|
1197
|
+
PERSISTENCY_FOLDER = 'persist_store'
|
|
1198
|
+
ASPERA = 'aspera'
|
|
1199
|
+
SERVER_COMMAND = 'server'
|
|
1200
|
+
TRANSFERD_APP_NAME = 'sdk'
|
|
1201
|
+
DEMO_SERVER = 'demo'
|
|
1202
|
+
DEMO_PRESET = 'demoserver' # cspell: disable-line
|
|
1203
|
+
EMAIL_TEST_TEMPLATE = <<~END_OF_TEMPLATE
|
|
1204
|
+
From: <%=from_name%> <<%=from_email%>>
|
|
1205
|
+
To: <<%=to%>>
|
|
1206
|
+
Subject: #{Info::GEM_NAME} email test
|
|
1207
|
+
|
|
1208
|
+
This email was sent to test #{Info::CMD_NAME}.
|
|
1209
|
+
END_OF_TEMPLATE
|
|
1210
|
+
# Special extended values
|
|
1211
|
+
EXTEND_PRESET = :preset
|
|
1212
|
+
EXTEND_VAULT = :vault
|
|
1213
|
+
EXTEND_ARGS = :''
|
|
1214
|
+
PRESET_DIG_SEPARATOR = '.'
|
|
1215
|
+
DEFAULT_CHECK_NEW_VERSION_DAYS = 7
|
|
1216
|
+
COFFEE_IMAGE_URL = 'https://enjoyjava.com/wp-content/uploads/2018/01/How-to-make-strong-coffee.jpg'
|
|
1217
|
+
GEM_CHECK_DATE_FMT = '%Y/%m/%d'
|
|
1218
|
+
# For testing only
|
|
1219
|
+
SELF_SIGNED_CERT = OpenSSL::SSL.const_get(:enon_yfirev.to_s.upcase.reverse) # cspell: disable-line
|
|
1220
|
+
CONF_OVERVIEW_KEYS = %w[preset parameter value].freeze
|
|
1221
|
+
SMTP_CONF_PARAMS = %i[server tls ssl port domain username password from_name from_email].freeze
|
|
1222
|
+
CERT_EXT = %w[crt cer pem der].freeze
|
|
1223
|
+
private_constant :ASPERA_HOME_FOLDER_NAME,
|
|
1224
|
+
:DEFAULT_CONFIG_FILENAME,
|
|
1225
|
+
:CONF_PRESET_CONFIG,
|
|
1226
|
+
:CONF_PRESET_VERSION,
|
|
1227
|
+
:CONF_PRESET_DEFAULTS,
|
|
1228
|
+
:CONF_PRESET_GLOBAL,
|
|
1229
|
+
:ASPERA_PLUGINS_FOLDERNAME,
|
|
1230
|
+
:ASPERA,
|
|
1231
|
+
:DEMO_SERVER,
|
|
1232
|
+
:DEMO_PRESET,
|
|
1233
|
+
:EMAIL_TEST_TEMPLATE,
|
|
1234
|
+
:EXTEND_PRESET,
|
|
1235
|
+
:EXTEND_VAULT,
|
|
1236
|
+
:DEFAULT_CHECK_NEW_VERSION_DAYS,
|
|
1237
|
+
:SERVER_COMMAND,
|
|
1238
|
+
:PRESET_DIG_SEPARATOR,
|
|
1239
|
+
:COFFEE_IMAGE_URL,
|
|
1240
|
+
:SELF_SIGNED_CERT,
|
|
1241
|
+
:PERSISTENCY_FOLDER,
|
|
1242
|
+
:CONF_OVERVIEW_KEYS,
|
|
1243
|
+
:SMTP_CONF_PARAMS,
|
|
1244
|
+
:TRANSFERD_APP_NAME,
|
|
1245
|
+
:GLOBAL_DEFAULT_KEYWORD,
|
|
1246
|
+
:CONF_GLOBAL_SYM,
|
|
1247
|
+
:GEM_CHECK_DATE_FMT,
|
|
1248
|
+
:CERT_EXT
|
|
1235
1249
|
end
|
|
1236
1250
|
end
|
|
1237
1251
|
end
|