ftp_paradise 1.4.5 → 1.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ftp_paradise might be problematic. Click here for more details.

Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +152 -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} +0 -0
  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 +554 -448
  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