ftp_paradise 1.4.5 → 1.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +155 -28
  3. data/bin/{iftp → ftp_paradise_shell} +1 -1
  4. data/doc/README.gen +97 -15
  5. data/doc/todo/{TODO_FOR_FTP_PARADISE_PROJECT.md → todo_for_the_ftp_paradise_project.md} +11 -1
  6. data/ftp_paradise.gemspec +30 -39
  7. data/lib/ftp_paradise/base/base.rb +375 -0
  8. data/lib/ftp_paradise/colours/colours.rb +27 -27
  9. data/lib/ftp_paradise/colours/use_colours.rb +6 -1
  10. data/lib/ftp_paradise/configuration/configuration.rb +7 -4
  11. data/lib/ftp_paradise/connection/README.md +0 -0
  12. data/lib/ftp_paradise/connection/connection.rb +2782 -15
  13. data/lib/ftp_paradise/constants/constants.rb +91 -5
  14. data/lib/ftp_paradise/entry/entry.rb +42 -5
  15. data/lib/ftp_paradise/{connection → gui/gtk3/ftp_client}/constants.rb +33 -21
  16. data/lib/ftp_paradise/gui/{shared_code/ftp_paradise/ftp_paradise_module.rb → gtk3/ftp_client/ftp_client.rb} +658 -170
  17. data/lib/ftp_paradise/gui/gtk3/ftp_client/misc.rb +27 -0
  18. data/lib/ftp_paradise/project/project.rb +11 -15
  19. data/lib/ftp_paradise/requires/require_class_connection.rb +7 -0
  20. data/lib/ftp_paradise/requires/require_net_ftp.rb +7 -0
  21. data/lib/ftp_paradise/requires/require_the_ftp_paradise_project.rb +4 -3
  22. data/lib/ftp_paradise/requires/require_the_ftp_paradise_project_with_the_GUI_bindings.rb +1 -1
  23. data/lib/ftp_paradise/requires/require_the_toplevel_methods.rb +1 -0
  24. data/lib/ftp_paradise/{interactive_ftp → shell}/menu.rb +564 -449
  25. data/lib/ftp_paradise/shell/shell.rb +2321 -0
  26. data/lib/ftp_paradise/toplevel_methods/connect.rb +3 -0
  27. data/lib/ftp_paradise/toplevel_methods/dataset.rb +111 -0
  28. data/lib/ftp_paradise/toplevel_methods/file_related_actions.rb +4 -3
  29. data/lib/ftp_paradise/toplevel_methods/ftp_object.rb +6 -5
  30. data/lib/ftp_paradise/toplevel_methods/login_name.rb +6 -4
  31. data/lib/ftp_paradise/toplevel_methods/misc.rb +19 -0
  32. data/lib/ftp_paradise/toplevel_methods/opn.rb +1 -1
  33. data/lib/ftp_paradise/toplevel_methods/password.rb +4 -2
  34. data/lib/ftp_paradise/toplevel_methods/port.rb +4 -1
  35. data/lib/ftp_paradise/toplevel_methods/remote_url.rb +11 -5
  36. data/lib/ftp_paradise/toplevel_methods/upload_and_download.rb +1 -0
  37. data/lib/ftp_paradise/version/version.rb +6 -1
  38. data/lib/ftp_paradise/www/web_interface.cgi +1 -1
  39. data/lib/ftp_paradise/yaml/automatically_connect_on_startup_of_the_interactive_ftp_shell.yml +0 -0
  40. data/lib/ftp_paradise/yaml/debug.yml +0 -0
  41. data/lib/ftp_paradise/yaml/open_in_default_editor.yml +0 -0
  42. data/lib/ftp_paradise/yaml/show_full_names.yml +0 -0
  43. data/lib/ftp_paradise/yaml/use_colours.yml +0 -0
  44. data/test/testing_minimal_pure_net_ftp_example_to_connect.rb +13 -3
  45. metadata +52 -126
  46. data/lib/ftp_paradise/base/cliner.rb +0 -23
  47. data/lib/ftp_paradise/base/colours.rb +0 -83
  48. data/lib/ftp_paradise/base/prototype.rb +0 -171
  49. data/lib/ftp_paradise/base/reset.rb +0 -29
  50. data/lib/ftp_paradise/connection/data.rb +0 -164
  51. data/lib/ftp_paradise/connection/debug.rb +0 -78
  52. data/lib/ftp_paradise/connection/directory_handling.rb +0 -271
  53. data/lib/ftp_paradise/connection/do_login.rb +0 -108
  54. data/lib/ftp_paradise/connection/download.rb +0 -86
  55. data/lib/ftp_paradise/connection/file_handling.rb +0 -174
  56. data/lib/ftp_paradise/connection/ftp_object.rb +0 -21
  57. data/lib/ftp_paradise/connection/initialize.rb +0 -88
  58. data/lib/ftp_paradise/connection/initialize_a_new_net_ftp_object_with_this_url.rb +0 -20
  59. data/lib/ftp_paradise/connection/is_connected.rb +0 -46
  60. data/lib/ftp_paradise/connection/misc.rb +0 -474
  61. data/lib/ftp_paradise/connection/notify.rb +0 -71
  62. data/lib/ftp_paradise/connection/password.rb +0 -47
  63. data/lib/ftp_paradise/connection/port.rb +0 -33
  64. data/lib/ftp_paradise/connection/remote_pwd.rb +0 -72
  65. data/lib/ftp_paradise/connection/remote_url.rb +0 -164
  66. data/lib/ftp_paradise/connection/remove.rb +0 -143
  67. data/lib/ftp_paradise/connection/reset.rb +0 -78
  68. data/lib/ftp_paradise/connection/run.rb +0 -18
  69. data/lib/ftp_paradise/connection/set_array_available_hosts.rb +0 -27
  70. data/lib/ftp_paradise/connection/set_input.rb +0 -18
  71. data/lib/ftp_paradise/connection/show.rb +0 -153
  72. data/lib/ftp_paradise/connection/sync_ftp_object_onto_the_main_namespace.rb +0 -24
  73. data/lib/ftp_paradise/connection/transfer_mode.rb +0 -163
  74. data/lib/ftp_paradise/connection/upload.rb +0 -253
  75. data/lib/ftp_paradise/connection/use_default_dataset.rb +0 -40
  76. data/lib/ftp_paradise/connection/username.rb +0 -42
  77. data/lib/ftp_paradise/constants/misc.rb +0 -57
  78. data/lib/ftp_paradise/constants/namespace.rb +0 -14
  79. data/lib/ftp_paradise/constants/newline.rb +0 -14
  80. data/lib/ftp_paradise/constants/roebe.rb +0 -31
  81. data/lib/ftp_paradise/constants/roebe_ftp_constants.rb +0 -233
  82. data/lib/ftp_paradise/gui/gtk2/ftp_paradise.rb +0 -34
  83. data/lib/ftp_paradise/gui/gtk3/ftp_paradise.rb +0 -34
  84. data/lib/ftp_paradise/interactive_ftp/constants.rb +0 -103
  85. data/lib/ftp_paradise/interactive_ftp/directory_handling.rb +0 -216
  86. data/lib/ftp_paradise/interactive_ftp/help.rb +0 -50
  87. data/lib/ftp_paradise/interactive_ftp/initialize.rb +0 -27
  88. data/lib/ftp_paradise/interactive_ftp/interactive_ftp.rb +0 -998
  89. data/lib/ftp_paradise/interactive_ftp/main_loop.rb +0 -51
  90. data/lib/ftp_paradise/interactive_ftp/misc.rb +0 -208
  91. data/lib/ftp_paradise/interactive_ftp/mode.rb +0 -124
  92. data/lib/ftp_paradise/interactive_ftp/readline.rb +0 -113
  93. data/lib/ftp_paradise/interactive_ftp/remove.rb +0 -97
  94. data/lib/ftp_paradise/interactive_ftp/reset.rb +0 -90
  95. data/lib/ftp_paradise/interactive_ftp/run.rb +0 -22
  96. data/lib/ftp_paradise/interactive_ftp/show.rb +0 -184
  97. data/lib/ftp_paradise/interactive_ftp/upload.rb +0 -90
  98. data/lib/ftp_paradise/interactive_ftp/user_input.rb +0 -53
  99. data/lib/ftp_paradise/toplevel_methods/can_connect_to_remote_site.rb +0 -28
  100. data/lib/ftp_paradise/toplevel_methods/clear_user_dataset.rb +0 -28
  101. data/lib/ftp_paradise/toplevel_methods/data.rb +0 -31
  102. data/lib/ftp_paradise/toplevel_methods/determine_user_dataset_from_this_hash.rb +0 -37
@@ -0,0 +1,2321 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ # === FtpParadise::Shell
6
+ #
7
+ # This class can be used for an interactive usage of the FTP paradise
8
+ # project. It can be used to connect to remote FTP hosts.
9
+ #
10
+ # This class provides a commandline variant of the FtpParadise project,
11
+ # which allows you to interactively issue commands and instructions
12
+ # to a remote FTP server.
13
+
14
+ # Usage example:
15
+ #
16
+ # FtpParadise::Shell.new(ARGV)
17
+ # =========================================================================== #
18
+ # The official source for Ruby-FTP can be found at:
19
+ #
20
+ # https://www.ruby-doc.org/stdlib/libdoc/net/ftp/rdoc/Net/FTP.html
21
+ #
22
+ # =========================================================================== #
23
+ # require 'ftp_paradise/shell/shell.rb'
24
+ # =========================================================================== #
25
+ require 'ftp_paradise/requires/require_class_connection.rb'
26
+
27
+ module FtpParadise
28
+
29
+ class Shell # === FtpParadise::Shell
30
+
31
+ require 'ftp_paradise/base/base.rb'
32
+ include FtpParadise::Base
33
+
34
+ require 'ftp_paradise/shell/menu.rb'
35
+
36
+ require 'ftp_paradise/requires/require_the_toplevel_methods.rb'
37
+
38
+ require 'ftp_paradise/configuration/configuration.rb'
39
+
40
+ require 'ftp_paradise/version/version.rb'
41
+
42
+ begin
43
+ require 'verbose_truth'
44
+ rescue LoadError; end
45
+
46
+ begin
47
+ require 'readline'
48
+ rescue LoadError; end # Silent rescue.
49
+
50
+ # ========================================================================= #
51
+ # === NAMESPACE
52
+ # ========================================================================= #
53
+ NAMESPACE = inspect
54
+
55
+ # ========================================================================= #
56
+ # === TITLE
57
+ # ========================================================================= #
58
+ TITLE = 'Interactive FTP shell'
59
+
60
+ # ========================================================================= #
61
+ # === SHOW_REMOTE_FILES_UPON_SUCCESSFUL_LOGIN
62
+ #
63
+ # If this constant is true then we will show the remote file
64
+ # listing upon a successful (first) login action.
65
+ # ========================================================================= #
66
+ SHOW_REMOTE_FILES_UPON_SUCCESSFUL_LOGIN = false
67
+
68
+ # ========================================================================= #
69
+ # === SHALL_WE_DEBUG
70
+ # ========================================================================= #
71
+ SHALL_WE_DEBUG = true
72
+
73
+ # ========================================================================= #
74
+ # === PROMPT_TO_USE
75
+ #
76
+ # Which Prompt to use by default for the Interactive FTP component.
77
+ # ========================================================================= #
78
+ PROMPT_TO_USE = '> '
79
+
80
+ # ========================================================================= #
81
+ # === ARRAY_FORBIDDEN_HISTORY_COMMANDS
82
+ # ========================================================================= #
83
+ ARRAY_FORBIDDEN_HISTORY_COMMANDS = %w(
84
+ last
85
+ ) # Dont append last to the history.
86
+
87
+ # ========================================================================= #
88
+ # === OPEN_IN_DEFAULT_EDITOR
89
+ # ========================================================================= #
90
+ OPEN_IN_DEFAULT_EDITOR = true
91
+
92
+ # ========================================================================= #
93
+ # === USE_THIS_EDITOR
94
+ # ========================================================================= #
95
+ USE_THIS_EDITOR = ENV['EDITOR'].to_s
96
+
97
+ # ========================================================================= #
98
+ # === DEFAULT_LOCAL_DIRECTORY
99
+ # ========================================================================= #
100
+ DEFAULT_LOCAL_DIRECTORY = ::FtpParadise.rds("#{Dir.pwd}/") # More flexible that way, I suppose.
101
+
102
+ # ========================================================================= #
103
+ # === NAME_OF_THIS_FILE
104
+ # ========================================================================= #
105
+ NAME_OF_THIS_FILE = "#{PROJECT_BASE_DIRECTORY}shell/shell.rb"
106
+
107
+ # ========================================================================= #
108
+ # === ARRAY_PROJECT_FILES
109
+ #
110
+ # The following files have to be opened when you wish to open the
111
+ # project files.
112
+ # ========================================================================= #
113
+ ARRAY_PROJECT_FILES = %w(
114
+ library.rb
115
+ interactive.rb
116
+ addon/constants/ftp_constants.rb
117
+ doc/TODO
118
+ ).map {|entry| PROJECT_BASE_DIRECTORY+entry}
119
+
120
+ # ========================================================================= #
121
+ # === DEFAULT_REMOTE_DIRECTORY
122
+ #
123
+ # The default remote directory.
124
+ # ========================================================================= #
125
+ DEFAULT_REMOTE_DIRECTORY = %q(
126
+ htdocs
127
+ ).delete("\n").strip # kill newlines and empty spaces.
128
+
129
+ # ========================================================================= #
130
+ # === DEFAULT_REMOTE_FILE
131
+ #
132
+ # The default remote file comes next.
133
+ # ========================================================================= #
134
+ DEFAULT_REMOTE_FILE = %q(
135
+ README.md
136
+ ).gsub(/\n/,'').strip
137
+
138
+ # ========================================================================= #
139
+ # === initialize
140
+ # ========================================================================= #
141
+ def initialize(
142
+ commandline_arguments = nil,
143
+ run_already = true
144
+ )
145
+ register_sigint # Register sigint before calling reset().
146
+ reset
147
+ set_commandline_arguments(
148
+ commandline_arguments
149
+ )
150
+ set_run_mode(:standalone) # Purposely defined before run(). This way, we can change it.
151
+ run if run_already
152
+ end
153
+
154
+ # ========================================================================= #
155
+ # === reset (reset tag)
156
+ #
157
+ # Initialize and/or reset the variables used in this class.
158
+ # ========================================================================= #
159
+ def reset
160
+ super()
161
+ # ======================================================================= #
162
+ # === @namespace
163
+ # ======================================================================= #
164
+ @namespace = NAMESPACE
165
+ # ======================================================================= #
166
+ # === @internal_hash
167
+ # ======================================================================= #
168
+ @internal_hash = {} unless instance_variable_defined?('@internal_hash')
169
+ # ======================================================================= #
170
+ # === :connection
171
+ # ======================================================================= #
172
+ @internal_hash[:connection] = FtpParadise::Connection.new(:dont_run_yet)
173
+ # ======================================================================= #
174
+ # === :try_to_use_readline
175
+ #
176
+ # This variable will instruct this shell to make use of readline, or
177
+ # not. It is initially set to true, meaning that we will try to
178
+ # make use of the Readline module, if readline is available on
179
+ # the given computer system at hand.
180
+ # ======================================================================= #
181
+ @internal_hash[:try_to_use_readline] = true
182
+ # ======================================================================= #
183
+ # === :may_we_exit
184
+ #
185
+ # This variable determines whether we may exit from the interactive
186
+ # shell or whether we may not.
187
+ # ======================================================================= #
188
+ @internal_hash[:may_we_exit] = false
189
+ # ======================================================================= #
190
+ # === :use_this_editor
191
+ #
192
+ # Specify which editor we may use - this can be overruled in the
193
+ # interactive menu by the user of the FtpParadise project.
194
+ # ======================================================================= #
195
+ @internal_hash[:use_this_editor] = USE_THIS_EDITOR
196
+ # ======================================================================= #
197
+ # === :debug
198
+ #
199
+ # Whether we will debug or not, by default.
200
+ # ======================================================================= #
201
+ @internal_hash[:debug] = SHALL_WE_DEBUG
202
+ # ======================================================================= #
203
+ # === :padding_to_use
204
+ # ======================================================================= #
205
+ @internal_hash[:padding_to_use] = ' ' # The default padding to use.
206
+ # ======================================================================= #
207
+ # === :array_downloaded_files
208
+ #
209
+ # Which files we did download so far.
210
+ # ======================================================================= #
211
+ @internal_hash[:array_downloaded_files] = []
212
+ # ======================================================================= #
213
+ # === :history
214
+ # ======================================================================= #
215
+ @internal_hash[:history] = []
216
+ # ======================================================================= #
217
+ # === :user_input
218
+ #
219
+ # Must "initialize" the user_input variable to nil here.
220
+ # ======================================================================= #
221
+ @internal_hash[:user_input] = nil
222
+ # ======================================================================= #
223
+ # === :array_history_remote_directories
224
+ #
225
+ # This array keeps a listing of all remote directories we rcd-ed into.
226
+ # ======================================================================= #
227
+ @internal_hash[:array_history_remote_directories] = []
228
+ reset_instance_variables_that_hold_all_arguments
229
+ load_config
230
+ set_file
231
+ set_local_directory
232
+ end
233
+
234
+ # ========================================================================= #
235
+ # === show_ftp_docu
236
+ #
237
+ # This method will show where to find ruby's ftp docu.
238
+ # ========================================================================= #
239
+ def show_ftp_docu
240
+ e
241
+ e ' https://www.ruby-doc.org/stdlib/libdoc/net/ftp/rdoc/Net/FTP.html'
242
+ e
243
+ end
244
+
245
+ # ========================================================================= #
246
+ # === set_active
247
+ # ========================================================================= #
248
+ def set_active
249
+ ftp_connection?.set_active
250
+ end
251
+
252
+ # ========================================================================= #
253
+ # === set_login
254
+ # ========================================================================= #
255
+ def set_login(i)
256
+ ftp_connection?.set_login_name(i)
257
+ end
258
+
259
+ # ========================================================================= #
260
+ # === login_name?
261
+ # ========================================================================= #
262
+ def login_name?
263
+ ftp_connection?.login_name?
264
+ end
265
+
266
+ # ========================================================================= #
267
+ # === show_available_connections
268
+ # ========================================================================= #
269
+ def show_available_connections(
270
+ i = ARRAY_AVAILABLE_HOSTS
271
+ )
272
+ i.each_with_index {|entry, index|
273
+ e "#{index} #{entry}"
274
+ } if Object.const_defined? :RoebeFtpConstants
275
+ end
276
+
277
+ # ========================================================================= #
278
+ # === connect_to_this_remote_url
279
+ # ========================================================================= #
280
+ def connect_to_this_remote_url(
281
+ i = remote_url?,
282
+ be_verbose = :be_verbose
283
+ )
284
+ case be_verbose
285
+ when :be_verbose
286
+ be_verbose = true
287
+ end
288
+ if be_verbose
289
+ e "Connecting to this remote URL: #{sfancy(i)}"
290
+ end
291
+ FtpParadise.use_this_as_ftp_object(
292
+ FtpParadise::Connection.new(i)
293
+ )
294
+ ftp_connection?.login(
295
+ FtpParadise.login_name?,
296
+ password?
297
+ )
298
+ end
299
+
300
+ # ========================================================================= #
301
+ # === download_remote_file (download tag)
302
+ #
303
+ # This method will download a remote file. When we download a remote
304
+ # file, we will also set the remote base directory since Dec 2011.
305
+ # ========================================================================= #
306
+ def download_remote_file(
307
+ file = DEFAULT_REMOTE_FILE
308
+ )
309
+ file = DEFAULT_REMOTE_FILE if file.nil?
310
+ if file.include? '*'
311
+ file = ftp_connection?.find_matches_for(file)
312
+ end
313
+ if file.is_a? Array
314
+ file.each {|the_file| download_remote_file(the_file) }
315
+ else
316
+ if file =~ /^\d+$/ # if is a number. DEBUG HERE THOUGH.
317
+ ftp_connection?.update
318
+ file = ftp_connection?.array_file_listing[file.to_i - 1][0]
319
+ end
320
+ set_remote_directory(file)
321
+ unless file == '*'
322
+ opne 'Trying to download `'+sfile(file)+'` now.'
323
+ # return_value = ftp_connection?.download(file)
324
+ result = ftp_connection?.download(file) # Delegate to the parent class.
325
+ if result
326
+ @internal_hash[:array_downloaded_files] << file
327
+ set_file(File.basename(file)) # setting new again.
328
+ if open_in_default_editor? # Works on @file now, as we did set it before.
329
+ open_this_file_in_editor(file?)
330
+ end
331
+ else
332
+ opne 'An exception occurred - you probably lack permissions to'
333
+ opne 'download that remote file.'
334
+ end
335
+ end
336
+ end
337
+ end
338
+
339
+ # ========================================================================= #
340
+ # === show_www_component
341
+ # ========================================================================= #
342
+ def show_www_component
343
+ e 'Make sure to visit:'
344
+ path = '$RSRC/ftp_paradise/lib/ftp_paradise/www/sinatra_web_interface.rb'
345
+ e " #{sfancy(path)}"
346
+ _ = get_env_of("ruby #{path}")
347
+ esystem _
348
+ end
349
+
350
+ # ========================================================================= #
351
+ # === automatically_connect_on_startup_of_the_interactive_ftp_shell?
352
+ # ========================================================================= #
353
+ def automatically_connect_on_startup_of_the_interactive_ftp_shell?
354
+ _ = FILE_AUTOMATICALLY_CONNECT_ON_STARTUP_OF_THE_INTERACTIVE_FTP_SHELL
355
+ if File.exist? _
356
+ YAML.load_file(_)
357
+ else
358
+ false # In this case we default to false.
359
+ end
360
+ end
361
+
362
+ # ========================================================================= #
363
+ # === show_ftp_yaml_file
364
+ # ========================================================================= #
365
+ def show_ftp_yaml_file
366
+ e 'The yaml file in question can be found at:'
367
+ e
368
+ e " #{sfile(FILE_ROEBE_FTP)}"
369
+ e
370
+ end
371
+
372
+ # ========================================================================= #
373
+ # === show_history
374
+ #
375
+ # This method can be used to display the input-history of the user.
376
+ # ========================================================================= #
377
+ def show_history # History tag.
378
+ e "The history for #{sfancy(return_title)} is:"
379
+ @internal_hash[:history].each_with_index { |key, index|
380
+ e '%3s' % (index+1).to_s+' '+key
381
+ }
382
+ end
383
+
384
+ # ========================================================================= #
385
+ # ==== history?
386
+ # ========================================================================= #
387
+ def history?
388
+ @internal_hash[:history]
389
+ end
390
+
391
+ # ========================================================================= #
392
+ # === use_readline?
393
+ # ========================================================================= #
394
+ def use_readline?
395
+ @internal_hash[:try_to_use_readline]
396
+ end; alias do_we_use_readline? use_readline? # === do_we_use_readline?
397
+
398
+ # ========================================================================= #
399
+ # === move_local_file
400
+ # ========================================================================= #
401
+ def move_local_file(from, to)
402
+ e 'Next moving (local) file from '+sfile(from)+' to '+sfile(to)+'.'
403
+ if File.exist? from
404
+ FileUtils.mv(from, to)
405
+ else
406
+ e 'No (local) file called '+sfile(from)+' could be found.'
407
+ end
408
+ end
409
+
410
+ # ========================================================================= #
411
+ # === toggle_show_full_names
412
+ # ========================================================================= #
413
+ def toggle_show_full_names
414
+ config?.show_full_names = ! config?.show_full_names
415
+ end
416
+
417
+ # ========================================================================= #
418
+ # === do_not_show_full_names
419
+ # ========================================================================= #
420
+ def do_not_show_full_names
421
+ ftp_connection?.show_full_names = false
422
+ config?.show_full_names = false # Sync.
423
+ end
424
+
425
+ # ========================================================================= #
426
+ # === show_local_entries
427
+ # ========================================================================= #
428
+ def show_local_entries
429
+ show_local_files(false)
430
+ end
431
+
432
+ # ========================================================================= #
433
+ # === return_local_files
434
+ #
435
+ # Return local files. Directories will not be included here.
436
+ # ========================================================================= #
437
+ def return_local_files
438
+ entries = Dir['*']
439
+ entries = Dir[return_pwd+'*'] if show_full_names? # Overrule in this case.
440
+ entries.reject! {|entry| File.directory? entry }
441
+ return entries
442
+ end; alias file_listing return_local_files # === file_listing
443
+
444
+ # ========================================================================= #
445
+ # === report_file
446
+ #
447
+ # Here we simply report which file we would upload.
448
+ # ========================================================================= #
449
+ def report_file
450
+ if file?
451
+ e 'The file that we would upload is: '
452
+ e " #{sfile(file?)}"
453
+ else
454
+ e 'No file was specified yet.'
455
+ end
456
+ end
457
+
458
+ # ========================================================================= #
459
+ # === do_not_use_readline
460
+ # ========================================================================= #
461
+ def do_not_use_readline
462
+ @internal_hash[:try_to_use_readline] = false
463
+ end
464
+
465
+ # ========================================================================= #
466
+ # === enable_readline
467
+ # ========================================================================= #
468
+ def enable_readline
469
+ @internal_hash[:try_to_use_readline] = true
470
+ try_to_use_readline
471
+ end
472
+
473
+ # ========================================================================= #
474
+ # === show_modtime_of
475
+ # ========================================================================= #
476
+ def show_modtime_of(i)
477
+ e "The modification time of #{sfile(i)} is:"
478
+ e
479
+ e ' '+sfancy(ftp_connection?.modification_time_of?(i))
480
+ e
481
+ end
482
+
483
+ # ========================================================================= #
484
+ # === debug_it
485
+ # ========================================================================= #
486
+ def debug_it # debug tag
487
+ ftp_connection?.debug(true)
488
+ # pp ftp_connection?.array_file_listing
489
+ end
490
+
491
+ # ========================================================================= #
492
+ # === debug?
493
+ # ========================================================================= #
494
+ def debug?
495
+ @internal_hash[:debug]
496
+ end
497
+
498
+ # ========================================================================= #
499
+ # === set_local_directory
500
+ # ========================================================================= #
501
+ def set_local_directory(
502
+ i = return_pwd
503
+ )
504
+ i = i.to_s.dup
505
+ i << '/' unless i.end_with? '/'
506
+ i = FtpParadise.rds(i)
507
+ @internal_hash[:local_directory] = i
508
+ end
509
+
510
+ # ========================================================================= #
511
+ # === password?
512
+ # ========================================================================= #
513
+ def password?
514
+ FtpParadise.password?
515
+ end
516
+
517
+ # ========================================================================= #
518
+ # === toggle_modes
519
+ # ========================================================================= #
520
+ def toggle_modes
521
+ case ftp_transfer_mode?
522
+ when :ascii
523
+ set_transfer_mode :binary
524
+ else
525
+ set_transfer_mode :ascii
526
+ end
527
+ e transfer_mode?.to_s
528
+ end
529
+
530
+ # ========================================================================= #
531
+ # === this_remote_entry_exists?
532
+ # ========================================================================= #
533
+ def this_remote_entry_exists?(i)
534
+ does_it_exist = false
535
+ does_it_exist = true if is_dir? i # This will also check whether it exists.
536
+ does_it_exist = true if is_file? i
537
+ return does_it_exist
538
+ end
539
+
540
+ # ========================================================================= #
541
+ # === show_date_sorted_entries
542
+ #
543
+ # This method will show the sorted entries of the given remote directory
544
+ # at hand.
545
+ # ========================================================================= #
546
+ def show_date_sorted_entries
547
+ dataset = ftp_connection?.array_file_listing?
548
+ reverse_sort_dateset = dataset.sort_by {|_a,_b_,_c, timestamp|
549
+ timestamp
550
+ }.reverse
551
+ ftp_connection?.show_remote_listing(reverse_sort_dateset)
552
+ end
553
+
554
+ # ========================================================================= #
555
+ # === upload (upload tag)
556
+ #
557
+ # Use this method to upload something locally to the remote site.
558
+ #
559
+ # You can also upload several files in one go - to do this, try
560
+ # one of these ways:
561
+ #
562
+ # upload 7,8 # This would upload file position 7 and 8.
563
+ # upload 1..293
564
+ #
565
+ # ========================================================================= #
566
+ def upload(
567
+ i = Dir['*']
568
+ )
569
+ # ======================================================================= #
570
+ # We will always work with an Array past the following point.
571
+ # ======================================================================= #
572
+ i = [i].flatten.compact # Safeguard against nil.
573
+ if i.empty?
574
+ i << file? if file?
575
+ end
576
+ i.map! {|entry|
577
+ if entry.include?('-') and !entry.include?('.') # Assume a range was given like 1-20.
578
+ splitted = entry.split('-')
579
+ entry = (splitted[0] .. splitted[1]).to_a
580
+ elsif entry.include?('..') # Assume a range such as: upload 1..25
581
+ entry =~ /(\d+)\.\.(\d+)/
582
+ start_position = $1.to_s.dup.to_i
583
+ end_position = $2.to_s.dup.to_i
584
+ entry = return_local_files[start_position, end_position]
585
+ elsif entry.include?(',')
586
+ splitted = i.split(',')
587
+ entry = (splitted[0] .. splitted[1]).to_a
588
+ elsif (entry == 'ALL') or (entry == '*')
589
+ entry = Dir['*']
590
+ elsif entry.include?('*.') or entry.include?('*')
591
+ entry = Dir[entry]
592
+ end
593
+ entry
594
+ }
595
+ i.flatten!
596
+ i.compact!
597
+ if on_roebe? and !is_connected?
598
+ connect_to :shevy
599
+ end
600
+ i.each {|this_file|
601
+ if this_file =~ /^\d+$/ # upload only a specific number.
602
+ sorted = Dir['*'].sort
603
+ if i.is_a? Array
604
+ i = i.first
605
+ end
606
+ this_file = sorted[i.to_i - 1]
607
+ end
608
+ _ = this_file # default to upload to 'all'
609
+ if File.exist?(_)
610
+
611
+ # =================================================================== #
612
+ # Next, some files will always be in binary mode. These are
613
+ # defined in the Array ARRAY_BINARY_FILES.
614
+ # =================================================================== #
615
+ if ARRAY_BINARY_FILES.include?(File.extname(_).delete('.')) and
616
+ (ftp_transfer_mode? != :binary)
617
+ use_binary_mode
618
+ end
619
+ case ftp_transfer_mode?
620
+ # =================================================================== #
621
+ # === :ascii
622
+ # =================================================================== #
623
+ when :ascii
624
+ set_file(_)
625
+ ftp_connection?.upload(_) # And now, call the functionality in the FTP lib.
626
+ else
627
+ ftp_connection?.upload_binary(_)
628
+ end
629
+ else
630
+ opne swarn('But the file `')+
631
+ sfile(_)+
632
+ swarn('` does not exist.')
633
+ end
634
+ }
635
+ end
636
+
637
+ # ========================================================================= #
638
+ # === display_configuration_options (show config tag)
639
+ #
640
+ # This method will show the configuration settings.
641
+ #
642
+ # You can invoke this in an interactive FTP session by doing this:
643
+ #
644
+ # config?
645
+ #
646
+ # ========================================================================= #
647
+ def display_configuration_options # Config tag.
648
+ cliner {
649
+ if file?.to_s.empty?
650
+ e '@file is: unassigned as of yet'
651
+ else
652
+ e '@file is: '+sfancy(file?.to_s)
653
+ end
654
+ e '@internal_hash[:local_directory] is: '+
655
+ sfancy(@internal_hash[:local_directory].to_s)
656
+ e '@splitted is: '+sfancy(splitted?.to_s)
657
+ e 'Will we use the Readline module? '+
658
+ sfancy(verbose_truth(use_readline?))
659
+ e 'Will we show full names (with full path)? '+
660
+ sfancy(verbose_truth(show_full_names?))
661
+ e 'What is the base directory? '+
662
+ sfancy(config?.base_directory.to_s)
663
+ }
664
+ end
665
+
666
+ # ========================================================================= #
667
+ # === load_config
668
+ #
669
+ # This method will load the configuration for this class.
670
+ # ========================================================================= #
671
+ def load_config
672
+ #FtpParadise.yaml_directory?
673
+ # @config = ::Roebe::Configuration::Configuration.new(FtpParadise.yaml_directory?)
674
+ @internal_hash[:config] = FtpParadise.configuration?
675
+ @internal_hash[:open_in_default_editor] = OPEN_IN_DEFAULT_EDITOR
676
+ if config?.has_entry? 'open_in_default_editor'
677
+ @internal_hash[:open_in_default_editor] = config?.open_in_default_editor
678
+ end
679
+ if config?.respond_to? :debug
680
+ @internal_hash[:debug] = config?.debug # Obtain (or rather, overrule) the @debug variable.
681
+ end
682
+ end
683
+
684
+ # ========================================================================= #
685
+ # === open_in_default_editor?
686
+ # ========================================================================= #
687
+ def open_in_default_editor?
688
+ @internal_hash[:open_in_default_editor]
689
+ end
690
+
691
+ # ========================================================================= #
692
+ # === config?
693
+ # ========================================================================= #
694
+ def config?
695
+ @internal_hash[:config]
696
+ end
697
+
698
+ # ========================================================================= #
699
+ # === enable_anonymous_login
700
+ #
701
+ # We use this method to enable anonymous logins.
702
+ # ========================================================================= #
703
+ def enable_anonymous_login
704
+ opne 'We will enable anonymous login now.'
705
+ set_password :anonymous
706
+ set_user_name 'anonymous'
707
+ end
708
+
709
+ # ========================================================================= #
710
+ # === ftp_transfer_mode?
711
+ #
712
+ # ftp_transfer_mode is a Symbol, hence we will not apply .to_s on it.
713
+ # ========================================================================= #
714
+ def ftp_transfer_mode?
715
+ return @internal_hash[:ftp_transfer_mode]
716
+ end; alias mode? ftp_transfer_mode? # === mode?
717
+
718
+ # ========================================================================= #
719
+ # === disable
720
+ # ========================================================================= #
721
+ def disable(i = nil)
722
+ i = i.to_s.to_sym
723
+ case i
724
+ # ======================================================================= #
725
+ # === :base_directory
726
+ # ======================================================================= #
727
+ when :base_directory,
728
+ :full_names
729
+ do_not_show_full_names
730
+ # ======================================================================= #
731
+ # === :debug
732
+ # ======================================================================= #
733
+ when :debug
734
+ config?.debug = false
735
+ ftp_connection?.disable_debug
736
+ save_config
737
+ end
738
+ e 'Disabling '+sfancy(i.to_s)+' now.' unless i.to_s.empty?
739
+ end
740
+
741
+ # ========================================================================= #
742
+ # === show_which_files_we_did_download_so_far
743
+ # ========================================================================= #
744
+ def show_which_files_we_did_download_so_far
745
+ if array_downloaded_files?.empty?
746
+ e 'We did not yet download any file.'
747
+ else
748
+ e 'We downloaded these files so far:'
749
+ pp array_downloaded_files?
750
+ end
751
+ end
752
+
753
+ # ========================================================================= #
754
+ # === report_local_directory
755
+ #
756
+ # Use only this method when reporting the local directory.
757
+ # ========================================================================= #
758
+ def report_local_directory
759
+ e 'The local directory is: '+N+
760
+ @internal_hash[:padding_to_use]+
761
+ sdir(return_pwd)
762
+ end; alias report_local_dir report_local_directory # === report_local_dir
763
+
764
+ # ========================================================================= #
765
+ # === move_remote_file
766
+ #
767
+ # We expect an Array as input.
768
+ #
769
+ # To test this method, do:
770
+ #
771
+ # rmv DONE_Prüfungsfragen_Hartig_Einheiten_2_3_5_9_10_11_12_15_16_21.pdf PDFs/
772
+ # mmv vimrc vim
773
+ #
774
+ # ========================================================================= #
775
+ def move_remote_file(i)
776
+ from = i[0]
777
+ to = i[1]
778
+ if is_directory?(to)
779
+ to << '/' unless to.end_with? '/'
780
+ to << File.basename(from)
781
+ end
782
+ e 'Next moving from '+sfancy(from)+' to '+sfancy(to)+'.'
783
+ ftp_connection?.move_file(from, to)
784
+ end
785
+
786
+ # ========================================================================= #
787
+ # === disconnect
788
+ #
789
+ # Disconnect the remote connection by invoking the quit() method on
790
+ # the FTP object.
791
+ # ========================================================================= #
792
+ def disconnect(be_verbose = true)
793
+ if ftp_connection?.did_we_connect?
794
+ e 'Disconnected from `'+coloured_remote_host?+'`.' if be_verbose
795
+ end
796
+ ftp_connection?.quit
797
+ exit
798
+ end
799
+
800
+ # ========================================================================= #
801
+ # === set_remote_directory
802
+ # ========================================================================= #
803
+ def set_remote_directory(i)
804
+ i = File.dirname(i) if ftp_connection?.is_file?(i) # Get the base directory here.
805
+ @internal_hash[:remote_directory] = i
806
+ @internal_hash[:array_history_remote_directories] << @internal_hash[:remote_directory]
807
+ end
808
+
809
+ # ========================================================================= #
810
+ # === remote_change_directory
811
+ #
812
+ # This method can be used to change directory on the remote host.
813
+ #
814
+ # An argument such as :show_remote_file_listing can be passed as second
815
+ # argument to this method, in which case we will list the content of
816
+ # the remote directory after the cd-action.
817
+ #
818
+ # If readline is used, as determined by the instance variabl
819
+ # @internal_hash[:try_to_use_readline] then we will attempt
820
+ # to cd-<TAB>.
821
+ #
822
+ # Invocation example:
823
+ #
824
+ # rcd htdocs
825
+ #
826
+ # ========================================================================= #
827
+ def remote_change_directory(
828
+ i = f?,
829
+ optional_instruction = nil,
830
+ be_verbose = false
831
+ )
832
+ i = i.first if i.is_a? Array
833
+ i = '..' if i.nil? # ← Tiny "safeguard".
834
+ # ======================================================================= #
835
+ # We must first check whether we input only numbers,
836
+ # and whether such a directory does NOT exist.
837
+ # ======================================================================= #
838
+ if (i =~ /^\d+$/) and !is_dir?(i)
839
+ ftp_connection?.update_file_listing
840
+ i = ftp_connection?.array_file_listing[i.to_i - 1]
841
+ end
842
+ if be_verbose
843
+ e "Trying to cd into the remote directory `#{sfancy(i)}`."
844
+ end
845
+ case i # case tag
846
+ when '?' # intercept ?
847
+ e 'You went into these remote directories so far:'
848
+ @internal_hash[:array_history_remote_directories].each { |entry|
849
+ e "- #{entry}"
850
+ }
851
+ else # This is the default.
852
+ if i
853
+ i.squeeze!('/') if i.include? '//' # Get rid of multiple //.
854
+ e "Changing remote directory to `#{sdir(i)}` now."
855
+ end
856
+ begin
857
+ ftp_connection?.chdir(i)
858
+ set_remote_directory(i)
859
+ if optional_instruction
860
+ case optional_instruction
861
+ when :show_remote_file_listing
862
+ show_remote_files
863
+ end
864
+ end
865
+ rescue Exception => error
866
+ pp error
867
+ end
868
+ end
869
+ end; alias remote_cd remote_change_directory # === remote_cd
870
+
871
+ # ========================================================================= #
872
+ # === create_directory
873
+ #
874
+ # This method will create a local directory.
875
+ # ========================================================================= #
876
+ def create_directory(
877
+ i, be_verbose = false
878
+ )
879
+ be_verbose = true if be_verbose == :be_verbose
880
+ e 'Now creating local directory '+sdir(i)+'.' if be_verbose
881
+ FileUtils.mkdir_p(i)
882
+ end
883
+
884
+ # ========================================================================= #
885
+ # === show_colours
886
+ # ========================================================================= #
887
+ def show_colours # Use this to show the colours.
888
+ pp Colours.colours?
889
+ end
890
+
891
+ # ========================================================================= #
892
+ # === return_local_entries
893
+ #
894
+ # Returns all local entries.
895
+ # ========================================================================= #
896
+ def return_local_entries
897
+ entries = Dir['*']
898
+ entries = Dir[return_pwd+'*'] if show_full_names? # Overrule in this case.
899
+ return entries
900
+ end
901
+
902
+ # ========================================================================= #
903
+ # === remote_directory?
904
+ # ========================================================================= #
905
+ def remote_directory?
906
+ @internal_hash[:remote_directory]
907
+ end
908
+
909
+ # ========================================================================= #
910
+ # === upload_directory
911
+ # ========================================================================= #
912
+ def upload_directory(i)
913
+ ftp_connection?.upload_directory(i)
914
+ end
915
+
916
+ # ========================================================================= #
917
+ # === upload_this_file
918
+ # ========================================================================= #
919
+ def upload_this_file(
920
+ i = f?
921
+ )
922
+ if i.is_a? Array
923
+ i.each {|entry| upload_this_file(entry) }
924
+ else
925
+ e "Trying to upload this file `#{sfile(i)}` next:"
926
+ ftp_connection?.puttextfile(i)
927
+ end
928
+ end
929
+
930
+ # ========================================================================= #
931
+ # === coloured_remote_host?
932
+ # ========================================================================= #
933
+ def coloured_remote_host?
934
+ sfancy(remote_host?)
935
+ end
936
+
937
+ # ========================================================================= #
938
+ # === stat_remote_file (stat tag)
939
+ #
940
+ # This method can be called via '?33' for instance, or via 'stat 33'.
941
+ # ========================================================================= #
942
+ def stat_remote_file(i)
943
+ file = ftp_connection?[i] # Obtain that file.
944
+ matches = ftp_connection?.array_file_listing.select {|key,value| key == file }
945
+ matches.each { |entry|
946
+ e ' '+entry[0]+': '+sfancy(entry[2]+' KB')
947
+ }
948
+ end
949
+
950
+ # ========================================================================= #
951
+ # === has_unwanted_file_suffix?
952
+ #
953
+ # The following method will return true or false.
954
+ #
955
+ # I needed it so that the editor does not open every file that was
956
+ # thrown at it.
957
+ # ========================================================================= #
958
+ def has_unwanted_file_suffix?(i)
959
+ return_value = false
960
+ case File.extname(i).delete('.')
961
+ when 'xz'
962
+ return_value = true
963
+ end
964
+ return return_value
965
+ end
966
+
967
+ # ========================================================================= #
968
+ # === set_password
969
+ # ========================================================================= #
970
+ def set_password(
971
+ i, be_verbose = be_verbose?
972
+ )
973
+ i = i.to_s
974
+ if be_verbose
975
+ e "Setting password to #{sfancy(i)} now."
976
+ end
977
+ FtpParadise.set_password(i)
978
+ end
979
+
980
+ # ========================================================================= #
981
+ # === set_editor
982
+ # ========================================================================= #
983
+ def set_editor(
984
+ i, be_verbose = true
985
+ )
986
+ i = i.first if i.is_a? Array
987
+ if be_verbose
988
+ opnn; e "Now using the editor called `#{sfancy(i)}`."
989
+ end
990
+ @internal_hash[:use_this_editor] = i
991
+ end
992
+
993
+ # ========================================================================= #
994
+ # === use_this_editor?
995
+ # ========================================================================= #
996
+ def use_this_editor?
997
+ @internal_hash[:use_this_editor]
998
+ end
999
+
1000
+ # ========================================================================= #
1001
+ # === try_to_use_readline?
1002
+ # ========================================================================= #
1003
+ def try_to_use_readline?
1004
+ @internal_hash[:try_to_use_readline]
1005
+ end
1006
+
1007
+ # ========================================================================= #
1008
+ # === connection?
1009
+ # ========================================================================= #
1010
+ def connection?
1011
+ @internal_hash[:connection]
1012
+ end; alias ftp? connection? # === ftp?
1013
+ alias ftp_object? connection? # === ftp_object?
1014
+ alias ftp_connection? connection? # === ftp_connection?
1015
+
1016
+ # ========================================================================= #
1017
+ # === change_local_and_remote_directories
1018
+ #
1019
+ # We combine local cd and remote cd here.
1020
+ # ========================================================================= #
1021
+ def change_local_and_remote_directories(
1022
+ target = DEFAULT_LOCAL_DIRECTORY
1023
+ )
1024
+ change_directory(target, :be_silent) # Mandatory since as of 01.05.2011
1025
+ if are_we_connected?
1026
+ remote_change_directory(target) # Since as of August 2011.
1027
+ end
1028
+ end
1029
+
1030
+ # ========================================================================= #
1031
+ # === set_file
1032
+ #
1033
+ # Use only this method to assign the @instance_variable[:file]
1034
+ # variable.
1035
+ # ========================================================================= #
1036
+ def set_file(i = nil)
1037
+ if i # Safeguard against nil.
1038
+ i = i.first if i.is_a? Array
1039
+ i = i.to_s
1040
+ i = return_pwd+i if !i.include?('/') # Since Dec 2011 we try to use only the absolute path.
1041
+ unless File.exist?(i)
1042
+ i << '.c' unless i.include? '.' # Append .c to files, unless the file exists.
1043
+ end
1044
+ i = FtpParadise.rds(i)
1045
+ end
1046
+ @internal_hash[:file] = i # This is the only allowed way to modify @file.
1047
+ end
1048
+
1049
+ # ========================================================================= #
1050
+ # === show_help (help tag)
1051
+ # ========================================================================= #
1052
+ def show_help
1053
+ cliner_violet
1054
+ e "Try one of these #{sfancy('help options')} for interactive-ftp:#{N}#{N}"
1055
+ e parens(:assign)+' '+pound_token+'Assign to the '\
1056
+ '@internal_hash[:file] variable'
1057
+ e parens(:help)+' '+pound_token+'To see the help section'
1058
+ e parens(:history)+' '+pound_token+'To show the history'
1059
+ e parens(:cd)+' '+pound_token+'Change local directory'
1060
+ e parens(:config)+' '+pound_token+'Show the configuration'
1061
+ e parens(:dated)+' '+pound_token+'Display the remote directory '\
1062
+ 'content in a time-sorted manner'
1063
+ e parens(:edit)+' '+pound_token+'Edit this file here in your main editor'
1064
+ e parens(:everything)+' '+pound_token+'Show everything (username, password, host and so on)'
1065
+ e parens(:login)+' '+pound_token+'Connect to the remote host (alias '\
1066
+ 'to connect_to exists)'
1067
+ e parens(:list)+' '+pound_token+'List remote files'
1068
+ e parens(:last)+' '+pound_token+'Repeat the last action (or show the last action)'
1069
+ e parens(:rcd)+' '+pound_token+'Change remote directory'
1070
+ e parens(:remote?)+' '+pound_token+'List where we are connected'
1071
+ e parens(:stat)+' '+pound_token+'Show information about a file'
1072
+ e parens(:status?)+' '+pound_token+'See the current status of the connection'
1073
+ e parens(:file?)+' '+pound_token+'Shows whether we have a '+
1074
+ 'default file set (which can be used to upload)'
1075
+ e parens(:info)+' '+pound_token+'Shows some information (debug)'
1076
+ e parens(:set_port)+' '+pound_token+'Set the port number'
1077
+ e parens(:q)+' '+pound_token+'To quit/exit'
1078
+ e parens(:quit)+' '+pound_token+'Quit the session'
1079
+ if on_roebe? # Display it only for me.
1080
+ e parens(:shevy)+' '+pound_token+'Connect to shevy'
1081
+ end
1082
+ e parens(:lpwd)+' '+pound_token+'Report the current remote directory'
1083
+ e parens(:pwd)+' '+pound_token+'Report the local directory'+N
1084
+ e parens(:welcome)+' '+pound_token+'Show the welcome-message of the remote FTP server'+N
1085
+ e
1086
+ cliner_violet
1087
+ end; alias show_help_options show_help # === show_help_options
1088
+
1089
+ # ========================================================================= #
1090
+ # === set_passive
1091
+ # ========================================================================= #
1092
+ def set_passive(
1093
+ be_verbose = false
1094
+ )
1095
+ if be_verbose
1096
+ e 'Enabling passive mode for FTP.'
1097
+ end
1098
+ ftp_object?.passive = true if are_we_connected?
1099
+ end
1100
+
1101
+ # ========================================================================= #
1102
+ # === connected_to?
1103
+ #
1104
+ # Feedback where we are connected to.
1105
+ # ========================================================================= #
1106
+ def connected_to?
1107
+ if ftp_connection?.open?
1108
+ report_where_we_are_connected_to
1109
+ report_remote_directory # Added Dec 2011.
1110
+ # report_local_dir
1111
+ # unless ftp?.empty?
1112
+ # e 'The remote file listing is:'
1113
+ # show_remote_listing
1114
+ # end # Disabled the above chunk as of Apr 2017.
1115
+ else
1116
+ e 'We are not connected to any remote FTP server currently.'
1117
+ end
1118
+ end
1119
+
1120
+ # ========================================================================= #
1121
+ # === rename
1122
+ #
1123
+ # This will attempt a remote rename-action.
1124
+ # ========================================================================= #
1125
+ def rename(a, b)
1126
+ begin
1127
+ a = convert_number_to_file(a)
1128
+ ftp_connection?.rename(a, b)
1129
+ rescue Net::FTPPermError
1130
+ e "The file at #{sfile(a)} does not seem to exist - thus, "\
1131
+ "we can not rename it."
1132
+ end
1133
+ end
1134
+
1135
+ # ========================================================================= #
1136
+ # === reset_instance_variables_that_hold_all_arguments
1137
+ #
1138
+ # Use this method to initialite the instance variables that will hold
1139
+ # the arguments to methods, from the user input.
1140
+ # ========================================================================= #
1141
+ def reset_instance_variables_that_hold_all_arguments
1142
+ @internal_hash[:splitted] =
1143
+ @internal_hash[:first_argument] =
1144
+ @internal_hash[:all_arguments] = nil
1145
+ end
1146
+
1147
+ # ========================================================================= #
1148
+ # === report_last_response_code
1149
+ # ========================================================================= #
1150
+ def report_last_response_code
1151
+ e 'The last response code was: '+
1152
+ simp(ftp_connection?.last_response_code.to_s)
1153
+ end
1154
+
1155
+ # ========================================================================= #
1156
+ # === do_show_full_names
1157
+ # ========================================================================= #
1158
+ def do_show_full_names
1159
+ ftp_connection?.show_full_names = true
1160
+ config?.show_full_names = true # Sync.
1161
+ end
1162
+
1163
+ # ========================================================================= #
1164
+ # === will_we_show_full_names
1165
+ # ========================================================================= #
1166
+ def will_we_show_full_names
1167
+ e 'Will we now show full names? '+
1168
+ verbose_truth(show_full_names?)
1169
+ end
1170
+
1171
+ # ========================================================================= #
1172
+ # === report_last_response
1173
+ # ========================================================================= #
1174
+ def report_last_response
1175
+ e 'The last response was: '+
1176
+ simp(ftp_connection?.last_response.to_s)
1177
+ end
1178
+
1179
+ # ========================================================================= #
1180
+ # === check_commandline_arguments (commandline tag)
1181
+ #
1182
+ # This is called from within method enter_loop().
1183
+ # ========================================================================= #
1184
+ def check_commandline_arguments(
1185
+ i = @commandline_arguments
1186
+ )
1187
+ if i.is_a?(String) and i.include?(',') # Here we assume a chained-instruction.
1188
+ i = i.split(',')
1189
+ end
1190
+ i = [i].flatten.compact
1191
+ i.each {|entry|
1192
+ case entry
1193
+ when '',nil # Do nothing in this case.
1194
+ when '--disable-colours','--disable-colors','nocolours','nocol',
1195
+ /^-?-?nocol$/
1196
+ e 'Now disabling colours.'
1197
+ FtpParadise.disable_colours
1198
+ when *ARRAY_HELP_OPTIONS
1199
+ show_commandline_help
1200
+ exit
1201
+ when 'BINARY'
1202
+ set_binary :be_verbose
1203
+ else
1204
+ entry = entry.to_s
1205
+ if File.exist?(entry)
1206
+ set_file(entry)
1207
+ @commandline_arguments.reject! {|line|
1208
+ line.include? entry
1209
+ }
1210
+ end
1211
+ end
1212
+ }
1213
+ end
1214
+
1215
+ # ========================================================================= #
1216
+ # === consider_reporting_file
1217
+ # ========================================================================= #
1218
+ def consider_reporting_file
1219
+ if file?.empty?
1220
+ e 'No file has been assigned yet.'
1221
+ e 'You can set a specific file via '+simp('"set_file"')+'.'
1222
+ else
1223
+ report_file
1224
+ end
1225
+ end
1226
+
1227
+ # ========================================================================= #
1228
+ # === all_arguments?
1229
+ #
1230
+ # The alias a? may be an easier wrapper over the variable
1231
+ # @internal_hash[:all_arguments].
1232
+ # ========================================================================= #
1233
+ def all_arguments?
1234
+ @internal_hash[:all_arguments]
1235
+ end; alias a? all_arguments? # === a?
1236
+
1237
+ # ========================================================================= #
1238
+ # === try_to_chmod_this_remote_file
1239
+ # ========================================================================= #
1240
+ def try_to_chmod_this_remote_file(
1241
+ filename, chmod_value_to_use = '0777'
1242
+ )
1243
+ e "Trying to chmod the remote file #{filename} next."
1244
+ ftp_connection?.sendcmd("SITE CHMOD #{chmod_value_to_use} #{filename}")
1245
+ end
1246
+
1247
+ # ========================================================================= #
1248
+ # === set_name
1249
+ # ========================================================================= #
1250
+ def set_name(i)
1251
+ i = i.to_s
1252
+ e 'Setting user-name to `'+sfancy(i)+'` now.'
1253
+ ftp_connection?.set_user_name(i)
1254
+ end; alias set_user_name set_name # === set_user_name
1255
+
1256
+
1257
+ # ========================================================================= #
1258
+ # === set_commandline_arguments
1259
+ # ========================================================================= #
1260
+ def set_commandline_arguments(i = ARGV)
1261
+ i = [i].flatten.compact
1262
+ @commandline_arguments = i
1263
+ end
1264
+
1265
+ # ========================================================================= #
1266
+ # === commandline_arguments?
1267
+ # ========================================================================= #
1268
+ def commandline_arguments?
1269
+ @commandline_arguments
1270
+ end
1271
+
1272
+ # ========================================================================= #
1273
+ # === change_directory (cd tag)
1274
+ #
1275
+ # This only changes for local directories, not remote directories.
1276
+ # ========================================================================= #
1277
+ def change_directory(
1278
+ i = DEFAULT_LOCAL_DIRECTORY,
1279
+ be_verbose = true
1280
+ )
1281
+ i = '..' if i.nil?
1282
+ be_verbose = false if be_verbose == :be_silent
1283
+ i = i.to_s
1284
+ i.gsub!(/; pwd/,'') if i.include? '; pwd'
1285
+ begin
1286
+ i = get_env_of(i) if i.include? '$'
1287
+ if File.exist?(i)
1288
+ # =================================================================== #
1289
+ # Next, do the actual "change directory" action.
1290
+ # =================================================================== #
1291
+ Dir.chdir(i) # This will cd for local directories.
1292
+ i = return_pwd if i == '..'
1293
+ i = rds(return_pwd) unless i.include? '/'
1294
+ set_local_directory(i) # Set the new pwd here.
1295
+ report_local_directory if be_verbose
1296
+ else # else, the directory does not exist.
1297
+ e swarn('But the directory '+sdir(i)+' does not exist '\
1298
+ 'locally in '+sdir(return_pwd)+'.')
1299
+ end
1300
+ rescue Exception => error
1301
+ e "An exception occurred in #{swarn('change_directory()')}"
1302
+ e "The directory `#{sdir(i)}` does not exist."
1303
+ pp error # Should remove this and error perhaps.
1304
+ end
1305
+ end; alias cd change_directory # === cd
1306
+
1307
+ # ========================================================================= #
1308
+ # === remote_create_directory
1309
+ # ========================================================================= #
1310
+ def remote_create_directory(
1311
+ i = a?,
1312
+ be_verbose = true
1313
+ )
1314
+ if i.is_a? Array
1315
+ i.each {|entry| remote_create_directory(entry, be_verbose) }
1316
+ else
1317
+ # ===================================================================== #
1318
+ # Delegate towards the respective module-method next.
1319
+ # ===================================================================== #
1320
+ if be_verbose
1321
+ e "Creating the directory #{sdir(i)} next:"
1322
+ end
1323
+ FtpParadise.remote_create_directory(i, ftp_connection?)
1324
+ end
1325
+ end
1326
+
1327
+ # ========================================================================= #
1328
+ # === set_start_directory=
1329
+ # ========================================================================= #
1330
+ def set_start_directory=(i) # set_start_directory=(i)
1331
+ change_directory(i)
1332
+ end
1333
+
1334
+ # ========================================================================= #
1335
+ # === toplevel_login_name?
1336
+ # ========================================================================= #
1337
+ def toplevel_login_name?
1338
+ FtpParadise.login_name?
1339
+ end
1340
+
1341
+ # ========================================================================= #
1342
+ # === remote_remove_file
1343
+ # ========================================================================= #
1344
+ def remote_remove_file(
1345
+ i = first_argument_for_the_menu_interface?
1346
+ )
1347
+ if i.is_a? Array
1348
+ i.each {|entry| remote_remove_file(entry) }
1349
+ else
1350
+ e "Trying to remove `#{sfile(i)}` next:"
1351
+ ftp_connection?.delete(i)
1352
+ end
1353
+ end; alias remote_remove_files remote_remove_file # === remote_remove_files
1354
+
1355
+ # ========================================================================= #
1356
+ # === show_local_files
1357
+ #
1358
+ # This method shows the local file listing. That is, all the entries in
1359
+ # the given directory.
1360
+ # ========================================================================= #
1361
+ def show_local_files(show_only_directories = true)
1362
+ _ = return_pwd
1363
+ if Dir.entries(_).size == 2 # Dir.empty?, we assume that we have '.' and '..' only
1364
+ e "The directory `#{sdir(_)}` is empty."
1365
+ else
1366
+ e 'Showing local files now from `'+sdir(_)+'`:'
1367
+ e ('=' * 55)+' '+FtpParadise.yellow('LOCAL FILES')+' '+('=' * 12)
1368
+ entries = return_local_entries
1369
+ entries.reject! {|x| ! File.directory?(x) } if show_only_directories
1370
+ entries.sort.each_with_index { |item, index|
1371
+ case File.ftype(item)
1372
+ when 'directory'
1373
+ item = sdir(item+'/')
1374
+ when 'file'
1375
+ item = sfile(item)
1376
+ end
1377
+ e '('+('%2s' % (index+1).to_s)+') '+FtpParadise.rds(item)
1378
+ }
1379
+ cliner
1380
+ end
1381
+ end
1382
+
1383
+ # ========================================================================= #
1384
+ # === first_argument?
1385
+ # ========================================================================= #
1386
+ def first_argument?
1387
+ @commandline_arguments.first
1388
+ end; alias first? first_argument? # === first?
1389
+
1390
+ # ========================================================================= #
1391
+ # === first_argument_for_the_menu_interface?
1392
+ # ========================================================================= #
1393
+ def first_argument_for_the_menu_interface?
1394
+ @internal_hash[:first_argument]
1395
+ end
1396
+
1397
+ # ========================================================================= #
1398
+ # === ftp_remote_directory?
1399
+ # ========================================================================= #
1400
+ def ftp_remote_directory?
1401
+ ftp_connection?.remote_directory?
1402
+ end; alias return_remote_pwd ftp_remote_directory? # === return_remote_pwd
1403
+
1404
+ # ========================================================================= #
1405
+ # === remote_url?
1406
+ # ========================================================================= #
1407
+ def remote_url?
1408
+ FtpParadise.remote_url?.to_s
1409
+ end; alias remote_host? remote_url? # === remote_host?
1410
+
1411
+ # ========================================================================= #
1412
+ # === show_remote_directories
1413
+ # ========================================================================= #
1414
+ def show_remote_directories
1415
+ e "The remote directories at "\
1416
+ "#{sdir(remote_host?)}#{sdir(return_remote_pwd)} are:"
1417
+ e
1418
+ ftp_connection?.return_remote_directories.each_with_index {|dir, index|
1419
+ index += 1
1420
+ e index.to_s.rjust(3)+') '+sdir(dir)
1421
+ }
1422
+ e
1423
+ end
1424
+
1425
+ # ========================================================================= #
1426
+ # === populate_the_ftp_dataset_with_default_values
1427
+ # ========================================================================= #
1428
+ def populate_the_ftp_dataset_with_default_values
1429
+ FtpParadise.determine_user_dataset_from_this_hash(
1430
+ YAML.load_file(FtpParadise.my_yaml_file), :default
1431
+ )
1432
+ end
1433
+
1434
+ # ========================================================================= #
1435
+ # === try_to_use_readline
1436
+ #
1437
+ # This method will try to use the readline module.
1438
+ #
1439
+ # It ought to be called before the method menu() is invoked.
1440
+ # ========================================================================= #
1441
+ def try_to_use_readline
1442
+ begin
1443
+ require 'readline' # Using readline since August 2011.
1444
+ setup_readline_completion
1445
+ rescue LoadError
1446
+ # ===================================================================== #
1447
+ # In this case the user can not use the readline-module.
1448
+ # ===================================================================== #
1449
+ do_not_use_readline
1450
+ end
1451
+ end; alias consider_using_the_readline_module try_to_use_readline # === consider_using_the_readline_module
1452
+
1453
+ # ========================================================================= #
1454
+ # === setup_readline_completion
1455
+ #
1456
+ # Call this method to invoke completion support.
1457
+ # ========================================================================= #
1458
+ def setup_readline_completion
1459
+ Readline.completion_case_fold = true # Ignore case on tab-completion.
1460
+ Readline.completer_word_break_characters = "\n"
1461
+ Readline.completion_append_character = ' '
1462
+ # ======================================================================= #
1463
+ # Act on Readline's completion functionality here. (readline tag)
1464
+ #
1465
+ # We will respond to these events specifically:
1466
+ #
1467
+ # - rcd
1468
+ # - cd
1469
+ # - upload
1470
+ # - download
1471
+ #
1472
+ # ======================================================================= #
1473
+ Readline.completion_proc = proc {|input|
1474
+ _ = []
1475
+ case input # case tag
1476
+ # ===================================================================== #
1477
+ # To test it, do:
1478
+ # rcd AUS<TAB>
1479
+ # ===================================================================== #
1480
+ when /^rcd/,
1481
+ /^rcd /,
1482
+ /^rc/,
1483
+ 'rchange_dir',
1484
+ 'lcd',
1485
+ 'remote_change_directory'
1486
+ result = ftp_connection?.return_directories # This will return the remote directories only.
1487
+ _ << result.map {|entry| input+' '+entry}
1488
+ # ===================================================================== #
1489
+ # === cd
1490
+ # ===================================================================== #
1491
+ when /^cd/,/^cd / # Fetch only directories.
1492
+ _ << ftp_connection?.return_local_directories
1493
+ when /^upload/ # Act on upload.
1494
+ return_local_files.each { |array| _ << array }
1495
+ when /^download/ # Act on download.
1496
+ ftp_connection?.array_file_listing.each { |array| _ << array.first }
1497
+ else # Default.
1498
+ # _ << return_local_files # Disabled in June 2014 because it gives completions to things I did not ask for.
1499
+ end
1500
+ _ = _.flatten
1501
+ _ # Return it here finally.
1502
+ }
1503
+ end
1504
+
1505
+ # ========================================================================= #
1506
+ # === report_which_editor_is_in_use
1507
+ # ========================================================================= #
1508
+ def report_which_editor_is_in_use
1509
+ opnn; e "The editor in use is `#{sfancy(use_this_editor?)}`."
1510
+ end
1511
+
1512
+ # ========================================================================= #
1513
+ # === set_port
1514
+ #
1515
+ # Use this method to set the port.
1516
+ # ========================================================================= #
1517
+ def set_port(
1518
+ i = 21, be_verbose = false
1519
+ )
1520
+ if be_verbose
1521
+ e "Setting port to #{sfancy(i)} now."
1522
+ end
1523
+ ftp_connection?.set_port(i)
1524
+ end
1525
+
1526
+ # ========================================================================= #
1527
+ # === display_file
1528
+ #
1529
+ # Use this method to quickly display a file in question.
1530
+ # ========================================================================= #
1531
+ def display_file(i)
1532
+ if i and File.exist? i
1533
+ e File.readlines(i).join
1534
+ else
1535
+ ewarn "File #{sfile(i)} does not exist."
1536
+ end
1537
+ end
1538
+
1539
+ # ========================================================================= #
1540
+ # === report_version
1541
+ # ========================================================================= #
1542
+ def report_version
1543
+ e sfancy(FtpParadise::VERSION)
1544
+ end
1545
+
1546
+ # ========================================================================= #
1547
+ # === set_url
1548
+ # ========================================================================= #
1549
+ def set_url(i)
1550
+ ::FtpParadise.set_remote_host(i)
1551
+ end
1552
+
1553
+ # ========================================================================= #
1554
+ # === save_config
1555
+ # ========================================================================= #
1556
+ def save_config
1557
+ config?.save
1558
+ end
1559
+
1560
+ # ========================================================================= #
1561
+ # === convert_number_to_file
1562
+ #
1563
+ # Use this to convert a number.
1564
+ #
1565
+ # convert_number_to_file(i) if i =~ /^\d+$/
1566
+ #
1567
+ # ========================================================================= #
1568
+ def convert_number_to_file(number)
1569
+ number = number.to_s.chomp
1570
+ if number =~ /^\d+$/ # if is a number
1571
+ ftp_connection?.update_file_listing
1572
+ number = ftp_connection?.array_file_listing[number.to_i - 1][0]
1573
+ end
1574
+ return number
1575
+ end
1576
+
1577
+ # ========================================================================= #
1578
+ # === ftp_dataset?
1579
+ # ========================================================================= #
1580
+ def ftp_dataset?
1581
+ FtpParadise.dataset?
1582
+ end
1583
+
1584
+ # ========================================================================= #
1585
+ # === initialize_the_dataset_for_bplaced
1586
+ # ========================================================================= #
1587
+ def initialize_the_dataset_for_bplaced
1588
+ FtpParadise.determine_user_dataset_from_this_hash(
1589
+ YAML.load_file(FILE_ROEBE_FTP)['bplaced']
1590
+ )
1591
+ end
1592
+
1593
+ # ========================================================================= #
1594
+ # === use_ascii_mode
1595
+ # ========================================================================= #
1596
+ def use_ascii_mode(
1597
+ be_verbose = false
1598
+ )
1599
+ e 'Using ascii mode now.' if be_verbose
1600
+ set_transfer_mode :ascii
1601
+ end
1602
+
1603
+ # ========================================================================= #
1604
+ # === s?
1605
+ # ========================================================================= #
1606
+ def s?
1607
+ @internal_hash[:second_argument]
1608
+ end
1609
+
1610
+ # ========================================================================= #
1611
+ # === opne
1612
+ # ========================================================================= #
1613
+ def opne(message)
1614
+ opnn; e message
1615
+ end
1616
+
1617
+ # ========================================================================= #
1618
+ # === opnn
1619
+ # ========================================================================= #
1620
+ def opnn(i = {namespace: NAMESPACE, use_colours: use_colours?})
1621
+ Opn.opn(i)
1622
+ end
1623
+
1624
+ # ========================================================================= #
1625
+ # === remote_remove
1626
+ #
1627
+ # Use this if you wish to remove a remote file or a remote directory.
1628
+ # ========================================================================= #
1629
+ def remote_remove(i)
1630
+ if i.is_a? Array
1631
+ i.each {|entry| remote_remove(entry) }
1632
+ else
1633
+ i = i.to_s.strip # Added as of July 2014.
1634
+ i = File.basename(i) if i.include? '/'
1635
+ # ===================================================================== #
1636
+ # The user may input numbers. If the input is a number, we will try to
1637
+ # find the corresponding entry - but only if no remote directory or
1638
+ # remote file exists with that name. Some directories may be named,
1639
+ # e. g. "123456".
1640
+ # ===================================================================== #
1641
+ unless this_remote_entry_exists? i
1642
+ i = convert_number_to_file(i) if i =~ /^\d+$/
1643
+ end
1644
+ # ===================================================================== #
1645
+ # Next check for user input. If the user did input a '*', then we
1646
+ # will expand that.
1647
+ # ===================================================================== #
1648
+ if i.include?('*') or i.include?('*.')
1649
+ i = ftp_connection?.array_file_listing.select {|entry|
1650
+ entry[0].include? i.delete('*')
1651
+ }
1652
+ i.reject! {|line|
1653
+ line == '.' or line == '..' # Reject '.' and '..' entries.
1654
+ }
1655
+ i.map! {|entry|
1656
+ File.basename(entry)
1657
+ } # ^^^ This is a bit hackish.
1658
+ remote_remove(i)
1659
+ else
1660
+ # =================================================================== #
1661
+ # We try to find out whether we have a directory or a file next.
1662
+ # =================================================================== #
1663
+ if is_dir?(i)
1664
+ remove_remote_directory(i)
1665
+ else # Assume it is a file.
1666
+ remove_remote_file(i)
1667
+ end
1668
+ end
1669
+ end
1670
+ end
1671
+
1672
+ # ========================================================================= #
1673
+ # === remove_remote_file
1674
+ #
1675
+ # Use this method to attempt remove a remote file.
1676
+ # ========================================================================= #
1677
+ def remove_remote_file(i)
1678
+ i[0,1] = ''.dup if i.start_with? '/' # We don't like starting "/" characters here.
1679
+ e "Removing remote file `#{sfile(i)}` next." # We remove the remote file here.
1680
+ begin
1681
+ result = ftp_connection?.remove_file(i)
1682
+ e "Successfully removed remote file `#{sfile(result)}`."
1683
+ rescue Net::FTPPermError => error
1684
+ e 'Can not remove file `'+sfile(i)+'` as you are not '\
1685
+ 'the owner. ('+simp('Net::FTPPermError')+')'
1686
+ pp error
1687
+ end
1688
+ end
1689
+
1690
+ # ========================================================================= #
1691
+ # === set_transfer_mode
1692
+ #
1693
+ # Set the mode here. We default to :ascii mode.
1694
+ #
1695
+ # There are only two valid modes:
1696
+ #
1697
+ # :ascii
1698
+ # :binary
1699
+ #
1700
+ # ========================================================================= #
1701
+ def set_transfer_mode(
1702
+ i = :ascii
1703
+ )
1704
+ @internal_hash[:ftp_transfer_mode] = i
1705
+ ftp_connection?.set_transfer_mode(
1706
+ i, :be_quiet # Cascade the variable down into ftp_lib.rb.
1707
+ )
1708
+ end; alias set_mode set_transfer_mode # === set_mode
1709
+
1710
+ # ========================================================================= #
1711
+ # === set_run_mode
1712
+ #
1713
+ # This will set the run-mode. The run-mode can be either :standalone or
1714
+ # :connected.
1715
+ # ========================================================================= #
1716
+ def set_run_mode(
1717
+ i = :standalone
1718
+ )
1719
+ @internal_hash[:run_mode] = i
1720
+ end
1721
+
1722
+ # ========================================================================= #
1723
+ # === change
1724
+ #
1725
+ # This method can be used to change the main transfer mode.
1726
+ # ========================================================================= #
1727
+ def change(i)
1728
+ case i
1729
+ # ======================================================================= #
1730
+ # === mode
1731
+ # ======================================================================= #
1732
+ when 'mode' # Change the mode that we use.
1733
+ use_binary_mode
1734
+ end
1735
+ end
1736
+
1737
+ # ========================================================================= #
1738
+ # === use_binary_mode
1739
+ #
1740
+ # This enables use the binary mode.
1741
+ # ========================================================================= #
1742
+ def use_binary_mode(
1743
+ be_verbose = false
1744
+ )
1745
+ case be_verbose
1746
+ when :be_quiet
1747
+ be_verbose = false
1748
+ when :be_verbose
1749
+ be_verbose = true
1750
+ end
1751
+ e 'Using binary mode now.' if be_verbose
1752
+ set_transfer_mode :binary
1753
+ end; alias set_binary use_binary_mode # === set_binary
1754
+
1755
+ # ========================================================================= #
1756
+ # === do_use_binary_mode
1757
+ # ========================================================================= #
1758
+ def do_use_binary_mode
1759
+ use_binary_mode(:be_quiet)
1760
+ end
1761
+
1762
+ # ========================================================================= #
1763
+ # === vte
1764
+ # ========================================================================= #
1765
+ def vt(i)
1766
+ VerboseTruth[i].to_s
1767
+ end
1768
+
1769
+ # ========================================================================= #
1770
+ # === f?
1771
+ # ========================================================================= #
1772
+ def f?
1773
+ @internal_hash[:first_argument] # First argument. Keep in mind that the second argument is stored in @s.
1774
+ end; alias f f? # === f
1775
+
1776
+ # ========================================================================= #
1777
+ # === show_remote_files
1778
+ #
1779
+ # Use this method to show all remote files on a FTP site.
1780
+ # ========================================================================= #
1781
+ def show_remote_files(
1782
+ mode = nil
1783
+ ) # Show the content of the remote host.
1784
+ ftp_connection?.show_remote_files
1785
+ end
1786
+
1787
+ # ========================================================================= #
1788
+ # === show_hosts
1789
+ # ========================================================================= #
1790
+ def show_hosts
1791
+ e "The available hosts are:#{N}#{N}"
1792
+ ftp_connection?.array_available_hosts.each {|host|
1793
+ e simp(" #{host}")
1794
+ }; e
1795
+ end
1796
+
1797
+ # ========================================================================= #
1798
+ # === remove_local
1799
+ # ========================================================================= #
1800
+ def remove_local(i)
1801
+ delete(i)
1802
+ end
1803
+
1804
+ # ========================================================================= #
1805
+ # === remove_remote_directory
1806
+ #
1807
+ # Use this method to remove a remote directory.
1808
+ # ========================================================================= #
1809
+ def remove_remote_directory(i)
1810
+ e "Removing remote directory `#{sdir(i)}` next."
1811
+ # ======================================================================= #
1812
+ # Delegate to ftp?. :force_remove so we remove even non-empty directories.
1813
+ # ======================================================================= #
1814
+ ftp_connection?.remove_directory(i, :force_remove)
1815
+ end
1816
+
1817
+ # ========================================================================= #
1818
+ # === toggle (toggle tag)
1819
+ #
1820
+ # Simply toggle the value for whether we @config.show_full_names or not.
1821
+ # ========================================================================= #
1822
+ def toggle(
1823
+ i = :names
1824
+ )
1825
+ i = i.to_s
1826
+ i = 'mode' if i.empty? # Safeguard.
1827
+ case i
1828
+ # ======================================================================= #
1829
+ # === mode
1830
+ # ======================================================================= #
1831
+ when 'mode'
1832
+ case ftp_transfer_mode?
1833
+ when :binary
1834
+ use_ascii_mode
1835
+ else
1836
+ use_binary_mode
1837
+ end
1838
+ when 'names','name'
1839
+ toggle_show_full_names
1840
+ will_we_show_full_names
1841
+ end
1842
+ e 'We will now toggle '+sfancy(i)+' to '+simp(ftp_transfer_mode?.to_s)+'.'
1843
+ end; alias show_full_names toggle # === show_full_names
1844
+
1845
+ # ========================================================================= #
1846
+ # === show_user_and_password
1847
+ # ========================================================================= #
1848
+ def show_user_and_password
1849
+ ftp_connection?.show_user_and_password
1850
+ end
1851
+
1852
+ # ========================================================================= #
1853
+ # === create_remote_directory
1854
+ # ========================================================================= #
1855
+ def create_remote_directory(i)
1856
+ ftp_connection?.mkdir(i)
1857
+ end
1858
+
1859
+ # ========================================================================= #
1860
+ # === return_remote_files
1861
+ #
1862
+ # We call into FtpParadise::Connection here.
1863
+ # ========================================================================= #
1864
+ def return_remote_files(mode = nil)
1865
+ ftp_connection?.show_full_names if show_full_names? # Display the full path here.
1866
+ ftp_connection?.return_remote_files
1867
+ end
1868
+
1869
+ # ========================================================================= #
1870
+ # === display_prompt
1871
+ # ========================================================================= #
1872
+ def display_prompt
1873
+ print PROMPT_TO_USE
1874
+ end
1875
+
1876
+ # ========================================================================= #
1877
+ # === download?
1878
+ # ========================================================================= #
1879
+ def download?
1880
+ e 'The remote file we would download is: '
1881
+ e
1882
+ e " #{sfile(DEFAULT_REMOTE_FILE)}"
1883
+ e
1884
+ end
1885
+
1886
+ # ========================================================================= #
1887
+ # === do_login
1888
+ #
1889
+ # If the first argument is :dont_login_yet, which is the default,
1890
+ # we will not yet connect.
1891
+ # ========================================================================= #
1892
+ def do_login(
1893
+ i = :dont_login_yet
1894
+ )
1895
+ i = nil if i == :dont_login_yet
1896
+ if i
1897
+ # ===================================================================== #
1898
+ # Next, feed this information to the ftp? object.
1899
+ # ===================================================================== #
1900
+ ftp_connection?.set_data(i)
1901
+ ftp_connection?.do_login # bl $RUBY_FTP/ftp_library.rb
1902
+ # @internal_hash[:are_we_connected] = true
1903
+ end
1904
+ end
1905
+
1906
+ # ========================================================================= #
1907
+ # === report_remote_directory
1908
+ #
1909
+ # This method will report the remote directory.
1910
+ # ========================================================================= #
1911
+ def report_remote_directory(
1912
+ make_newline = true
1913
+ )
1914
+ if is_connected?
1915
+ remote_dir = sdir(ftp_remote_directory?)
1916
+ if make_newline
1917
+ e 'The remote directory is: '
1918
+ e " #{sdir(remote_dir)}"
1919
+ else
1920
+ e 'The remote directory is: '+sdir(remote_dir)
1921
+ end
1922
+ else
1923
+ e 'No connection is available. You may have to re-connect again.'
1924
+ end
1925
+ end; alias show_remote_directory report_remote_directory # === show_remote_directory
1926
+
1927
+ # ========================================================================= #
1928
+ # === show_host_user_name_port_and_password
1929
+ # ========================================================================= #
1930
+ def show_host_user_name_port_and_password
1931
+ ftp_connection?.show_host_user_name_port_and_password
1932
+ end
1933
+
1934
+ # ========================================================================= #
1935
+ # === show_full_names?
1936
+ # ========================================================================= #
1937
+ def show_full_names?
1938
+ config?.show_full_names
1939
+ end
1940
+
1941
+ # ========================================================================= #
1942
+ # === obtain_user_input
1943
+ #
1944
+ # This method will obtain user input from the user, and assign it to
1945
+ # the corresponding variable that keeps track of user input given.
1946
+ # ========================================================================= #
1947
+ def obtain_user_input(
1948
+ shall_we_use_readline = try_to_use_readline?
1949
+ )
1950
+ if shall_we_use_readline
1951
+ user_input = Readline.readline('', true)
1952
+ Readline::HISTORY.pop if user_input.strip.empty?
1953
+ else
1954
+ user_input = $stdin.gets.chomp
1955
+ end
1956
+ # ======================================================================= #
1957
+ # Get rid of potential '#' comments in the input next.
1958
+ # ======================================================================= #
1959
+ if user_input.include? '#'
1960
+ user_input = user_input[0 .. user_input.index('#') - 1]
1961
+ end
1962
+ user_input.strip! # Get rid of ' ' empty characters.
1963
+ unless user_input.empty? # append to history.
1964
+ try_to_append_this_to_the_history(user_input)
1965
+ end
1966
+ # ======================================================================= #
1967
+ # If the user did input a ';' character then we will assume that he
1968
+ # wants to send multiple commands. We will however NOT assume so
1969
+ # if the string also includes a 'http://' - in that case, we assume
1970
+ # a HTTP URL instead. Since as of July 2022 we just check for the
1971
+ # keyword "http".
1972
+ # ======================================================================= #
1973
+ if user_input.include?(';') and !user_input.include?('http')
1974
+ user_input = user_input.split(';')
1975
+ else
1976
+ user_input = [user_input] # In this case simply turn it into an Array.
1977
+ end
1978
+ # ======================================================================= #
1979
+ # The @internal_hash[:user_input] variable should always be an Array.
1980
+ # ======================================================================= #
1981
+ @internal_hash[:user_input] = user_input
1982
+ end; alias get_user_input obtain_user_input # === get_user_input
1983
+ alias fetch_user_input obtain_user_input # === fetch_user_input
1984
+
1985
+ # ========================================================================= #
1986
+ # === user_input?
1987
+ # ========================================================================= #
1988
+ def user_input?
1989
+ @internal_hash[:user_input]
1990
+ end
1991
+
1992
+ # ========================================================================= #
1993
+ # === return_title
1994
+ # ========================================================================= #
1995
+ def return_title
1996
+ sfancy(TITLE)
1997
+ end
1998
+
1999
+ # ========================================================================= #
2000
+ # === try_to_append_this_to_the_history
2001
+ #
2002
+ # Right now only 'last' is a forbidden entry.
2003
+ # ========================================================================= #
2004
+ def try_to_append_this_to_the_history(i)
2005
+ unless i.empty?
2006
+ @internal_hash[:history] << i unless ARRAY_FORBIDDEN_HISTORY_COMMANDS.include? i
2007
+ end
2008
+ end
2009
+
2010
+ # ========================================================================= #
2011
+ # === determine_user_dataset_from_this_hash
2012
+ #
2013
+ # This method can set relevant entries from an input Hash.
2014
+ # ========================================================================= #
2015
+ def determine_user_dataset_from_this_hash(
2016
+ i,
2017
+ optional_use_this_entry = :default
2018
+ )
2019
+ FtpParadise.determine_user_dataset_from_this_hash(i, optional_use_this_entry)
2020
+ end
2021
+
2022
+ # ========================================================================= #
2023
+ # === enter_the_main_loop
2024
+ # ========================================================================= #
2025
+ def enter_the_main_loop(
2026
+ shall_we_use_readline = try_to_use_readline?
2027
+ )
2028
+ check_commandline_arguments # ← This will also query the menu() method.
2029
+ loop {
2030
+ begin
2031
+ # =================================================================== #
2032
+ # Obtain the user input next:
2033
+ # =================================================================== #
2034
+ obtain_user_input
2035
+ rescue Interrupt
2036
+ e 'In order to quit, please use "'+
2037
+ steelblue('q')+'" instead.'
2038
+ end
2039
+ menu(user_input?)
2040
+ if @internal_hash[:may_we_exit]
2041
+ break if exit_the_program_properly == :break
2042
+ end
2043
+ }
2044
+ end; alias enter_loop enter_the_main_loop # === enter_loop
2045
+
2046
+ # ========================================================================= #
2047
+ # === exit_the_program_properly (exit tag)
2048
+ # ========================================================================= #
2049
+ def exit_the_program_properly # Use only this method to exit i-ftp.
2050
+ e "Bye from #{return_title}!"
2051
+ case @internal_hash[:run_mode]
2052
+ when :standalone # Not embedded.
2053
+ @internal_hash[:run_mode] = :exit
2054
+ disconnect
2055
+ exit
2056
+ else
2057
+ @internal_hash[:run_mode] = :break
2058
+ return @internal_hash[:run_mode]
2059
+ end
2060
+ end
2061
+
2062
+ # ========================================================================= #
2063
+ # === show_remote_listing
2064
+ #
2065
+ # This will display the remote file listing.
2066
+ # ========================================================================= #
2067
+ def show_remote_listing
2068
+ ftp_connection?.show_remote_listing
2069
+ end
2070
+
2071
+ # ========================================================================= #
2072
+ # === report_where_we_are_connected_to
2073
+ # ========================================================================= #
2074
+ def report_where_we_are_connected_to
2075
+ if are_we_connected?
2076
+ e 'We are connected to: '+simp(ftp_connection?.remote?)
2077
+ else
2078
+ e 'We are not connected. Invoke "do_connect" to connect to a FTP host.'
2079
+ end
2080
+ end
2081
+
2082
+ # ========================================================================= #
2083
+ # === are_we_connected?
2084
+ # ========================================================================= #
2085
+ def are_we_connected?
2086
+ ftp_connection?.are_we_connected?
2087
+ end; alias is_connected? are_we_connected? # === is_connected?
2088
+
2089
+ # ========================================================================= #
2090
+ # === is_dir?
2091
+ #
2092
+ # Return true or false, depending on whether the input is a directory
2093
+ # or whether it is not.
2094
+ # ========================================================================= #
2095
+ def is_dir?(i)
2096
+ ftp_connection?.is_directory?(i)
2097
+ end; alias is_directory? is_dir? # === is_directory?
2098
+
2099
+ # ========================================================================= #
2100
+ # === is_file?
2101
+ # ========================================================================= #
2102
+ def is_file?(i)
2103
+ ftp_connection?.is_file?(i)
2104
+ end
2105
+
2106
+ # ========================================================================= #
2107
+ # === show_status
2108
+ # ========================================================================= #
2109
+ def show_status
2110
+ cliner {
2111
+ # e
2112
+ # show_help # ← Disabled as of May 2017.
2113
+ e
2114
+ report_where_we_are_connected_to
2115
+ report_remote_directory # Added Dec 2011.
2116
+ report_local_dir
2117
+ # debug_it
2118
+ e
2119
+ }
2120
+ end
2121
+
2122
+ # ========================================================================= #
2123
+ # === show_title
2124
+ #
2125
+ # Use this method to give us the title
2126
+ # ========================================================================= #
2127
+ def show_title
2128
+ e return_title
2129
+ end
2130
+
2131
+ # ========================================================================= #
2132
+ # === pass_commandline_arguments_into_the_menu
2133
+ # ========================================================================= #
2134
+ def pass_commandline_arguments_into_the_menu
2135
+ menu(commandline_arguments?)
2136
+ end
2137
+
2138
+ # ========================================================================= #
2139
+ # === do_login_to_shevy_and_consider_showing_the_remote_files
2140
+ # ========================================================================= #
2141
+ def do_login_to_shevy_and_consider_showing_the_remote_files
2142
+ do_login(:shevy)
2143
+ if SHOW_REMOTE_FILES_UPON_SUCCESSFUL_LOGIN
2144
+ show_remote_files :also_show_filesize # Also display this since as of March 2015.
2145
+ end
2146
+ end
2147
+
2148
+ # ========================================================================= #
2149
+ # === show_commandline_help
2150
+ #
2151
+ # This method is different from "normal" help. The "normal" help will
2152
+ # be displayed when we are already running in interactive mode. The
2153
+ # commandline help however had will be run when we are invoking it
2154
+ # from the commandline.
2155
+ # ========================================================================= #
2156
+ def show_commandline_help
2157
+ opne 'These options are currently supported:'
2158
+ opn(use_colours?); Colours.ecomment ' --disable-colours # Run without colours.'
2159
+ end
2160
+
2161
+ # ========================================================================= #
2162
+ # === show_welcome_message
2163
+ #
2164
+ # The initial startup message to welcome the user.
2165
+ # ========================================================================= #
2166
+ def show_welcome_message
2167
+ e 'Welcome to the '+return_title+' shell.'
2168
+ e 'Input '+sfancy('"help"')+' to show the help-section.'
2169
+ e 'Please input commands next:'
2170
+ end
2171
+
2172
+ # ========================================================================= #
2173
+ # === file?
2174
+ #
2175
+ # This may always be a String.
2176
+ # ========================================================================= #
2177
+ def file?
2178
+ @internal_hash[:file].to_s
2179
+ end
2180
+
2181
+ # ========================================================================= #
2182
+ # === open_this_file_in_editor (edit tag, editor tag, open tag)
2183
+ #
2184
+ # If you pass as first argument to this method the string 'ALL', we
2185
+ # will try to open the (local) project files in your editor.
2186
+ #
2187
+ # To test this, do:
2188
+ #
2189
+ # open ALL
2190
+ # open YAML
2191
+ #
2192
+ # ========================================================================= #
2193
+ def open_this_file_in_editor(
2194
+ this_file = file?
2195
+ )
2196
+ this_file = ARRAY_PROJECT_FILES if this_file.nil?
2197
+ if this_file.is_a? Array
2198
+ this_file.each {|entry| open_this_file_in_editor(entry) }
2199
+ else
2200
+ this_file = this_file.to_s
2201
+ if this_file == 'TODO'
2202
+ this_file = ARRAY_PROJECT_FILES.select {|entry| entry.include? 'TODO' }[0]
2203
+ end
2204
+ if this_file.to_s =~ /^\d+$/ # If only numbers were given.
2205
+ this_file = Dir['*'].sort[this_file.to_i - 1]
2206
+ end
2207
+ this_file = NAME_OF_THIS_FILE if this_file.empty?
2208
+ if this_file == 'ALL' and ! File.exist?('ALL')
2209
+ open_this_file_in_editor(ARRAY_PROJECT_FILES)
2210
+ elsif this_file == 'YAML' and ! File.exist?('YAML')
2211
+ open_this_file_in_editor(YAML_FILE)
2212
+ else
2213
+ _ = use_this_editor?+" #{this_file}"
2214
+ if File.exist?(this_file) && File.file?(this_file)
2215
+ unless has_unwanted_file_suffix?(this_file)
2216
+ e 'Loading '+sfile(this_file)+' in editor '+
2217
+ 'now as '+simp('USE_THIS_EDITOR')+' was set '+
2218
+ 'to true:'
2219
+ e ' '+_+' &'
2220
+ `#{_}`
2221
+ end
2222
+ set_file(this_file) # Since 24.12.2011 we also assign it.
2223
+ else
2224
+ e swarn('But the file `')+sfile(this_file)+
2225
+ swarn('` does not exist.')
2226
+ end
2227
+ end
2228
+ end
2229
+ end; alias open_in_editor open_this_file_in_editor # === open_in_editor
2230
+
2231
+ # ========================================================================= #
2232
+ # === report_port
2233
+ # ========================================================================= #
2234
+ def report_port
2235
+ e 'The port in use is: '+sfancy(ftp?.port)
2236
+ end
2237
+
2238
+ # ========================================================================= #
2239
+ # === get_env_of
2240
+ # ========================================================================= #
2241
+ def get_env_of(i)
2242
+ ConvertGlobalEnv.convert(i, ConvertGlobalEnv.report_errors?)
2243
+ end
2244
+
2245
+ # ========================================================================= #
2246
+ # === show_ftp_server_welcome
2247
+ #
2248
+ # Simply show the FTP server's welcome message.
2249
+ # ========================================================================= #
2250
+ def show_ftp_server_welcome
2251
+ e ftp_connection?.welcome
2252
+ end
2253
+
2254
+ # ========================================================================= #
2255
+ # === try_to_connect
2256
+ # ========================================================================= #
2257
+ def try_to_connect
2258
+ hash = FtpParadise.info?
2259
+ connection?.connect_via_this_dataset(hash)
2260
+ end
2261
+
2262
+ # ========================================================================= #
2263
+ # === run (run tag)
2264
+ # ========================================================================= #
2265
+ def run
2266
+ try_to_create_a_temporary_log_directory_and_cd_into_it_or_the_temp_directory
2267
+ shall_we_use_readline = try_to_use_readline?
2268
+ try_to_use_readline if shall_we_use_readline
2269
+ if is_on_roebe?
2270
+ populate_the_ftp_dataset_with_default_values
2271
+ FtpParadise.use_this_as_ftp_object(ftp_connection?)
2272
+ ftp_connection?.enable_debug if debug? # Set the @debug variable inside of @ftp to true.
2273
+ if automatically_connect_on_startup_of_the_interactive_ftp_shell?
2274
+ try_to_connect
2275
+ set_passive
2276
+ use_ascii_mode
2277
+ end
2278
+ # ===================================================================== #
2279
+ # Enter the remote directory htdocs if we are on ftpupload.net
2280
+ # or on a similar host.
2281
+ # ===================================================================== #
2282
+ if remote_url?.include?('ftpupload.net')
2283
+ remote_cd 'htdocs', :be_verbose
2284
+ elsif remote_url?.include?('shevy.bplaced.net')
2285
+ remote_cd 'www', :be_verbose
2286
+ end
2287
+ end
2288
+ # ======================================================================= #
2289
+ # The welcome message should come before the main loop is started and
2290
+ # before the prompt is shown.
2291
+ # ======================================================================= #
2292
+ show_welcome_message
2293
+ pass_commandline_arguments_into_the_menu # ← Must come before startup_actions().
2294
+ display_prompt # Must come once before we enter the main loop.
2295
+ enter_the_main_loop
2296
+ end
2297
+
2298
+ # ========================================================================= #
2299
+ # === FtpParadise::Shell[]
2300
+ # ========================================================================= #
2301
+ def self.[](i = ARGV)
2302
+ new(i)
2303
+ end; self.instance_eval { alias interactive_shell [] } # === FtpParadise.interactive_shell
2304
+
2305
+ end
2306
+
2307
+ # =========================================================================== #
2308
+ # === FtpParadise.shell
2309
+ #
2310
+ # This is a convenience method to instantiate a new class
2311
+ # FtpParadise::Shell instance.
2312
+ # =========================================================================== #
2313
+ def self.shell(i = ARGV)
2314
+ FtpParadise::Shell.new(i)
2315
+ end; self.instance_eval { alias interactive shell } # === FtpParadise.interactive
2316
+
2317
+ end
2318
+
2319
+ if __FILE__ == $PROGRAM_NAME
2320
+ FtpParadise::Shell.new(ARGV)
2321
+ end # iftp