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
@@ -2,34 +2,2801 @@
2
2
  # Encoding: UTF-8
3
3
  # frozen_string_literal: true
4
4
  # =========================================================================== #
5
+ # === FtpParadise::Connection
6
+ #
5
7
  # This is the "connection class". It will have methods that can be use
6
- # when we are connected to a remote site (via the FTP protocol).
8
+ # when the user is connected to a remote site (via the FTP protocol).
7
9
  #
8
10
  # Rather than keeping FTP-related state within this class, such as remote
9
- # URL and such, we will instead use FtpParadise module methods.
11
+ # URL and such, we will instead use FtpParadise toplevel-module methods.
12
+ # Or, at the least, we will tap into that dataset if it has been
13
+ # assigned by the user.
14
+ #
15
+ # Usage example:
16
+ #
17
+ # FtpParadise::Connection.new(ARGV)
18
+ #
10
19
  # =========================================================================== #
11
20
  # Possible errors and failures when we are trying to connect:
12
21
  #
13
22
  # Net::FTPPermError: 530 Please login with USER and PASS.
14
23
  #
15
- # Net::FTPConnectionError is raised if we are no longer connected to
16
- # the remote FTP site.
24
+ # Net::FTPConnectionError is raised if we are no longer connected
25
+ # to the remote FTP site.
17
26
  #
18
27
  # Errno::ETIMEDOUT is raised when a timeout event occurred.
28
+ #
19
29
  # =========================================================================== #
20
30
  # The official documentation for Ruby-FTP can be found here:
21
31
  #
22
32
  # https://ruby-doc.org/stdlib/libdoc/net/ftp/rdoc/Net/FTP.html
23
33
  #
24
34
  # =========================================================================== #
25
- require 'ftp_paradise/connection/initialize.rb'
26
- require 'ftp_paradise/connection/data.rb'
27
- require 'ftp_paradise/connection/debug.rb'
28
- require 'ftp_paradise/connection/misc.rb'
29
- require 'ftp_paradise/connection/notify.rb'
30
- require 'ftp_paradise/connection/remote_pwd.rb'
31
- require 'ftp_paradise/connection/remove.rb'
32
- require 'ftp_paradise/connection/show.rb'
33
- require 'ftp_paradise/connection/upload.rb'
34
- require 'ftp_paradise/version/version.rb'
35
- require 'ftp_paradise/configuration/configuration.rb'
35
+ # require 'ftp_paradise/connection/connection.rb'
36
+ # =========================================================================== #
37
+ module FtpParadise
38
+
39
+ class Connection # === FtpParadise::Connection
40
+
41
+ require 'ftp_paradise/base/base.rb'
42
+ include ::FtpParadise::Base
43
+
44
+ require 'ftp_paradise/requires/require_net_ftp.rb'
45
+ require 'ftp_paradise/requires/require_the_toplevel_methods.rb'
46
+ require 'ftp_paradise/entry/entry.rb'
47
+ require 'ftp_paradise/configuration/configuration.rb'
48
+
49
+ # ========================================================================= #
50
+ # === NAMESPACE
51
+ # ========================================================================= #
52
+ NAMESPACE = inspect
53
+
54
+ # ========================================================================= #
55
+ # === BE_VERBOSE
56
+ # ========================================================================= #
57
+ BE_VERBOSE = true
58
+
59
+ # ========================================================================= #
60
+ # === DEFAULT_TRANSFER_MODE
61
+ # ========================================================================= #
62
+ DEFAULT_TRANSFER_MODE = :ascii # Which transfer mode to use by default.
63
+
64
+ # ========================================================================= #
65
+ # === DEFAULT_PORT
66
+ # ========================================================================= #
67
+ DEFAULT_PORT = 21
68
+
69
+ # ========================================================================= #
70
+ # === DEFAULT_USER_NAME
71
+ #
72
+ # In the past this was set to a String (the user name); but since as
73
+ # of October 2018, it will default to nil, so that we really initialize
74
+ # the whole project to a nil-state (as the default). This thus allows
75
+ # us to determine whether this has been changed, aka initialized.
76
+ # ========================================================================= #
77
+ DEFAULT_USER_NAME = nil
78
+
79
+ # ========================================================================= #
80
+ # === RUN_ALREADY
81
+ # ========================================================================= #
82
+ RUN_ALREADY = true
83
+
84
+ # ========================================================================= #
85
+ # === initialize
86
+ #
87
+ # The first argument to this method should be the remote host's URL.
88
+ # ========================================================================= #
89
+ def initialize(
90
+ i = ARGV,
91
+ run_already = RUN_ALREADY
92
+ )
93
+ reset
94
+ # ======================================================================= #
95
+ # - If we pass in a Hash as the first argument, then we will use
96
+ # set_data(), otherwise we will set individually it all individually.
97
+ # ======================================================================= #
98
+ if i.is_a? Hash
99
+ set_data(i)
100
+ else
101
+ set_input(i)
102
+ end
103
+ case i
104
+ # ======================================================================= #
105
+ # === :dont_run_yet
106
+ # ======================================================================= #
107
+ when :dont_run_yet,
108
+ :do_not_run_yet
109
+ run_already = false
110
+ end
111
+ case run_already
112
+ # ======================================================================= #
113
+ # === :dont_run_yet
114
+ # ======================================================================= #
115
+ when :dont_run_yet
116
+ run_already = false
117
+ end
118
+ if run_already.is_a? Hash
119
+ _ = run_already
120
+ if _.has_key? :connect_to_this_host
121
+ set_this_host(
122
+ _.delete(:connect_to_this_host)
123
+ )
124
+ end
125
+ run_already = RUN_ALREADY # Restore to the default in this case.
126
+ end
127
+ # ======================================================================= #
128
+ # === Handle blocks given to this method next
129
+ # ======================================================================= #
130
+ if block_given?
131
+ yielded = yield
132
+ case yielded
133
+ # ===================================================================== #
134
+ # === :do_not_run_yet
135
+ # ===================================================================== #
136
+ when :do_not_run_yet
137
+ run_already = false
138
+ # ===================================================================== #
139
+ # The "default" dataset defaults to my personal FTP login dataset.
140
+ # ===================================================================== #
141
+ when :use_default_dataset,
142
+ :default_dataset,
143
+ :default
144
+ use_default_dataset
145
+ end
146
+ end
147
+ run if run_already
148
+ end
149
+
150
+ # ========================================================================= #
151
+ # === reset (reset tag)
152
+ # ========================================================================= #
153
+ def reset
154
+ super()
155
+ # ======================================================================= #
156
+ # === @namespace
157
+ # ======================================================================= #
158
+ @namespace = NAMESPACE
159
+ # ======================================================================= #
160
+ # === @ftp_object
161
+ # ======================================================================= #
162
+ @ftp_object = nil
163
+ # ======================================================================= #
164
+ # === @input
165
+ # ======================================================================= #
166
+ @input = nil
167
+ populate_internal_hash_with_default_values
168
+ # ======================================================================= #
169
+ # The next method-call must come after
170
+ # populate_internal_hash_with_default_values().
171
+ # ======================================================================= #
172
+ set_be_verbose if BE_VERBOSE
173
+ set_port
174
+ set_array_available_hosts
175
+ set_default_transfer_mode :be_quiet
176
+ set_username
177
+ end
178
+
179
+ # ========================================================================= #
180
+ # === binary=
181
+ # ========================================================================= #
182
+ def binary=(i = true)
183
+ @internal_hash[:transfer_mode] = :binary
184
+ ftp_object?.binary = i
185
+ end
186
+
187
+ # ========================================================================= #
188
+ # === binary_mode?
189
+ # ========================================================================= #
190
+ def binary_mode?
191
+ @internal_hash[:transfer_mode] == :binary
192
+ end
193
+
194
+ # ========================================================================= #
195
+ # === passive=
196
+ # ========================================================================= #
197
+ def passive=(i = true)
198
+ if ftp_object?
199
+ ftp_object?.passive = i
200
+ else
201
+ e 'In .passive=: No ftp-object has been instantiated yet.'
202
+ end
203
+ end; alias set_passive passive= # === set_passive
204
+
205
+ # ========================================================================= #
206
+ # === try_to_download_this_remote_file
207
+ # ========================================================================= #
208
+ def try_to_download_this_remote_file(
209
+ i, be_verbose = false, &block
210
+ )
211
+ if block_given?
212
+ yielded = yield
213
+ case yielded
214
+ when :be_verbose
215
+ be_verbose = true
216
+ end
217
+ end
218
+ e 'Trying to download `'+steelblue(i)+'` next.' if be_verbose
219
+ @ftp_object.getbinaryfile(i)
220
+ if be_verbose
221
+ e 'Download of '+steelblue(i)+' has finished! It is '\
222
+ 'now at '+sfile(return_pwd+i)
223
+ end
224
+ end; alias getbinaryfile try_to_download_this_remote_file # === getbinaryfile
225
+ alias download_binary_file try_to_download_this_remote_file # === download_binary_file
226
+
227
+ # ========================================================================= #
228
+ # === list (raw tag)
229
+ #
230
+ # This method must yield the result of .list(), as Array.
231
+ # ========================================================================= #
232
+ def list(i = '*')
233
+ ftp_object?.list(i)
234
+ end; alias raw_list list # === raw_list
235
+
236
+ # ========================================================================= #
237
+ # === nlst?
238
+ #
239
+ # This method will return an array of filenames in the remote
240
+ # directory. This will yield less information than the "ls -l"
241
+ # variant, aka list().
242
+ #
243
+ # Documentation:
244
+ #
245
+ # https://ruby-doc.org/stdlib/libdoc/net/ftp/rdoc/Net/FTP.html#method-i-nlst
246
+ #
247
+ # ========================================================================= #
248
+ def nlst?
249
+ ftp_object?.nlst
250
+ end; alias nlst nlst? # === nlst
251
+
252
+ # ========================================================================= #
253
+ # === sendcmd
254
+ #
255
+ # Sends a command and returns the response of the server.
256
+ #
257
+ # This has to be rescued, because there are lots of different errors
258
+ # possible.
259
+ # ========================================================================= #
260
+ def sendcmd(i)
261
+ begin
262
+ ftp_object?.sendcmd(i)
263
+ rescue Exception => error
264
+ pp error
265
+ e '(This error may be due to the remote file not existing.)'
266
+ end
267
+ end
268
+
269
+ # ========================================================================= #
270
+ # === remove_file
271
+ #
272
+ # This method will delete a remote file.
273
+ #
274
+ # The API should remain fairly flexible.
275
+ #
276
+ # Example:
277
+ #
278
+ # ftp_connection?.remove_file(i.text?) { :be_verbose }
279
+ #
280
+ # ========================================================================= #
281
+ def remove_file(
282
+ i, be_verbose = false, &block
283
+ )
284
+ if block_given?
285
+ yielded = yield
286
+ case yielded
287
+ # ===================================================================== #
288
+ # === :be_verbose
289
+ # ===================================================================== #
290
+ when :be_verbose
291
+ be_verbose = true
292
+ end
293
+ end
294
+ e 'Deleting the remote file at '+steelblue(i)+' next:' if be_verbose
295
+ ftp_connection?.delete(i)
296
+ e 'Deleting the remote file at '+steelblue(i)+' has been completed.' if be_verbose
297
+ end; alias delete_file remove_file # === delete_file
298
+ alias delete remove_file # === delete
299
+
300
+ # ========================================================================= #
301
+ # === option
302
+ #
303
+ # This method will issue an OPTS command. The first argument should
304
+ # be the name of the option that is to be set. Additional arguments
305
+ # are treated as parameter to that command.
306
+ #
307
+ # Example:
308
+ #
309
+ # option('UTF8', 'ON') => 'OPTS UTF8 ON'
310
+ #
311
+ # ========================================================================= #
312
+ def option(i, optional_argument = nil)
313
+ ftp_connection?.option(i, optional_argument)
314
+ end
315
+
316
+ # ========================================================================= #
317
+ # === set_remote_url
318
+ #
319
+ # This method will do some sanitizing before it sets a proper and
320
+ # valid hostname. Remember to keep the 'default' entry at the
321
+ # current main FTP host you use.
322
+ # ========================================================================= #
323
+ def set_remote_url(
324
+ i = :default,
325
+ be_verbose = true
326
+ )
327
+ i = :default? if i.nil?
328
+ if i.is_a? Hash # Handle Hash as input here.
329
+ if i.has_key?(:to)
330
+ i = i[:to]
331
+ end
332
+ end
333
+ # ======================================================================= #
334
+ # The next block is mostly for my custom constants.
335
+ # You can simply pass in your own Hash.
336
+ # ======================================================================= #
337
+ case i # Do some sanitizing. This is a String here. (case tag)
338
+ # ======================================================================= #
339
+ # === bplaced (this is equivalent to shevy)
340
+ # ======================================================================= #
341
+ when /^-?-?bplaced$/i,
342
+ /^-?-?shevy$/i,
343
+ 'default'
344
+ set_data(:bplaced)
345
+ i = BPLACED.first
346
+ # ======================================================================= #
347
+ # === ?
348
+ # ======================================================================= #
349
+ when '?'
350
+ feedback_login_hosts
351
+ # ======================================================================= #
352
+ # === uniwien_homepage
353
+ # ======================================================================= #
354
+ when /^uniwien_?homepage/
355
+ set_data(UNIWIEN_HOMEPAGE)
356
+ i = UNIWIEN_HOMEPAGE.first
357
+ # ======================================================================= #
358
+ # === unet
359
+ # ======================================================================= #
360
+ when 'unet','uni',
361
+ 'uniftp'
362
+ set_data(UNIVIE)
363
+ i = UNIVIE.first
364
+ # ======================================================================= #
365
+ # === a1
366
+ # ======================================================================= #
367
+ when /^a1/
368
+ set_data(A1)
369
+ i = A1.first
370
+ # ======================================================================= #
371
+ # === byte
372
+ # ======================================================================= #
373
+ when /^byte/ # This also includese bytehost.
374
+ set_data(BYTEHOST)
375
+ i = BYTEHOST.first
376
+ # ======================================================================= #
377
+ # === zerofees
378
+ # ======================================================================= #
379
+ when 'ZEROFEES','zero','ZERO'
380
+ set_data(ZEROFEES)
381
+ i = ZEROFEES.first
382
+ # ======================================================================= #
383
+ # === ucoz
384
+ # ======================================================================= #
385
+ when 'ucoz','UCOZ',
386
+ 'LAST',
387
+ /tanriel/i,
388
+ 'last'
389
+ set_data(UCOZ)
390
+ i = UCOZ.first
391
+ end
392
+ case i.to_s
393
+ # ======================================================================= #
394
+ # === shevy
395
+ # ======================================================================= #
396
+ when 'shevy','5','default' # Current default entry.
397
+ i = SQUARE7.first
398
+ # ======================================================================= #
399
+ # === a1
400
+ # ======================================================================= #
401
+ when '1','a1'
402
+ i = A1.first
403
+ # ======================================================================= #
404
+ # === unet
405
+ # ======================================================================= #
406
+ when '2','unet','uni','uniftp'
407
+ i = UNIVIE.first
408
+ # ======================================================================= #
409
+ # === geas
410
+ # ======================================================================= #
411
+ when '3',
412
+ 'geas'
413
+ i = GEAS.first
414
+ # ======================================================================= #
415
+ # === byte
416
+ # ======================================================================= #
417
+ when '4',
418
+ 'byte'
419
+ i = BYTEHOST.first
420
+ end
421
+ i = i.to_s # Need a String here.
422
+ # ======================================================================= #
423
+ # === Provide more information to the user
424
+ # ======================================================================= #
425
+ if debug?
426
+ opnn; e "The remote URL was set to: #{sfancy(i)}"
427
+ end
428
+ if be_verbose
429
+ e "Setting url to #{sfancy(i)} now."
430
+ end
431
+ FtpParadise.set_remote_url(i)
432
+ # ======================================================================= #
433
+ # And we will always initialize a new ftp-object as well, whenever
434
+ # we call this method:
435
+ # ======================================================================= #
436
+ initialize_a_new_net_ftp_object_with_this_remote_url(i)
437
+ end; alias set_this_host set_remote_url # === set_this_host
438
+ alias set_host set_remote_url # === set_host
439
+ alias set_url set_remote_url # === set_url
440
+ alias host= set_remote_url # === host=
441
+ alias url= set_remote_url # === url=
442
+ alias set_remote_host set_remote_url # === set_remote_host
443
+
444
+ # ========================================================================= #
445
+ # === show_host_user_name_port_and_password
446
+ #
447
+ # Inform us about the basic settings.
448
+ # ========================================================================= #
449
+ def show_host_user_name_port_and_password(
450
+ do_use_spacer_around_the_output = true
451
+ )
452
+ ljust = 15
453
+ e if do_use_spacer_around_the_output
454
+ e ('Host: ' ).ljust(ljust)+sfancy(host?)
455
+ e ('User-Name: ').ljust(ljust)+sfancy(user_name?.to_s)
456
+ e ('Port: ' ).ljust(ljust)+sfancy(port?)
457
+ e ('Password: ' ).ljust(ljust)+sfancy(password?)
458
+ e if do_use_spacer_around_the_output
459
+ end
460
+
461
+ # ========================================================================= #
462
+ # === use_default_dataset
463
+ #
464
+ # This method will just take the default dataset for my FTP connections,
465
+ # hence the "File.exist?" check.
466
+ #
467
+ # Additionally we will initialize the default net-ftp object.
468
+ #
469
+ # Up to 20.07.2022 we also automatically tried to log in, but since
470
+ # that day we no longer do this.
471
+ # ========================================================================= #
472
+ def use_default_dataset(
473
+ i = :default # ← This is the default.
474
+ )
475
+ if File.exist? FILE_ROEBE_FTP
476
+ dataset = YAML.load_file(FILE_ROEBE_FTP)
477
+ # ===================================================================== #
478
+ # Set remote-url, username and password through the following method:
479
+ # ===================================================================== #
480
+ FtpParadise.determine_user_dataset_from_this_hash(dataset, i)
481
+ # do_login
482
+ end
483
+ end
484
+
485
+ # ========================================================================= #
486
+ # === show_full_names?
487
+ # ========================================================================= #
488
+ def show_full_names?
489
+ @internal_hash[:show_full_names]
490
+ end
491
+
492
+ # ========================================================================= #
493
+ # === show_remote_listing
494
+ #
495
+ # Use this method whenever you want to show the remote entries.
496
+ #
497
+ # As of June 2016, you can pass in your own dataset into this method
498
+ # as well. It must conform to the Array with the four entries, which
499
+ # is also returned via the method sanitized_remote_directory_content?.
500
+ # ========================================================================= #
501
+ def show_remote_listing(
502
+ dataset = sanitized_remote_directory_content?,
503
+ be_verbose = be_verbose?
504
+ )
505
+ n_rjust = 10
506
+ _ = dataset
507
+ if show_full_names?
508
+ _.map! {|entry|
509
+ filename = entry[0]
510
+ entry[0] = remote_pwd?+filename # This is the file size.
511
+ entry
512
+ }
513
+ end
514
+ _.each_with_index { |array, index|
515
+ if be_verbose # Display only when in verbose mode, which is the default.
516
+ file_or_directory = array[1]
517
+ name_of_the_file = array.first
518
+ # =================================================================== #
519
+ # Get a pointer to the filesize as well.
520
+ # =================================================================== #
521
+ filesize = array[2].to_s.rjust(n_rjust)
522
+ if file_or_directory == 'directory'
523
+ name_of_the_file << '/' unless name_of_the_file.end_with? '/'
524
+ end
525
+ # =================================================================== #
526
+ # === Put a proper padding to the index
527
+ # =================================================================== #
528
+ new_index = (index+1).to_s.rjust(_.size.to_s.size)
529
+ n_pad = 125
530
+ case file_or_directory
531
+ when 'directory' # Display for directories.
532
+ name_of_the_file = sdir(name_of_the_file)
533
+ e (padding?+sdir(new_index+') ')+name_of_the_file).ljust(n_pad)+' '+
534
+ filesize
535
+ else
536
+ e (padding?+sfancy(new_index+') ')+sfancy(name_of_the_file)).ljust(n_pad)+' '+
537
+ filesize
538
+ end
539
+ end
540
+ }
541
+ end; alias show_file_listing show_remote_listing # === show_file_listing
542
+ alias show_remote_file_listing show_remote_listing # === show_remote_file_listing
543
+
544
+ # ========================================================================= #
545
+ # === show_remote_directories
546
+ # ========================================================================= #
547
+ def show_remote_directories
548
+ show_remote_directory_listing :default, :show_only_directories
549
+ end
550
+
551
+ # ========================================================================= #
552
+ # === show_full_names=
553
+ # ========================================================================= #
554
+ def show_full_names=(i = true)
555
+ @internal_hash[:show_full_names] = i
556
+ end; alias show_full_names show_full_names= # === show_full_names
557
+
558
+ # ========================================================================= #
559
+ # === show_user_and_password
560
+ # ========================================================================= #
561
+ def show_user_and_password
562
+ ljust = 12
563
+ e
564
+ e ('User-Name: ').ljust(ljust)+sfancy(user_name?.to_s)
565
+ e ('Password: ' ).ljust(ljust)+sfancy(password?)
566
+ e
567
+ end; alias show_user_name_and_password show_user_and_password # === show_user_name_and_password
568
+
569
+ # ========================================================================= #
570
+ # === sync_ftp_object_onto_the_main_namespace
571
+ #
572
+ # Invoke this method only after having made sure that ftp_object?
573
+ # returns a non-nil object.
574
+ # ========================================================================= #
575
+ def sync_ftp_object_onto_the_main_namespace
576
+ ::FtpParadise.ftp_object = self
577
+ end
578
+
579
+ # ========================================================================= #
580
+ # === upload_binary_file
581
+ #
582
+ # Use this method to upload a binary file to a remote host.
583
+ #
584
+ # The first argument `i` is the file that we wish to upload.
585
+ #
586
+ # The method will make use of the method .putbinaryfile().
587
+ #
588
+ # Documentation for that file can be found here:
589
+ #
590
+ # https://ruby-doc.org/stdlib/libdoc/net/ftp/rdoc/Net/FTP.html#method-i-putbinaryfile
591
+ #
592
+ # ========================================================================= #
593
+ def upload_binary_file(
594
+ i,
595
+ be_verbose = be_verbose?
596
+ )
597
+ be_verbose = false if be_verbose == :be_silent
598
+ if i.is_a? Array
599
+ i.each {|entry| upload_binary_file(entry, be_verbose) }
600
+ else
601
+ i = i.strip.delete(N) # Added Feb 2014.
602
+ if be_verbose
603
+ notify_the_user_about(i, __method__)
604
+ end
605
+ begin
606
+ # =================================================================== #
607
+ # Next we will delegate towards the @ftp_object:
608
+ # =================================================================== #
609
+ ftp_object?.putbinaryfile(i) # We will use the method .putbinaryfile()
610
+ @internal_hash[:uploaded_these_files] << i
611
+ if be_verbose
612
+ remote_path = rds(remote_path?+'/'+File.basename(i))
613
+ e 'Done uploading! The remote path is: '
614
+ e " #{simp(remote_path)}"
615
+ report_finished_uploading_of_this_file(i)
616
+ end
617
+ rescue Exception => error
618
+ e 'An error happened as we tried to use the method '+simp('upload_binary()')+'.'
619
+ e 'The method we used was: '+simp('ftp?.putbinaryfile(i)')
620
+ e 'We will feedback this error now (of class '+sfancy(error.class.to_s)+'):'
621
+ pp error
622
+ end
623
+ end
624
+ end; alias upload_binary upload_binary_file # === upload_binary
625
+ alias upload_this_binary_file upload_binary_file # === upload_this_binary_file()
626
+
627
+ # ========================================================================= #
628
+ # === upload_file
629
+ #
630
+ # This method will distinguish between a binary file or a text file,
631
+ # based on the transfer mode in use. The default is to work on a
632
+ # text file.
633
+ # ========================================================================= #
634
+ def upload_file(
635
+ i,
636
+ be_verbose = be_verbose?
637
+ )
638
+ if File.exist? i
639
+ case transfer_mode?
640
+ # ===================================================================== #
641
+ # === :ascii
642
+ # ===================================================================== #
643
+ when :ascii,
644
+ :text,
645
+ :default
646
+ upload_this_text_file(i, be_verbose)
647
+ # ===================================================================== #
648
+ # === :binary
649
+ # ===================================================================== #
650
+ when :binary
651
+ upload_this_binary_file(i, be_verbose)
652
+ end
653
+ update_raw_listing(:be_quiet)
654
+ else
655
+ opnn; e "No file called `#{sfile(i)}` appears to exist locally."
656
+ end
657
+ end; alias upload_this_file upload_file # === upload_this_file
658
+
659
+ # ========================================================================= #
660
+ # === set_array_available_hosts
661
+ #
662
+ # Use this method if you wish to define the available hosts. This is
663
+ # useful whenever you already have some pre-defined hosts that you wish
664
+ # to use.
665
+ # ========================================================================= #
666
+ def set_array_available_hosts(i = nil)
667
+ i = [i].flatten.compact
668
+ @internal_hash[:array_available_hosts] = i
669
+ end
670
+
671
+ # ========================================================================= #
672
+ # === set_input
673
+ # ========================================================================= #
674
+ def set_input(i)
675
+ if is_a? Symbol
676
+ i = '' # For now all Symbols are ignored here.
677
+ end
678
+ @input = i
679
+ end
680
+
681
+ # ========================================================================= #
682
+ # === set_username
683
+ #
684
+ # Set the username that you wish to use here. If the input is nil, a
685
+ # default name will be used instead.
686
+ # ========================================================================= #
687
+ def set_username(
688
+ i = DEFAULT_USER_NAME
689
+ )
690
+ i = i.first if i.is_a? Array
691
+ i = DEFAULT_USER_NAME if i.nil?
692
+ # ======================================================================= #
693
+ # The username will be stored on the toplevel-module.
694
+ # ======================================================================= #
695
+ FtpParadise.set_username(i)
696
+ end; alias set_user_name set_username # === set_user_name
697
+ alias login_name= set_username # === login_name?
698
+ alias set_name set_username # === set_name
699
+ alias set_user set_username # === set_user
700
+ alias set_login_name set_username # === set_login_name
701
+ alias user_name= set_username # === user_name?
702
+
703
+ # ========================================================================= #
704
+ # === username?
705
+ # ========================================================================= #
706
+ def username?
707
+ FtpParadise.username?.to_s
708
+ end; alias user_name? username? # === user_name?
709
+
710
+ # ========================================================================= #
711
+ # === download_remote_file (download tag)
712
+ #
713
+ # Use this method to download a remote file. If you are sure to have
714
+ # a binary file, the method download_binary_file() could be used
715
+ # instead.
716
+ #
717
+ # gettextfile(remotefile, localfile = File.basename(remotefile)) {|line| ...}
718
+ # ========================================================================= #
719
+ def download_remote_file(
720
+ i, be_verbose = be_verbose?
721
+ )
722
+ if i.is_a? Array # Handle arrays first.
723
+ i.each {|entry| download_remote_file(entry, be_verbose) }
724
+ else
725
+ if i =~ /^\d+$/ # if is a number
726
+ update_file_listing
727
+ i = return_remote_files[i.to_i - 1].first
728
+ end
729
+ if i == '*' # Here we want to download all files, as we passed in '*'.
730
+ i = []
731
+ update_file_listing
732
+ return_remote_files.each { |a,b| i << FtpParadise.rds(a) }
733
+ end
734
+ if be_verbose
735
+ notify_the_user_about(i, __method__)
736
+ end
737
+ set_file(i) # This assigns to @internal_hash[:file].
738
+ begin # We can use @file because we called set_file() before.
739
+ ftp_object?.gettextfile(file?)
740
+ basename = File.basename(file?)
741
+ e "Finished downloading `#{sandybrown(file?)}`"
742
+ e 'into `'+sdir(rds(Dir.pwd+'/'+basename))+'`.'
743
+ return file?
744
+ rescue Net::FTPPermError => error
745
+ pp error
746
+ e 'An exception occurred in the method '+sfancy('download()')+'.'
747
+ e 'The error was a '+sfancy('Permission Error')+', the input '\
748
+ 'to the method was: `'+simp(i)+'`.'
749
+ e 'Is the file that you are trying to download really '\
750
+ 'existing on the remote server?'
751
+ return false
752
+ end
753
+ end
754
+ end; alias download download_remote_file # === download
755
+ alias download_this_remote_file download_remote_file # === download_this_remote_file
756
+ alias download_this_file download_remote_file # === download_this_file
757
+
758
+ # ========================================================================= #
759
+ # === create_remote_file (touch tag)
760
+ #
761
+ # This "touches" a remote file.
762
+ # ========================================================================= #
763
+ def create_remote_file(
764
+ i,
765
+ be_verbose = be_verbose?
766
+ )
767
+ if i.is_a? Array
768
+ i.each {|entry| create_remote_file(entry, be_verbose) }
769
+ else
770
+ FileUtils.touch(i)
771
+ if be_verbose
772
+ notify_the_user_about(i, __method__)
773
+ end
774
+ upload_this_text_file(i, :be_quiet)
775
+ File.delete(i) if File.zero? i # And get rid of that file too.
776
+ end
777
+ end; alias touch create_remote_file # === touch
778
+
779
+ # ========================================================================= #
780
+ # === fancy_remote_listing
781
+ #
782
+ # This method will obtain the (remote) directory listing and then
783
+ # display it.
784
+ # ========================================================================= #
785
+ def fancy_remote_listing(
786
+ be_verbose = be_verbose?
787
+ )
788
+ update_file_listing
789
+ case be_verbose
790
+ when :be_silent,
791
+ :be_quiet
792
+ be_verbose = false
793
+ when :also_show_filesize
794
+ be_verbose = true
795
+ end
796
+ if be_verbose
797
+ e ('=' * 55)+' '+
798
+ FtpParadise.yellow('REMOTE FILES')+' '+('=' * 12)
799
+ if remote_directory_is_empty?
800
+ e "Remote `#{sdir(remote_path?)}` is empty."
801
+ e 'No files or directories can be found therein.'
802
+ else
803
+ e 'Remote content of `'+sdir(remote_path?)+'` is:'+N+N
804
+ e 'Index Filename '\
805
+ ' Filesize'
806
+ show_remote_file_listing
807
+ end
808
+ cliner
809
+ end
810
+ return remote_directory_content
811
+ end
812
+
813
+ # ========================================================================= #
814
+ # === rename
815
+ #
816
+ # This method will attempt to rename a file on the remote server.
817
+ #
818
+ # Note that this is equivalent to moving a file, which is why the alias
819
+ # move_file can also be used. Any move-file actioni s simply a rename()
820
+ # action.
821
+ #
822
+ # The first argument passed to this method should be the name of an
823
+ # existing (remote) file. The second second argument should be the
824
+ # new name of that file, or its full (remote) path.
825
+ #
826
+ # Also note that it seems as if the FTP protocol requires the full
827
+ # target location, otherwise errors such as the following might
828
+ # happen:
829
+ #
830
+ # ftp.rb in `getresp': 451 Rename/move failure: Is a directory (Net::FTPTempError)
831
+ #
832
+ # The command used by .rename() command should be equivalent to this code:
833
+ #
834
+ # SITE mv oldpath newpath
835
+ #
836
+ # Documentation for the functionality can be found here:
837
+ #
838
+ # http://ruby-doc.org/stdlib/libdoc/net/ftp/rdoc/Net/FTP.html#method-i-rename
839
+ #
840
+ # ========================================================================= #
841
+ def rename(
842
+ from,
843
+ to,
844
+ be_verbose = be_verbose?
845
+ )
846
+ to = to.first if to.is_a? Array
847
+ if from.is_a? Array # Support batch-transfer.
848
+ from.each {|entry| rename(entry, to) }
849
+ else
850
+ from = rds(from)
851
+ to = rds(to)
852
+ begin
853
+ ftp_object?.rename(from, to)
854
+ if be_verbose
855
+ opnn; e "Renamed the remote entry `#{sfancy(from)}"\
856
+ "` to `#{sfancy(to)}`."
857
+ end
858
+ rescue Net::FTPTempError => error
859
+ e "An error (#{simp('Net::FTPTempError')}) occurred "\
860
+ "in the method #{simp('rename()')}:"
861
+ pp error
862
+ end
863
+ end
864
+ end; alias rename_file rename # === rename_file
865
+ alias move_file rename # === move_file
866
+ alias rename_remote_file rename # === rename_remote_file
867
+
868
+ # ========================================================================= #
869
+ # === update_remote_file_listing
870
+ # ========================================================================= #
871
+ def update_remote_file_listing(
872
+ be_verbose = be_verbose?
873
+ )
874
+ case be_verbose
875
+ when :be_quiet
876
+ be_verbose = false
877
+ end
878
+ if is_connected?
879
+ begin
880
+ # =================================================================== #
881
+ # Make use of a method that will skip a few entries, such as
882
+ # "." or "..".
883
+ # =================================================================== #
884
+ @internal_hash[:raw_entries] = return_slightly_sanitized_entries_ignoring_a_few
885
+ rescue Exception => error
886
+ opnn; e swarn('An error happened in the method '\
887
+ 'update_remote_file_listing(), at '\
888
+ 'line: '+__LINE__.to_s+'.')
889
+ pp error.class
890
+ pp error
891
+ end
892
+ else
893
+ if be_verbose
894
+ opnn; e 'Can not update the remote file listing '\
895
+ 'because we are not connected.'
896
+ end
897
+ end
898
+ end; alias update_file_listing update_remote_file_listing # === update_file_listing
899
+ alias update_raw_listing update_remote_file_listing # === update_raw_listing
900
+ alias get_listing update_remote_file_listing # === get_listing
901
+ alias get_remote_listing update_remote_file_listing # === get_remote_listing
902
+ alias update update_remote_file_listing # === update
903
+
904
+ # ========================================================================= #
905
+ # === does_this_remote_file_exist?
906
+ # ========================================================================= #
907
+ def does_this_remote_file_exist?(i)
908
+ i = File.basename(i).strip
909
+ array = return_all_remote_files
910
+ if array.is_a?(Array) and
911
+ array.first.is_a?(String)
912
+ array.map! {|entry|
913
+ entry = FtpParadise::Entry.new(entry)
914
+ }
915
+ array.select! {|entry| entry.is_a_file? }
916
+ array.map! {|entry| entry.filename? }
917
+ end
918
+ return array.include?(i)
919
+ end
920
+
921
+ # ========================================================================= #
922
+ # === show_remote_directory_listing
923
+ #
924
+ # This will simply show the content of a remote directory.
925
+ #
926
+ # Invocation examples:
927
+ #
928
+ # show_remote_directory_listing
929
+ # show_remote_directory_listing :default, :show_only_directories
930
+ #
931
+ # ========================================================================= #
932
+ def show_remote_directory_listing(
933
+ i = list,
934
+ array_options = []
935
+ )
936
+ unless array_options.is_a? Array
937
+ array_options = [array_options]
938
+ end
939
+ case i
940
+ when :default
941
+ i = list
942
+ end
943
+ if i.is_a? Array
944
+ # ===================================================================== #
945
+ # Get rid of '.' and '..'.
946
+ # ===================================================================== #
947
+ i.reject! {|entry| entry.end_with?('..') or entry.end_with?('.') }
948
+ # ===================================================================== #
949
+ # First, turn them into entries.
950
+ # ===================================================================== #
951
+ i.map! {|entry| FtpParadise::Entry.new(entry) }
952
+ # ===================================================================== #
953
+ # Next, we can use different behaviours.
954
+ # ===================================================================== #
955
+ if array_options.include? :show_only_directories
956
+ i.select! {|entry| entry.is_a_directory? }
957
+ end
958
+ i.each {|entry| entry.show_the_line }
959
+ end
960
+ end; alias show_remote_files show_remote_directory_listing # === show_remote_files
961
+
962
+ # ========================================================================= #
963
+ # === upload (upload tag)
964
+ #
965
+ # This method can upload binary files, text files and whole directories.
966
+ # Based on that check, the method body will behave differently, and
967
+ # delegate to other methods such as upload_directory() or upload_file().
968
+ #
969
+ # A single file (as String) can be uploaded, or an Array of files. The
970
+ # upload activity will transfer the file or the files onto the remote host.
971
+ #
972
+ # The second argument specifies whether the method will be verbose and
973
+ # report back to the user, or whether the method will be quiet,
974
+ # defaulting to the return value of the method `be_verbose?`.
975
+ # ========================================================================= #
976
+ def upload(
977
+ i,
978
+ be_verbose = be_verbose?
979
+ )
980
+ be_verbose = false if be_verbose == :be_silent
981
+ if i.is_a? Array
982
+ i.each {|entry| upload(entry, be_verbose) }
983
+ else
984
+ if i == '*' # Here we want to upload all files.
985
+ i = get_all_local_files
986
+ upload(i, be_verbose)
987
+ else
988
+ # =================================================================== #
989
+ # === Handle upload of directories first
990
+ # =================================================================== #
991
+ if File.directory? i
992
+ upload_directory(i, be_verbose)
993
+ # =================================================================== #
994
+ # === Handle uploading of files next
995
+ # =================================================================== #
996
+ else
997
+ upload_file(i, be_verbose)
998
+ end
999
+ end
1000
+ end
1001
+ end
1002
+
1003
+ # ========================================================================= #
1004
+ # === uploaded_these_files?
1005
+ # ========================================================================= #
1006
+ def uploaded_these_files?
1007
+ @internal_hash[:uploaded_these_files]
1008
+ end
1009
+
1010
+ # ========================================================================= #
1011
+ # === list? (list tag)
1012
+ #
1013
+ # Returns an array of file information in the directory (the output
1014
+ # is like `ls -l`). If a block is given, it iterates through the
1015
+ # listing.
1016
+ # ========================================================================= #
1017
+ def list?(i = '*')
1018
+ # ======================================================================= #
1019
+ # We will also sanitize this a bit.
1020
+ # ======================================================================= #
1021
+ @internal_hash[:raw_entries] = return_slightly_sanitized_entries_ignoring_a_few
1022
+ return @internal_hash[:raw_entries] # And return the result here.
1023
+ end; alias ls list? # === ls
1024
+ alias populate_raw_entries list? # === populate_raw_entries
1025
+
1026
+ # ========================================================================= #
1027
+ # === list_content (list tag, ls tag)
1028
+ #
1029
+ # List available data.
1030
+ # ========================================================================= #
1031
+ def list_content
1032
+ report_current_remote_dir
1033
+ result = list?
1034
+ cliner { pp result }
1035
+ _ = result.first[0, 1]
1036
+ case _
1037
+ when 'd'
1038
+ e "Directory #{result.first}"
1039
+ # @array_directories
1040
+ when 'l'
1041
+ e "Link #{result.first}"
1042
+ else
1043
+ e "File #{result.first}"
1044
+ end
1045
+ end; alias do_list_content list_content # === list
1046
+ alias listing? list_content # === listing?
1047
+
1048
+ # ========================================================================= #
1049
+ # === file_listing_as_entries?
1050
+ # ========================================================================= #
1051
+ def file_listing_as_entries?
1052
+ _ = remote_file_listing?
1053
+ if _
1054
+ return _.map {|entry| FtpParadise::Entry.new(entry) }
1055
+ end
1056
+ return nil
1057
+ end
1058
+
1059
+ # ========================================================================= #
1060
+ # === closed?
1061
+ #
1062
+ # Returns true if the connection to our remote host is closed.
1063
+ # ========================================================================= #
1064
+ def closed?
1065
+ begin
1066
+ ftp_object?.closed? if ftp_object?
1067
+ rescue Net::FTPConnectionError
1068
+ true
1069
+ end
1070
+ end
1071
+
1072
+ # ========================================================================= #
1073
+ # === dataset?
1074
+ # ========================================================================= #
1075
+ def dataset?
1076
+ FtpParadise.data?
1077
+ end
1078
+
1079
+ # ========================================================================= #
1080
+ # === return_slightly_sanitized_entries_ignoring_a_few
1081
+ # ========================================================================= #
1082
+ def return_slightly_sanitized_entries_ignoring_a_few(
1083
+ i = '*'
1084
+ )
1085
+ ftp_object?.list(i).reject {|entry|
1086
+ entry.to_s.strip.empty? or entry.end_with?(' .') or entry.end_with?(' ..')
1087
+ }.map {|line|
1088
+ if line.end_with? ':' # <- Some remote FTP-hosts use ':' for a directory.
1089
+ line[-1,1] = '/'
1090
+ end
1091
+ line
1092
+ }
1093
+ end; alias list return_slightly_sanitized_entries_ignoring_a_few # === list
1094
+
1095
+ # ========================================================================= #
1096
+ # === populate_internal_hash_with_default_values
1097
+ # ========================================================================= #
1098
+ def populate_internal_hash_with_default_values
1099
+ # ======================================================================= #
1100
+ # === @internal_hash
1101
+ # ======================================================================= #
1102
+ @internal_hash = {}
1103
+ # ======================================================================= #
1104
+ # === :transfer_mode
1105
+ # ======================================================================= #
1106
+ @internal_hash[:transfer_mode] = :binary
1107
+ # ======================================================================= #
1108
+ # === :port
1109
+ #
1110
+ # The internal Hash keeps track of some configure-settings and slots
1111
+ # to be used that are of relevance to this class.
1112
+ # ======================================================================= #
1113
+ @internal_hash[:port] = nil # Has to be nil initially.
1114
+ # ======================================================================= #
1115
+ # === :be_verbose
1116
+ # ======================================================================= #
1117
+ @internal_hash[:be_verbose] = nil
1118
+ # ======================================================================= #
1119
+ # === :raw_entries
1120
+ # ======================================================================= #
1121
+ @internal_hash[:raw_entries] = nil
1122
+ @internal_hash[:file] = nil
1123
+ @internal_hash[:show_full_names] = false # Is false on startup.
1124
+ @internal_hash[:debug] = false
1125
+ # ======================================================================= #
1126
+ # === :array_available_hosts
1127
+ # ======================================================================= #
1128
+ @internal_hash[:array_available_hosts] = []
1129
+ # ======================================================================= #
1130
+ # === :padding
1131
+ # ======================================================================= #
1132
+ @internal_hash[:padding] = ' ' # This padding value is used for remote directory listing.
1133
+ # ======================================================================= #
1134
+ # The following Array keeps track over the files that were uploaded
1135
+ # successfully. This gives us the possibility to query this from other
1136
+ # classes.
1137
+ # ======================================================================= #
1138
+ @internal_hash[:uploaded_these_files] = []
1139
+ end
1140
+
1141
+ # ========================================================================= #
1142
+ # === is_a_directory?
1143
+ #
1144
+ # This method queries whether the given input is a (remote) directory.
1145
+ # For this to work, the given input must obviously exist as file or
1146
+ # directory.
1147
+ # ========================================================================= #
1148
+ def is_a_directory?(i)
1149
+ update_file_listing
1150
+ candidates = file_listing_as_entries?.select {|entry|
1151
+ entry.is_a_directory?
1152
+ }.map(&:last)
1153
+ candidates.include? i
1154
+ end; alias is_directory? is_a_directory? # === is_directory?
1155
+ alias is_a_directory? is_a_directory? # === is_a_directory?
1156
+ alias this_remote_directory_exists? is_a_directory? # === this_remote_directory_exists?
1157
+ alias is_dir? is_a_directory? # === is_dir?
1158
+
1159
+ # ========================================================================= #
1160
+ # === remote_directory_is_empty?
1161
+ #
1162
+ # This method will return a Boolean - true if the remote directory
1163
+ # is empty, and false otherwise.
1164
+ # ========================================================================= #
1165
+ def remote_directory_is_empty?
1166
+ _ = return_remote_directory_content
1167
+ _.reject! {|entry|
1168
+ (entry == '.') or (entry == '..')
1169
+ }
1170
+ _.empty?
1171
+ end
1172
+
1173
+ # ========================================================================= #
1174
+ # === create_this_remote_directory (mkdir tag)
1175
+ #
1176
+ # This method will attempt to create a remote directory.
1177
+ #
1178
+ # A Net::FTPPermError may result if the permission does not allow for
1179
+ # that action.
1180
+ # ========================================================================= #
1181
+ def create_this_remote_directory(
1182
+ i, be_verbose = be_verbose?
1183
+ )
1184
+ if i.is_a? Array
1185
+ i.each {|entry| create_this_remote_directory(entry, be_verbose) }
1186
+ else
1187
+ i = rds(i+'/')
1188
+ if be_verbose
1189
+ notify_the_user_about(i, __method__)
1190
+ if is_directory?(i)
1191
+ opnn; e swarn('Warning - the remote directory ')+
1192
+ sdir(i)+swarn(' already exists.')
1193
+ opnn; e swarn('We thus can not create a new directory.')
1194
+ end
1195
+ end
1196
+ begin
1197
+ ftp_object?.mkdir(i)
1198
+ rescue Net::FTPConnectionError
1199
+ opnn; e 'Not connected - is the network down/available?'
1200
+ rescue Net::FTPPermError
1201
+ opnn; e "Net::FTPPermError: Can not create the remote "\
1202
+ "directory `#{remote_path?}#{sdir(i)}`"
1203
+ opnn; e 'as it - or a file with the same name - already exists.'
1204
+ end
1205
+ end
1206
+ end; alias mkdir create_this_remote_directory # === mkdir
1207
+ alias rmkdir create_this_remote_directory # === rmkdir
1208
+ alias remote_mkdir create_this_remote_directory # === remote_mkdir
1209
+ alias create_directory create_this_remote_directory # === create_directory
1210
+ alias create_these_remote_directories create_this_remote_directory # === create_these_remote_directories
1211
+ alias remote_create_directory create_this_remote_directory # === remote_create_directory
1212
+ alias create_remote_directory create_this_remote_directory # === create_remote_directory
1213
+
1214
+ # ========================================================================= #
1215
+ # === sanitize_remote_directory_content
1216
+ #
1217
+ # The purpose of this method is to clean up the remote dataset.
1218
+ #
1219
+ # Keep in mind that the output comes in something like:
1220
+ #
1221
+ # "-rw-rw-rw- 1 web netscape 6820 May 30 2011 AppendToCookbook.rb"
1222
+ # "drwxrwxrwx 2 web netscape 8192 Oct 29 2007 CSS"
1223
+ # "-rw-rw-rw- 1 web netscape 10548 May 30 2011 Chained.rb"
1224
+ # "-rw-r--r-- 1 330 330 237904 Jun 9 14:24 11.03.2003_UniWien_Biologie_EinfuehrungInDieMikrobiologie.jpg",
1225
+ #
1226
+ # This should contain all the information that is needed.
1227
+ # ========================================================================= #
1228
+ def sanitize_remote_directory_content
1229
+ _ = []
1230
+ raw_entries?.each { |e|
1231
+ next if e.empty?
1232
+ entry = FtpParadise::Entry.new(e)
1233
+ filesize = entry.filesize?
1234
+ timestamp = entry.parsed_timestamp?
1235
+ # ===================================================================== #
1236
+ # === Exclude 3 entries next
1237
+ # ===================================================================== #
1238
+ next if e.include? 'total' or
1239
+ entry.name? == '.' or
1240
+ entry.name? == '..' # Batch next.
1241
+ # ===================================================================== #
1242
+ # === Build up the final Array
1243
+ #
1244
+ # Our Array will have four entries:
1245
+ #
1246
+ # (1) Filename
1247
+ # (2) File or Directory (String)
1248
+ # (3) Filesize
1249
+ # (4) Timestamp
1250
+ #
1251
+ # ===================================================================== #
1252
+ _ << [ rds(entry.filename?), entry.file_or_directory, filesize, timestamp ]
1253
+ }
1254
+ @internal_hash[:sanitized_remote_directory_content] = _ #.compact
1255
+ end
1256
+
1257
+ # ========================================================================= #
1258
+ # === sanitized_remote_directory_content?
1259
+ # ========================================================================= #
1260
+ def sanitized_remote_directory_content?
1261
+ update_remote_file_listing
1262
+ sanitize_remote_directory_content
1263
+ @internal_hash[:sanitized_remote_directory_content]
1264
+ end
1265
+
1266
+ # ========================================================================= #
1267
+ # === download_binary_file
1268
+ #
1269
+ # Use this method to download a binary file, by calling the method
1270
+ # getbinaryfile(). You can download as many files as you want to
1271
+ # through this method, but we expect this method to be a binary
1272
+ # file.
1273
+ #
1274
+ # Specific usage example:
1275
+ #
1276
+ # ftp?.download_binary_file('photos_2009-03-29.zip', 'ftp_photos/photos.zip')
1277
+ #
1278
+ # ========================================================================= #
1279
+ def download_binary_file(
1280
+ i,
1281
+ be_verbose = be_verbose?
1282
+ )
1283
+ if i.is_a? Array
1284
+ i.each {|entry| download_binary_file(entry) }
1285
+ else
1286
+ ftp?.getbinaryfile(i) # Delegate towards .getbinaryfile()
1287
+ if be_verbose
1288
+ e "Downloaded file #{sfile(i)}."
1289
+ end
1290
+ end
1291
+ end
1292
+
1293
+ # ========================================================================= #
1294
+ # === empty?
1295
+ # ========================================================================= #
1296
+ def empty?
1297
+ array_remote_files.empty?
1298
+ end
1299
+
1300
+ # ========================================================================= #
1301
+ # === find_matches_for
1302
+ #
1303
+ # This method will return an array of files and directories that match
1304
+ # to the provided input (which we will assume to be a query).
1305
+ # ========================================================================= #
1306
+ def find_matches_for(i)
1307
+ i = i.delete '*'
1308
+ update_file_listing
1309
+ _ = return_remote_directory_content.map(&:first)
1310
+ _ = _.grep(/#{i}/)
1311
+ return _
1312
+ end
1313
+
1314
+ # ========================================================================= #
1315
+ # === output_sorted_by_time
1316
+ #
1317
+ # This method will output the remote content in a time-sorted manner.
1318
+ # ========================================================================= #
1319
+ def output_sorted_by_time
1320
+ _ = sanitized_remote_directory_content?
1321
+ sorted_result = _.sort_by {|array|
1322
+ array.last
1323
+ }.reverse
1324
+ sorted_result.each_with_index {|array, index| index += 1
1325
+ file_or_directory = array[1]
1326
+ name_of_the_file = array.first
1327
+ if file_or_directory == 'directory'
1328
+ name_of_the_file << '/' unless name_of_the_file.end_with? '/'
1329
+ end
1330
+ index = simp( (index.to_s+') ').rjust(6))
1331
+ e index+sfancy(name_of_the_file)
1332
+ }
1333
+ end
1334
+
1335
+ # ========================================================================= #
1336
+ # === last_response
1337
+ #
1338
+ # The server's last response is available through this method here.
1339
+ # ========================================================================= #
1340
+ def last_response
1341
+ ftp_object?.last_response
1342
+ end; alias last_response? last_response # === last_response?
1343
+ alias last_server_response? last_response # === last_server_response?
1344
+
1345
+ # ========================================================================= #
1346
+ # === raw_entries?
1347
+ # ========================================================================= #
1348
+ def raw_entries?
1349
+ @internal_hash[:raw_entries]
1350
+ end; alias remote_file_listing? raw_entries? # === remote_file_listing?
1351
+ alias file_listing? raw_entries? # === file_listing?
1352
+ alias raw_listing? raw_entries? # === raw_listing?
1353
+
1354
+ # ========================================================================= #
1355
+ # === return_local_directories
1356
+ #
1357
+ # Return all local directories.
1358
+ # ========================================================================= #
1359
+ def return_local_directories
1360
+ Dir['*'].select {|entry| File.directory?(entry) }
1361
+ end
1362
+
1363
+ # ========================================================================= #
1364
+ # === modification_time_of?
1365
+ #
1366
+ # This method will give us the last modification time of a remote
1367
+ # file, by issuing the mdtm() command.
1368
+ #
1369
+ # The format returned will be in YYYMMDDhhmmss.
1370
+ #
1371
+ # If you require a parsed Time instance, you can use mtime()
1372
+ # on the ftp object.
1373
+ #
1374
+ # Symbols could also be used, such as "pp modification_time_of? :a".
1375
+ # ========================================================================= #
1376
+ def modification_time_of?(i)
1377
+ if i.is_a? Array
1378
+ i.each {|entry| modification_time_of(entry) } # <- Recursive call.
1379
+ else
1380
+ ftp_object?.mdtm(i.to_s)
1381
+ end
1382
+ end; alias mdtm modification_time_of? # === mdtm
1383
+
1384
+ # ========================================================================= #
1385
+ # === set_file
1386
+ #
1387
+ # Use only this to modify the @file variable.
1388
+ # ========================================================================= #
1389
+ def set_file(i = nil)
1390
+ @internal_hash[:file] = i
1391
+ end
1392
+
1393
+ # ========================================================================= #
1394
+ # === is_file?
1395
+ #
1396
+ # This method will check whether the input is a file or not.
1397
+ # It will call the method .is_directory?()
1398
+ # ========================================================================= #
1399
+ def is_file?(i)
1400
+ !is_a_directory?(i)
1401
+ end
1402
+
1403
+ # ========================================================================= #
1404
+ # === logged_in?
1405
+ # ========================================================================= #
1406
+ def logged_in?
1407
+ ftp_object?.instance_variable_get('@logged_in') and
1408
+ (ftp_object?.instance_variable_get('@logged_in') == true)
1409
+ end
1410
+
1411
+ # ========================================================================= #
1412
+ # === available_hosts?
1413
+ # ========================================================================= #
1414
+ def available_hosts?
1415
+ @internal_hash[:array_available_hosts]
1416
+ end; alias array_available_hosts available_hosts? # === array_available_hosts
1417
+ alias array_available_hosts? available_hosts? # === array_available_hosts?
1418
+
1419
+ # ========================================================================= #
1420
+ # === open_timeout?
1421
+ # ========================================================================= #
1422
+ def open_timeout?
1423
+ ftp_object?.open_timeout.to_s if ftp_object?.respond_to? :open_timeout
1424
+ end
1425
+
1426
+ # ========================================================================= #
1427
+ # === feedback_login_hosts
1428
+ #
1429
+ # Feedback all available login hosts, based on the information stored
1430
+ # in the Array @array_available_hosts.
1431
+ # ========================================================================= #
1432
+ def feedback_login_hosts
1433
+ opnn; e 'The followings hosts are easily available:'
1434
+ e
1435
+ available_hosts?.each { |host| e " - #{sfancy(host)}" }
1436
+ e
1437
+ end
1438
+
1439
+ # ========================================================================= #
1440
+ # === help?
1441
+ # ========================================================================= #
1442
+ def help?
1443
+ ftp_object?.help
1444
+ end; alias help help? # === help
1445
+
1446
+ # ========================================================================= #
1447
+ # === close (close tag)
1448
+ #
1449
+ # Close the connection here.
1450
+ #
1451
+ # Further operations will be impossible until a new connection
1452
+ # is opened up again, via connect().
1453
+ # ========================================================================= #
1454
+ def close
1455
+ ftp_object?.close
1456
+ end
1457
+
1458
+ # ========================================================================= #
1459
+ # === mlsd
1460
+ # ========================================================================= #
1461
+ def mlsd(i)
1462
+ ftp_object?.mlsd(i)
1463
+ end
1464
+
1465
+ # ========================================================================= #
1466
+ # === site
1467
+ # ========================================================================= #
1468
+ def site(i = nil)
1469
+ ftp_object?.site(i)
1470
+ end
1471
+
1472
+ # ========================================================================= #
1473
+ # === file?
1474
+ # ========================================================================= #
1475
+ def file?
1476
+ @internal_hash[:file]
1477
+ end
1478
+
1479
+ # ========================================================================= #
1480
+ # === system_command
1481
+ #
1482
+ # This will return system information from the remote host.
1483
+ #
1484
+ # Stuff like:
1485
+ # UNIX Type: L8
1486
+ # ========================================================================= #
1487
+ def system_command
1488
+ ftp_object?.system
1489
+ end; alias system system_command # === system
1490
+
1491
+ # ========================================================================= #
1492
+ # === report_host_port_user_name_and_password
1493
+ # ========================================================================= #
1494
+ def report_host_port_user_name_and_password
1495
+ ljust = 15
1496
+ e '- Now trying to log in to '+simp(host?)+
1497
+ ' (Port: '+swarn(port?)+') using:'
1498
+ e ' '+('Login Name: ').ljust(ljust)+sfancy(user_name?)
1499
+ e ' '+('Password: ').ljust(ljust)+sfancy(password?)
1500
+ end
1501
+
1502
+ # ========================================================================= #
1503
+ # === opnn
1504
+ # ========================================================================= #
1505
+ def opnn
1506
+ super(NAMESPACE)
1507
+ end
1508
+
1509
+ # ========================================================================= #
1510
+ # === read_timeout=
1511
+ #
1512
+ # Setter-method for the #read_timeout attribute.
1513
+ # ========================================================================= #
1514
+ def read_timeout=(i)
1515
+ ftp_object?.read_timeout = i
1516
+ end
1517
+
1518
+ # ========================================================================= #
1519
+ # === size?
1520
+ #
1521
+ # This method will return the size of the given (remote) filename.
1522
+ # ========================================================================= #
1523
+ def size?(i)
1524
+ ftp_object?.size(i)
1525
+ end; alias size size? # === size
1526
+
1527
+ # ========================================================================= #
1528
+ # === padding?
1529
+ # ========================================================================= #
1530
+ def padding?
1531
+ @internal_hash[:padding]
1532
+ end
1533
+
1534
+ # ========================================================================= #
1535
+ # === be_verbose?
1536
+ # ========================================================================= #
1537
+ def be_verbose?
1538
+ @internal_hash[:be_verbose]
1539
+ end
1540
+
1541
+ # ========================================================================= #
1542
+ # === server_welcome_message?
1543
+ #
1544
+ # This method will return the remote server's welcome message.
1545
+ # ========================================================================= #
1546
+ def server_welcome_message?
1547
+ ftp_object?.welcome
1548
+ end; alias welcome? server_welcome_message? # === welcome?
1549
+ alias welcome server_welcome_message? # === welcome
1550
+
1551
+ # ========================================================================= #
1552
+ # === noop
1553
+ # ========================================================================= #
1554
+ def noop
1555
+ ftp_object?.noop
1556
+ end
1557
+
1558
+ # ========================================================================= #
1559
+ # === last_response_code?
1560
+ #
1561
+ # Return the server's last response code.
1562
+ # ========================================================================= #
1563
+ def last_response_code?
1564
+ ftp_object?.last_response_code
1565
+ end; alias last_response_code last_response_code? # === last_response_code
1566
+
1567
+ # ========================================================================= #
1568
+ # === []
1569
+ # ========================================================================= #
1570
+ def [](i)
1571
+ update_file_listing
1572
+ if i =~ /^\d+$/ # If is a number.
1573
+ i = remote_file_listing.size if i.to_i > remote_file_listing.size
1574
+ i = remote_file_listing[i.to_i - 1].first
1575
+ end
1576
+ return i
1577
+ end
1578
+
1579
+ # ========================================================================= #
1580
+ # === notify_the_user_about
1581
+ #
1582
+ # This method is a general "user notifier". It will notify the user
1583
+ # about doing certain actions within the FtpParadise project.
1584
+ # ========================================================================= #
1585
+ def notify_the_user_about(
1586
+ i, method
1587
+ )
1588
+ case method
1589
+ # ======================================================================= #
1590
+ # === :set_transfer_mode
1591
+ # ======================================================================= #
1592
+ when :set_transfer_mode
1593
+ opnn; e "Setting mode to #{orange(i.to_s)} now."
1594
+ # ======================================================================= #
1595
+ # === :remove_remote_files
1596
+ # ======================================================================= #
1597
+ when :remove_remote_files
1598
+ opnn; e "Deleting the remote file `#{sdir(i)}` now."
1599
+ # ======================================================================= #
1600
+ # === :upload_binary_file
1601
+ # ======================================================================= #
1602
+ when :upload_binary_file
1603
+ opnn; e 'Now trying to upload the binary file `'+sfile(i)+'`'
1604
+ opnn; e 'to the remote host `'+sfancy(remote_host?)+'`.'
1605
+ # ======================================================================= #
1606
+ # === :create_this_remote_directory
1607
+ # ======================================================================= #
1608
+ when :create_this_remote_directory
1609
+ opnn; e 'Creating the remote directory `'+sdir(i)+'` now.'
1610
+ # ======================================================================= #
1611
+ # === :remote_cd
1612
+ # ======================================================================= #
1613
+ when :remote_cd
1614
+ opnn; e 'Trying to remote-change directory into `'+sdir(i)+'`.'
1615
+ # ======================================================================= #
1616
+ # === :download_this_remote_file
1617
+ # ======================================================================= #
1618
+ when :download_this_remote_file
1619
+ opnn; e "Downloading the remote file `#{sdir(i)}` now."
1620
+ # ======================================================================= #
1621
+ # === :upload_this_text_file
1622
+ # ======================================================================= #
1623
+ when :upload_this_text_file
1624
+ opnn; e 'Uploading the local text file `'+sfile(i)+'` to '\
1625
+ 'the remote host at `'+sfancy(remote_pwd?)+'`.'
1626
+ # ======================================================================= #
1627
+ # === :create_remote_file
1628
+ # ======================================================================= #
1629
+ when :create_remote_file
1630
+ opnn; e 'Creating the remote file `'+sdir(i)+'` now.'
1631
+ # ======================================================================= #
1632
+ # === :remove_remote_directory
1633
+ # ======================================================================= #
1634
+ when :remove_remote_directory
1635
+ opnn; e 'Removing the remote directory `'+sdir(i)+'` now.'
1636
+ end
1637
+ end
1638
+
1639
+ # ========================================================================= #
1640
+ # === report_finished_uploading_of_this_file
1641
+ #
1642
+ # Report that we have finished uploading a file.
1643
+ #
1644
+ # We should also denote the leading http part.
1645
+ # ========================================================================= #
1646
+ def report_finished_uploading_of_this_file(i)
1647
+ if is_connected?
1648
+ remote_path = "http://#{rds(remote_path?+File.basename(i))}"
1649
+ opnn; e "Done uploading `#{sfile(i)}` to `"\
1650
+ "#{sdir(remote_path)}`!"
1651
+ end
1652
+ end
1653
+
1654
+ # ========================================================================= #
1655
+ # === password?
1656
+ # ========================================================================= #
1657
+ def password?
1658
+ ::FtpParadise.password?.to_s
1659
+ end; alias password password? # === password
1660
+
1661
+ # ========================================================================= #
1662
+ # === set_password
1663
+ #
1664
+ # Use only this method when attempting to modify the @password.
1665
+ #
1666
+ # This @ivar keeps track of the password we will use.
1667
+ # ========================================================================= #
1668
+ def set_password(
1669
+ i = :try_to_use_a_default_password
1670
+ )
1671
+ case i
1672
+ # === try_to_use_a_default_password
1673
+ when :try_to_use_a_default_password,
1674
+ :default
1675
+ _ = return_password_from_bplaced
1676
+ _.chop! if _.end_with? '_'
1677
+ i = _
1678
+ when :anonymous
1679
+ i = nil
1680
+ else
1681
+ i = i.to_s
1682
+ end
1683
+ ::FtpParadise.set_password(i)
1684
+ i # Return the password here as well, so that we can use it for assignments.
1685
+ end; alias password= set_password # === password=
1686
+
1687
+ # ========================================================================= #
1688
+ # === return_password_from_bplaced
1689
+ # ========================================================================= #
1690
+ def return_password_from_bplaced
1691
+ dataset = YAML.load_file(FILE_ROEBE_FTP)['bplaced']
1692
+ return dataset['password']
1693
+ end
1694
+
1695
+ # ========================================================================= #
1696
+ # === set_port
1697
+ #
1698
+ # Use this method to set the port. The port will be stored on the
1699
+ # toplevel-"namespace".
1700
+ # ========================================================================= #
1701
+ def set_port(
1702
+ i = DEFAULT_PORT
1703
+ )
1704
+ FtpParadise.set_port(i)
1705
+ end
1706
+
1707
+ # ========================================================================= #
1708
+ # === port?
1709
+ # ========================================================================= #
1710
+ def port?
1711
+ FtpParadise.port?.to_s
1712
+ end; alias port port? # === port
1713
+
1714
+ require 'ftp_paradise/toplevel_methods/remote_url.rb'
1715
+ # ========================================================================= #
1716
+ # === remote_url?
1717
+ #
1718
+ # This method is guaranteed to return a String - except when an
1719
+ # error happens.
1720
+ # ========================================================================= #
1721
+ def remote_url?
1722
+ begin
1723
+ return FtpParadise.remote_url?.to_s
1724
+ rescue Interrupt
1725
+ exit # User interrupted, so we exit as requested.
1726
+ rescue Exception => error
1727
+ opnn; e 'We did encounter an error in the method '+
1728
+ simp(__method__.to_s)
1729
+ opnn; pp error
1730
+ return error.to_s # Return that exception.
1731
+ end
1732
+ end; alias remote_host? remote_url? # === remote_host?
1733
+ alias remote_url remote_url? # === remote_url
1734
+ alias url? remote_url? # === url?
1735
+ alias host? remote_url? # === host?
1736
+ alias host remote_url? # === host
1737
+
1738
+ # ========================================================================= #
1739
+ # === remove (remove tag)
1740
+ # ========================================================================= #
1741
+ def remove(i)
1742
+ if i.is_a? Array
1743
+ i.each {|entry| remove(entry) }
1744
+ else
1745
+ if is_a_directory?(i)
1746
+ remove_remote_directory(i)
1747
+ elsif is_a_file?(i)
1748
+ remove_remote_file(i, be_verbose?)
1749
+ end
1750
+ end
1751
+ end
1752
+
1753
+ # ========================================================================= #
1754
+ # === original_delete
1755
+ #
1756
+ # This method will remove the file, without doing any additional
1757
+ # checks.
1758
+ # ========================================================================= #
1759
+ def original_delete(i)
1760
+ ftp_object?.delete(i)
1761
+ end
1762
+
1763
+ # ========================================================================= #
1764
+ # === remove_remote_directory
1765
+ #
1766
+ # This method will remove a remote directory. For this to work, as
1767
+ # operation, the remote directory has to exist.
1768
+ #
1769
+ # This operation may fail e. g. when the remote directory is not empty.
1770
+ # This explains why we attempt to rescue some errors.
1771
+ # ========================================================================= #
1772
+ def remove_remote_directory(
1773
+ i,
1774
+ be_verbose = be_verbose?,
1775
+ force_remove = false
1776
+ )
1777
+ case force_remove
1778
+ when :force_remove
1779
+ force_remove = true
1780
+ when :do_not_force_remove
1781
+ force_remove = false
1782
+ end
1783
+ if i.is_a? Array
1784
+ i.each {|entry| remove_remote_directory(entry, be_verbose) }
1785
+ else
1786
+ if be_verbose
1787
+ notify_the_user_about(i, __method__)
1788
+ end
1789
+ if is_a_directory? i
1790
+ begin
1791
+ ftp_object?.rmdir(i)
1792
+ rescue Net::FTPPermError => error
1793
+ opnn; e swarn('We could not remove the remote directory at ')+
1794
+ sdir(i)+swarn(' as it is not empty.')
1795
+ pp error
1796
+ if force_remove
1797
+ opnn; e 'We will now try to enter into this directory'
1798
+ opnn; e 'and then remove all files of that directory.'
1799
+ rcd(this_dir)
1800
+ update_file_listing
1801
+ all_remote_files?.each {|file| remove(file) } # Now it should be removed.
1802
+ rcd('..') # Go back again.
1803
+ rmdir(i, be_verbose, :do_not_force_remove) # But we won't force again, to avoid recursive loops.
1804
+ opnn; e "The remote directory at #{sdir(i)} has been removed."
1805
+ end
1806
+ end
1807
+ else
1808
+ if be_verbose
1809
+ opnn; e "The given input #{sfancy(i)} is not a directory."
1810
+ end
1811
+ end
1812
+ end
1813
+ end; alias rmdir remove_remote_directory # === rmdir
1814
+ alias remove_these_remote_directories remove_remote_directory # === remove_these_remote_directories
1815
+ alias remove_directory remove_remote_directory # === remove_directory
1816
+
1817
+ # ========================================================================= #
1818
+ # === puttextfile
1819
+ #
1820
+ # This method will transfer a localfile to the remote server in
1821
+ # ASCII (text) mode. The result will be stored in "remotefile".
1822
+ #
1823
+ # If a callback or an associated block is supplied, calls it, passing
1824
+ # in the transmitted data one line at a time.
1825
+ # ========================================================================= #
1826
+ def puttextfile(
1827
+ local_file, remotefile = File.basename(local_file)
1828
+ )
1829
+ begin
1830
+ ftp_object?.puttextfile(local_file)
1831
+ @internal_hash[:uploaded_these_files] << local_file
1832
+ rescue Net::FTPPermError => error
1833
+ opnn; e swarn('Can not upload `')+sfile(local_file)+swarn('`.')
1834
+ opnn; e swarn('Reason provided to this method was:')
1835
+ opnn; e " → #{sfancy(error.to_s)}"
1836
+ rescue Exception => error
1837
+ opnn; e "An error happened in the method #{__method__}"
1838
+ pp error
1839
+ end
1840
+ end
1841
+
1842
+ # ========================================================================= #
1843
+ # === upload_this_text_file
1844
+ #
1845
+ # This method can be used to upload one or several text files.
1846
+ #
1847
+ # The first argument should be an Array or a String, denoting the
1848
+ # name/path of the local text file that you wish to upload.
1849
+ # ========================================================================= #
1850
+ def upload_this_text_file(
1851
+ i,
1852
+ be_verbose = be_verbose?
1853
+ )
1854
+ be_verbose = false if be_verbose == :be_silent
1855
+ if i.is_a? Array
1856
+ i.each {|entry| upload_this_text_file(entry, be_verbose) }
1857
+ else
1858
+ i = i.strip.delete(N) # Added in February 2014.
1859
+ case i
1860
+ when :default
1861
+ ENV['MISC'].to_s+'/SITEMAP.cgi' # <- Makes only sense for text-files anyway.
1862
+ end
1863
+ case be_verbose
1864
+ when :be_quiet
1865
+ be_verbose = false
1866
+ end
1867
+ if be_verbose
1868
+ notify_the_user_about(i, __method__)
1869
+ end
1870
+ puttextfile(i) # <- Delegate towards the method puttextfile().
1871
+ report_finished_uploading_of_this_file(i) if be_verbose
1872
+ end
1873
+ end
1874
+
1875
+ # ========================================================================= #
1876
+ # === upload_this_directory
1877
+ #
1878
+ # This method can be used to upload a local directory to a remote host.
1879
+ #
1880
+ # If the first input argument is an Array, then the method will call
1881
+ # itself recursively. This allows us to transfer several directories
1882
+ # in one go.
1883
+ #
1884
+ # If the input is a (local and existing) directory, then this method
1885
+ # will also have to create a remote directory, then chdir into it,
1886
+ # and then upload the content of that local directory to the remote
1887
+ # host.
1888
+ # ========================================================================= #
1889
+ def upload_this_directory(
1890
+ i,
1891
+ be_verbose = be_verbose?
1892
+ )
1893
+ if i.is_a? Array
1894
+ i.each {|entry| upload_this_directory(i, be_verbose) }
1895
+ else
1896
+ if File.directory? i
1897
+ unless this_remote_directory_exists?(i)
1898
+ remote_create_directory(i, be_verbose)
1899
+ end
1900
+ change_local_directory(i)
1901
+ change_remote_directory(i)
1902
+ report_remote_directory
1903
+ content = return_directory_content(i) # Last but not least, copy all files to that dir.
1904
+ content.each {|this_file| upload(this_file) }
1905
+ else
1906
+ opnn; e "The given input `#{sfancy(i)}` is not a directory."
1907
+ opnn; e 'This method can only upload directories.'
1908
+ end
1909
+ end
1910
+ end; alias upload_directory upload_this_directory # === upload_directory
1911
+ alias upload_these_directories upload_this_directory # === upload_these_directories
1912
+
1913
+ # ========================================================================= #
1914
+ # === set_transfer_mode
1915
+ #
1916
+ # This method will set to either one of two different possibles modes:
1917
+ #
1918
+ # (1) :ascii
1919
+ # (2) :binary
1920
+ # (3) :passive
1921
+ #
1922
+ # Note that :passive "mode" is ascii, with an additional invocation to
1923
+ # change the transfer mode to .passive.
1924
+ #
1925
+ # It will also change passive mode. The argument :default will default
1926
+ # to the more commonly used ASCII mode.
1927
+ #
1928
+ # When would you want to use ASCII mode?
1929
+ #
1930
+ # Use ascii mode for:
1931
+ #
1932
+ # txt, rtf, html, php
1933
+ #
1934
+ # Use binary mode for:
1935
+ #
1936
+ # images, videos and similar.
1937
+ #
1938
+ # ========================================================================= #
1939
+ def set_transfer_mode(
1940
+ i = DEFAULT_TRANSFER_MODE, # Will usually default to :ascii
1941
+ be_verbose = be_verbose?
1942
+ )
1943
+ case be_verbose
1944
+ when :be_verbose
1945
+ be_verbose = true
1946
+ when :be_quiet
1947
+ be_verbose = false
1948
+ end
1949
+ i = :ascii if i == :default
1950
+ case i
1951
+ # ======================================================================= #
1952
+ # === :ascii
1953
+ # ======================================================================= #
1954
+ when :ascii
1955
+ notify_the_user_about(i, __method__) if be_verbose
1956
+ @internal_hash[:transfer_mode] = :ascii
1957
+ ftp_object?.binary = false if ftp_object?
1958
+ # ======================================================================= #
1959
+ # === :binary
1960
+ # ======================================================================= #
1961
+ when :binary
1962
+ notify_the_user_about(i, __method__) if be_verbose
1963
+ @internal_hash[:transfer_mode] = :binary
1964
+ # ======================================================================= #
1965
+ # === :passive
1966
+ # ======================================================================= #
1967
+ when :passive,
1968
+ :pass
1969
+ notify_the_user_about(i, __method__) if be_verbose
1970
+ @internal_hash[:transfer_mode] = :ascii
1971
+ ftp_object?.passive = true if ftp_object?
1972
+ else
1973
+ opnn; e swarn('Not found the following mode: ')+
1974
+ sfancy(i.to_s)
1975
+ end
1976
+ end; alias mode_to_use= set_transfer_mode # === mode_to_use=
1977
+ alias set_mode set_transfer_mode # === set_mode
1978
+
1979
+ # ========================================================================= #
1980
+ # === report_transfer_mode_in_use
1981
+ # ========================================================================= #
1982
+ def report_transfer_mode_in_use
1983
+ e "Transfer mode: #{sfancy(transfer_mode?.to_s)}"
1984
+ end
1985
+
1986
+ # ========================================================================= #
1987
+ # === set_active
1988
+ # ========================================================================= #
1989
+ def set_active
1990
+ ftp_object?.passive = false
1991
+ end
1992
+
1993
+ # ========================================================================= #
1994
+ # === passive_transfer?
1995
+ # ========================================================================= #
1996
+ def passive_transfer?
1997
+ ftp_object?.passive
1998
+ end; alias passive? passive_transfer? # === passive?
1999
+
2000
+ # ========================================================================= #
2001
+ # === transfer_mode?
2002
+ #
2003
+ # This method will return the currently used transfer_mode. This mode
2004
+ # can be either :binary, or :ascii. By default it will be :binary.
2005
+ #
2006
+ # The transfer mode can be :binary or :text. :ascii is an alias to
2007
+ # :text.
2008
+ # ========================================================================= #
2009
+ def transfer_mode?
2010
+ @internal_hash[:transfer_mode]
2011
+ end; alias transfer_mode transfer_mode? # === transfer_mode
2012
+ alias mode? transfer_mode? # === mode?
2013
+ alias type transfer_mode? # === type
2014
+ alias type? transfer_mode? # === type?
2015
+
2016
+ # ========================================================================= #
2017
+ # === set_ascii
2018
+ #
2019
+ # Easier wrapper method.
2020
+ # ========================================================================= #
2021
+ def set_ascii
2022
+ set_transfer_mode :ascii
2023
+ end; alias set_ascii_mode set_ascii # === set_ascii_mode
2024
+
2025
+ # ========================================================================= #
2026
+ # === binary?
2027
+ #
2028
+ # When this is true, then then all FTP-transfers will be performed in
2029
+ # binary mode.
2030
+ #
2031
+ # Deaults to true.
2032
+ # ========================================================================= #
2033
+ def binary?
2034
+ ftp_object?.binary
2035
+ end; alias binary binary? # === binary
2036
+
2037
+ # ========================================================================= #
2038
+ # === set_binary_mode
2039
+ # ========================================================================= #
2040
+ def set_binary_mode
2041
+ set_transfer_mode :binary
2042
+ ftp_object?.binary = true
2043
+ end; alias set_binary set_binary_mode # === set_binary
2044
+ alias set_to_binary_mode set_binary_mode # === set_to_binary_mode
2045
+
2046
+ # ========================================================================= #
2047
+ # === set_passive_mode
2048
+ #
2049
+ # Use this when modifying the passive setting.
2050
+ # ========================================================================= #
2051
+ def set_passive_mode
2052
+ set_transfer_mode :ascii
2053
+ ftp_object?.passive = true if ftp_object?
2054
+ end; alias set_passive set_passive_mode # === set_passive
2055
+
2056
+ # ========================================================================= #
2057
+ # === set_default_transfer_mode
2058
+ # ========================================================================= #
2059
+ def set_default_transfer_mode(
2060
+ be_verbose = :be_quiet
2061
+ )
2062
+ set_transfer_mode(DEFAULT_TRANSFER_MODE, be_verbose)
2063
+ end
2064
+
2065
+ # ========================================================================= #
2066
+ # === set_debug
2067
+ # ========================================================================= #
2068
+ def set_debug(i = SHALL_WE_DEBUG)
2069
+ @internal_hash[:debug] = i
2070
+ end
2071
+
2072
+ # ========================================================================= #
2073
+ # === enable_debug_mode
2074
+ #
2075
+ # When the debug mode is set to true, then all traffic to and from
2076
+ # the server is written to $stdout. By default, this will NOT
2077
+ # be the case.
2078
+ # ========================================================================= #
2079
+ def enable_debug_mode
2080
+ ftp_object?.debug_mode = true
2081
+ end
2082
+
2083
+ # ========================================================================= #
2084
+ # === enable_debug
2085
+ #
2086
+ # Set the @debug variable to true, and also invoke enable_debug_mode().
2087
+ # ========================================================================= #
2088
+ def enable_debug
2089
+ enable_debug_mode
2090
+ set_debug(true)
2091
+ end
2092
+
2093
+ # ========================================================================= #
2094
+ # === debug?
2095
+ # ========================================================================= #
2096
+ def debug?
2097
+ @internal_hash[:debug]
2098
+ end
2099
+
2100
+ # ========================================================================= #
2101
+ # === disable_debug
2102
+ # ========================================================================= #
2103
+ def disable_debug
2104
+ ftp_object?.debug_mode = false
2105
+ @internal_hash[:debug] = false
2106
+ end
2107
+
2108
+ # ========================================================================= #
2109
+ # === debug (debug tag)
2110
+ #
2111
+ # This method can be used for some debugging output.
2112
+ # ========================================================================= #
2113
+ def debug(
2114
+ shall_we_debug = debug?
2115
+ )
2116
+ cliner {
2117
+ pp ftp?
2118
+ show_host_user_name_port_and_password
2119
+ update_file_listing
2120
+ if shall_we_debug
2121
+ opnn; e 'File Listing:'
2122
+ show_file_listing
2123
+ end
2124
+ if remote_file_listing?.empty?
2125
+ opnn; e 'No file could be found. The remote directory '\
2126
+ 'is most likely empty.'
2127
+ end
2128
+ } if shall_we_debug
2129
+ end; alias feedback debug # === feedback
2130
+ alias report debug # === report
2131
+
2132
+ # ========================================================================= #
2133
+ # === remote_pwd
2134
+ # ========================================================================= #
2135
+ def remote_pwd
2136
+ ftp_object?.pwd
2137
+ end; alias rpwd remote_pwd # === rpwd
2138
+ alias getdir remote_pwd # === getdir
2139
+
2140
+ # ========================================================================= #
2141
+ # === return_remote_pwd
2142
+ #
2143
+ # This method will return the (remote) pwd, including the remote working
2144
+ # directory - including the subpath..
2145
+ #
2146
+ # This method will ensure that a trailing '/' will be returned here.
2147
+ #
2148
+ # The official documentation can be seen here:
2149
+ # https://ruby-doc.org/stdlib/libdoc/net/ftp/rdoc/Net/FTP.html#method-i-pwd
2150
+ # ========================================================================= #
2151
+ def return_remote_pwd
2152
+ begin
2153
+ if is_connected?
2154
+ remote_pwd = remote_url?.dup
2155
+ # ===================================================================== #
2156
+ # Need to safeguard, in the event that we are not connected to a
2157
+ # remote FTP server.
2158
+ # ===================================================================== #
2159
+ if ftp_object? and is_connected? and logged_in?
2160
+ remote_pwd << ftp_object?.pwd.to_s
2161
+ end
2162
+ remote_pwd << '/'
2163
+ return rds(remote_pwd)
2164
+ else
2165
+ opnn; e 'No FTP connection is open.'
2166
+ ''
2167
+ end
2168
+ rescue Net::FTPReplyError
2169
+ opnn; e 'Error Net::FTPReplyError received. May be due to user interrupting.'
2170
+ opnn; e 'Exiting now at once either way.'
2171
+ exit
2172
+ rescue SystemExit, Interrupt
2173
+ opnn; e 'User requested to exit, thus exiting now.'
2174
+ exit
2175
+ end
2176
+ end; alias pwd? return_remote_pwd # === pwd?
2177
+ alias pwd return_remote_pwd # === pwd (pwd tag)
2178
+ alias getdir return_remote_pwd # === get_dir
2179
+ alias remote_pwd return_remote_pwd # === remote_pwd
2180
+ alias remote_pwd? return_remote_pwd # === remote_pwd?
2181
+ alias connected_to? return_remote_pwd # === connected_to?
2182
+ alias remote? return_remote_pwd # === remote?
2183
+ alias base_dir? return_remote_pwd # === base_dir?
2184
+ alias remote_directory? return_remote_pwd # === remote_directory?
2185
+ alias remote_dir? return_remote_pwd # === remote_dir?
2186
+ alias remote_path? return_remote_pwd # === remote_path?
2187
+ alias return_subdirectory return_remote_pwd # === return_subdirectory
2188
+ alias current_directory return_remote_pwd # === current_directory
2189
+ alias return_remote_dir return_remote_pwd # === return_remote_dir
2190
+ alias get_remote_dir return_remote_pwd # === get_remote_dir
2191
+ alias remote_host? return_remote_pwd # === remote_host?
2192
+
2193
+ # ========================================================================= #
2194
+ # === report_current_remote_dir
2195
+ #
2196
+ # Gives you the current dir.
2197
+ # ========================================================================= #
2198
+ def report_current_remote_dir(
2199
+ be_verbose = be_verbose?
2200
+ )
2201
+ begin
2202
+ if be_verbose
2203
+ opnn; e 'The remote directory is:'
2204
+ e " #{sdir(return_remote_pwd)}"
2205
+ end
2206
+ rescue Exception => error
2207
+ opnn; e error.class
2208
+ opnn; e error
2209
+ end
2210
+ end; alias report_remote_directory report_current_remote_dir # === report_remote_directory
2211
+ alias dir? report_current_remote_dir # === dir?
2212
+ alias report_remote_pwd report_current_remote_dir # === report_remote_pwd
2213
+
2214
+ # ========================================================================= #
2215
+ # === remote_chdir (cd tag, chdir tag)
2216
+ #
2217
+ # This method allows us to cd to another remote directory, on the
2218
+ # remote FTP server (our main connection).
2219
+ #
2220
+ # The method must be able to check whether we are connected to the
2221
+ # remote host.
2222
+ # ========================================================================= #
2223
+ def remote_chdir(
2224
+ i,
2225
+ be_verbose = be_verbose?,
2226
+ &block
2227
+ )
2228
+ if block_given?
2229
+ case yield
2230
+ # ===================================================================== #
2231
+ # === :be_verbose
2232
+ # ===================================================================== #
2233
+ when :be_verbose
2234
+ be_verbose = true
2235
+ end
2236
+ end
2237
+ i = i.dup if i.frozen?
2238
+ # ======================================================================= #
2239
+ # Sanitize odd entries ending with ':'
2240
+ # ======================================================================= #
2241
+ i[-1,1] = '/' if i.end_with? ':'
2242
+ i = rds("#{i}/") # <- Always ensure that a '/' is the last character.
2243
+ if be_verbose
2244
+ notify_the_user_about(i, __method__)
2245
+ end
2246
+ if is_connected?
2247
+ # ===================================================================== #
2248
+ # If we cd to a non-existing target, the exception Net::FTPPermError
2249
+ # will be raised.
2250
+ # ===================================================================== #
2251
+ begin
2252
+ ftp_object?.chdir(i)
2253
+ update_remote_file_listing
2254
+ # ===================================================================== #
2255
+ # The user may have insufficient permissions:
2256
+ # ===================================================================== #
2257
+ rescue Net::FTPPermError => error
2258
+ pp error
2259
+ rescue Net::ReadTimeout => error
2260
+ opnn; e 'An error was encountered in the method '\
2261
+ 'remote_chdir().'
2262
+ opnn; e 'The error-class was Net::ReadTimeout.'
2263
+ e
2264
+ opnn; e 'The specific error will be displayed next.'
2265
+ e
2266
+ pp error
2267
+ end
2268
+ else
2269
+ opnn; e 'We are not connected to a remote host right now.'
2270
+ opnn; e 'Thus we can not change the directory.'
2271
+ end
2272
+ report_current_remote_dir if be_verbose # right now mandatory
2273
+ end; alias rcd remote_chdir # === rcd
2274
+ alias remote_cd remote_chdir # === remote_cd
2275
+ alias chdir remote_chdir # === chdir
2276
+ alias cd remote_chdir # === cd
2277
+ alias chdir remote_chdir # === chdir
2278
+ alias rcd remote_chdir # === rcd
2279
+ alias change_directory remote_chdir # === change_directory
2280
+ alias change_remote_directory remote_chdir # === change_remote_directory
2281
+ alias cd_into_this_remote_directory remote_chdir # === cd_into_this_remote_directory
2282
+ alias remote_change_directory remote_chdir # === remote_change_directory
2283
+
2284
+ # ========================================================================= #
2285
+ # === return_remote_directories
2286
+ #
2287
+ # Give us a list of (remote) directories - only directories, not
2288
+ # files.
2289
+ #
2290
+ # An Array will be returned as a result.
2291
+ # ========================================================================= #
2292
+ def return_remote_directories
2293
+ _ = []
2294
+ update_file_listing # Populate the file listing anew, so we will always get proper results back.
2295
+ raw_listing?.each {|entry|
2296
+ entry = FtpParadise::Entry.new(entry)
2297
+ _ << rds(entry.return_name) if entry.is_a_directory?
2298
+ }
2299
+ # ======================================================================= #
2300
+ # Directories must end with '/'. Ensure this to be the case next.
2301
+ # ======================================================================= #
2302
+ _.map! {|entry|
2303
+ entry << '/' unless entry.end_with? '/'
2304
+ entry
2305
+ }
2306
+ return _
2307
+ end; alias directories? return_remote_directories # === directories?
2308
+ alias return_directories return_remote_directories # === return_directories
2309
+
2310
+ # ========================================================================= #
2311
+ # === return_remote_directory_content
2312
+ #
2313
+ # This method will return ALL remote entries, no matter if file or
2314
+ # directory.
2315
+ # ========================================================================= #
2316
+ def return_remote_directory_content
2317
+ raw_entries = raw_entries?
2318
+ if raw_entries.nil?
2319
+ populate_raw_entries
2320
+ raw_entries = raw_entries?
2321
+ end
2322
+ if raw_entries
2323
+ _ = raw_entries.reject {|line|
2324
+ line.empty?
2325
+ }.map {|entry|
2326
+ FtpParadise::Entry.new(entry).name?
2327
+ }
2328
+ end
2329
+ return _
2330
+ end; alias array_file_listing? return_remote_directory_content # === array_file_listing?
2331
+ alias array_file_listing return_remote_directory_content # === array_file_listing
2332
+ alias remote_directory_content return_remote_directory_content # === remote_directory_content
2333
+ alias list? return_remote_directory_content # === list?
2334
+
2335
+ # ========================================================================= #
2336
+ # === quit (quit tag)
2337
+ #
2338
+ # Use this method to quit (and disconnect) from the FTP Connection
2339
+ # again.
2340
+ # ========================================================================= #
2341
+ def quit
2342
+ begin
2343
+ if is_connected?
2344
+ if ftp_object?
2345
+ FtpParadise.clear_user_dataset
2346
+ ftp_object?.quit
2347
+ end
2348
+ end
2349
+ rescue Exception => error
2350
+ opnn; e "An error happened in the method #{sfancy(__method__)}()"
2351
+ pp error
2352
+ end
2353
+ end
2354
+
2355
+ # ========================================================================= #
2356
+ # === FtpParadise::Connection[]
2357
+ # ========================================================================= #
2358
+ def self.[](i = '')
2359
+ new(i)
2360
+ end
2361
+
2362
+ # ========================================================================= #
2363
+ # === chdir (cd tag, chdir tag)
2364
+ # ========================================================================= #
2365
+ def chdir(i)
2366
+ @ftp_object.chdir(i)
2367
+ end; alias cd chdir # === cd
2368
+ alias remote_cd chdir # === remote_cd
2369
+
2370
+ # ========================================================================= #
2371
+ # === pwd
2372
+ #
2373
+ # Returns the current remote directory.
2374
+ # ========================================================================= #
2375
+ def pwd
2376
+ "#{@ftp_object.pwd}/".squeeze('/')
2377
+ end; alias getdir pwd # === getdir
2378
+ alias remote_directory? pwd # === remote_directory?
2379
+
2380
+ # ========================================================================= #
2381
+ # === ftp_connection?
2382
+ # ========================================================================= #
2383
+ def ftp_connection?
2384
+ @ftp_object
2385
+ end; alias ftp_object? ftp_connection? # === ftp_object?
2386
+ alias net_ftp? ftp_connection? # === net_ftp?
2387
+ alias ftp? ftp_connection? # === ftp?
2388
+ alias ftp ftp_connection? # === ftp?
2389
+ alias ftp_object ftp_connection? # === ftp_object
2390
+
2391
+ # ========================================================================= #
2392
+ # === do_login
2393
+ #
2394
+ # This method is responsible for the login-action.
2395
+ #
2396
+ # The method signature for the net-ftp class' .login() is:
2397
+ #
2398
+ # login(user = "anonymous", passwd = nil, acct = nil)
2399
+ #
2400
+ # This method here accepts a Hash as first argument.
2401
+ #
2402
+ # For official information about .login(), see here:
2403
+ #
2404
+ # https://ruby-doc.org/stdlib/libdoc/net/ftp/rdoc/Net/FTP.html#method-i-login
2405
+ #
2406
+ # ========================================================================= #
2407
+ def do_login(
2408
+ to_this_url = nil, # The remote URL.
2409
+ use_this_as_username = username?, # The login-name.
2410
+ use_this_as_password = password?, # The password for that user.
2411
+ be_verbose = be_verbose?
2412
+ )
2413
+ if to_this_url.nil?
2414
+ to_this_url = FtpParadise.remote_url?
2415
+ elsif to_this_url.is_a? Hash
2416
+ end
2417
+ # ======================================================================= #
2418
+ # Rescue nil-passwords here.
2419
+ # ======================================================================= #
2420
+ if use_this_as_password.to_s.empty?
2421
+ use_this_as_password = set_password(:try_to_use_a_default_password)
2422
+ end
2423
+ if be_verbose
2424
+ # ===================================================================== #
2425
+ # Display some info to the user here.
2426
+ # ===================================================================== #
2427
+ e; cliner
2428
+ opnn; e "Using the URL #{royalblue(to_this_url)} (remote FTP host)."
2429
+ e
2430
+ e " Username: #{slateblue(use_this_as_username)}"
2431
+ e " Password: #{slateblue(use_this_as_password)}"
2432
+ e
2433
+ report_transfer_mode_in_use
2434
+ e
2435
+ cliner
2436
+ end
2437
+ if ftp_object?.nil? and !to_this_url.nil?
2438
+ initialize_a_new_net_ftp_object_with_this_url(to_this_url)
2439
+ end
2440
+ use_this_as_username = use_this_as_username.to_s
2441
+ # ======================================================================= #
2442
+ # The following code must be rescued because the login() method
2443
+ # may fail in various ways.
2444
+ # ======================================================================= #
2445
+ begin
2446
+ ftp_object?.login(
2447
+ use_this_as_username,
2448
+ use_this_as_password
2449
+ )
2450
+ # =================================================================== #
2451
+ # Next, assign towards the toplevel reference to the ftp-connection.
2452
+ # =================================================================== #
2453
+ sync_ftp_object_onto_the_main_namespace if ftp_object?
2454
+ if be_verbose and is_connected?
2455
+ e
2456
+ cliner {
2457
+ e "- #{sfancy('Successfully')} logged into "\
2458
+ "the remote FTP host at `#{simp(to_this_url)}`"
2459
+ }
2460
+ end
2461
+ rescue Net::FTPPermError => error
2462
+ opnn; e "We could not connect and login to `#{sfancy(to_this_url)}`."
2463
+ opnn; e 'It may be that you lack the proper permissions.'
2464
+ opnn; e 'This may happen because the user/password combination was'
2465
+ opnn; e 'incorrect. User and password combination will be shown next:'
2466
+ show_user_and_password
2467
+ opnn; e "Feedbacking that error next, of class #{error.class.to_s}:"
2468
+ opnn; e orange(error.to_s)
2469
+ rescue Net::FTPConnectionError => error
2470
+ opnn; e 'We do not seem to be connected. An error happened.'
2471
+ pp error
2472
+ pp error.class
2473
+ end
2474
+ end; alias do_connect do_login # === do_connect
2475
+ alias connect_to do_login # === connect_to
2476
+ alias connect do_login # === connect
2477
+ alias login do_login # === login
2478
+ alias login_to do_login # === login_to
2479
+ alias reconnect do_login # === reconnect
2480
+
2481
+ # ========================================================================= #
2482
+ # === remove_remote_file
2483
+ #
2484
+ # Remove a (remote) file, via the delete() method of the FTP protocol.
2485
+ #
2486
+ # Note that this method will only delete files.
2487
+ #
2488
+ # The official documentation for the Ruby-FTP delete() method can be
2489
+ # found here:
2490
+ #
2491
+ # https://www.ruby-doc.org/stdlib/libdoc/net/ftp/rdoc/Net/FTP.html#method-i-delete
2492
+ #
2493
+ # ========================================================================= #
2494
+ def remove_remote_file(
2495
+ i,
2496
+ be_verbose = be_verbose?
2497
+ )
2498
+ case be_verbose
2499
+ when :be_verbose
2500
+ be_verbose = true
2501
+ end
2502
+ if i.is_a? Array
2503
+ i.each {|entry| remove_remote_file(entry, be_verbose) }
2504
+ else
2505
+ if does_this_remote_file_exist?(File.basename(i))
2506
+ i = File.basename(i)
2507
+ if i =~ /^\d+$/ # if is a number
2508
+ update_file_listing
2509
+ _ = return_remote_file_listing[i.to_i - 1].first
2510
+ _ = File.basename(_)
2511
+ e "Performing a substitution of #{sfancy(i)}"\
2512
+ " to #{simp(_)}."
2513
+ i = _
2514
+ end
2515
+ if be_verbose
2516
+ notify_the_user_about(i, __method__)
2517
+ end
2518
+ ftp_object?.delete(i)
2519
+ update_file_listing
2520
+ return i # Also return the file that was deleted.
2521
+ else
2522
+ opnn; e "No remote file called `#{sfile(i)}` was "\
2523
+ "found at `#{sfancy(remote_pwd)}`."
2524
+ end
2525
+ end
2526
+ end; alias remote_remove remove_remote_file # === remote_remove
2527
+ alias remote_remove_files remove_remote_file # === remote_remove_files
2528
+ alias remote_remove_file remove_remote_file # === remote_remove_files
2529
+ alias delete remove_remote_file # === delete
2530
+ alias remove_file remove_remote_file # === remove_file
2531
+ alias rm_file remove_remote_file # === rm_file
2532
+ alias rmfile remove_remote_file # === rmfile
2533
+ alias delete_this_remote_file remove_remote_file # === delete_this_remote_file
2534
+
2535
+ # ========================================================================= #
2536
+ # === return_all_remote_files
2537
+ #
2538
+ # This method will return an Array with all remote files.
2539
+ # ========================================================================= #
2540
+ def return_all_remote_files
2541
+ results = []
2542
+ if file_listing?
2543
+ results = file_listing?.select {|entry|
2544
+ if entry.is_a?(String) and !entry.empty?
2545
+ entry = FtpParadise::Entry.new(entry)
2546
+ end
2547
+ entry.is_a_file?
2548
+ }
2549
+ end
2550
+ return results
2551
+ end; alias remote_file_listing? return_all_remote_files # === remote_file_listing?
2552
+ alias all_remote_files? return_all_remote_files # === all_remote_files?
2553
+ alias array_remote_files return_all_remote_files # === array_remote_files
2554
+ alias return_remote_files return_all_remote_files # === return_remote_files
2555
+ alias return_remote_file_listing return_all_remote_files # === return_remote_file_listing
2556
+ alias remote_files? return_all_remote_files # === remote_files
2557
+ alias files? return_all_remote_files # === files?
2558
+
2559
+ # ========================================================================= #
2560
+ # === open?
2561
+ #
2562
+ # This method can also be used to determine whether we are still
2563
+ # connected to the remote site.
2564
+ #
2565
+ # This method will return true if the connection is open.
2566
+ #
2567
+ # If you want to determine whether you are still connected to the
2568
+ # remote host, you can alias use the alias are_we_connected? - it
2569
+ # may read nicer.
2570
+ # ========================================================================= #
2571
+ def open?
2572
+ !closed?
2573
+ end; alias are_we_connected? open? # === are_we_connected?
2574
+ alias is_connected? open? # === is_connected?
2575
+ alias is_connected open? # === is_connected
2576
+ alias connected? open? # === connected?
2577
+ alias did_we_connect? open? # === did_we_connect?
2578
+
2579
+ # ========================================================================= #
2580
+ # === status?
2581
+ #
2582
+ # Report the status here. This is equivalent to the STAT command.
2583
+ # ========================================================================= #
2584
+ def status?
2585
+ ftp_object?.status.to_s
2586
+ end; alias status status? # === status
2587
+ alias remote_status? status? # === remote_status?
2588
+
2589
+ # ========================================================================= #
2590
+ # === initialize_a_new_net_ftp_object_with_this_remote_url
2591
+ #
2592
+ # This method is the only one allowed to create a new Net::FTP instance.
2593
+ # ========================================================================= #
2594
+ def initialize_a_new_net_ftp_object_with_this_remote_url(i)
2595
+ @ftp_object = Net::FTP.new(i) # ftp = Net::FTP.new(YAML.load_file(ENV['FTP_YAML_FILE'])['freehosting']['url'])
2596
+ end; alias initialize_a_new_net_ftp_object initialize_a_new_net_ftp_object_with_this_remote_url # === initialize_a_new_net_ftp_object
2597
+ alias initialize_a_new_net_ftp_object_with_this_url initialize_a_new_net_ftp_object_with_this_remote_url # === initialize_a_new_net_ftp_object_with_this_url
2598
+
2599
+ # ========================================================================= #
2600
+ # === connect_via_this_dataset
2601
+ # ========================================================================= #
2602
+ def connect_via_this_dataset(hash)
2603
+ set_data(hash)
2604
+ if ::FtpParadise.remote_host?.nil? and hash.has_key?(:remote_url)
2605
+ ::FtpParadise.set_remote_host(hash[:remote_url])
2606
+ end
2607
+ do_login(FtpParadise.remote_url?)
2608
+ end
2609
+
2610
+ # ========================================================================= #
2611
+ # === set_data (all in one, set_data tag)
2612
+ #
2613
+ # This method sets:
2614
+ #
2615
+ # - host
2616
+ # - user name
2617
+ # - port and
2618
+ # - password
2619
+ #
2620
+ # This method is thus a nifty little convenience method. You can pass
2621
+ # a hash to it too, which is the recommended way to use this method.
2622
+ #
2623
+ # You can also use an Array (with 4 elements), in which case we will
2624
+ # process it one after the other. The reason for this procedure is
2625
+ # because we can also use yaml files that way, that also use the
2626
+ # exact order of elements.
2627
+ #
2628
+ # If you add a new entry to the case menu below, also add this to
2629
+ # ARRAY_AVAILABLE_HOSTS, please. That Array can be found in the
2630
+ # file 'constants/roebe_ftp_constants.rb'.
2631
+ # ========================================================================= #
2632
+ def set_data(
2633
+ i = 'default'
2634
+ ) # set the default here.
2635
+ if debug?
2636
+ opnn; e 'We will debug next, as the @debug variable was set to true.'
2637
+ pp i
2638
+ end
2639
+ # ======================================================================= #
2640
+ # === Handle Hash as input first
2641
+ # ======================================================================= #
2642
+ if i.is_a? Hash # Hash is treated differently.
2643
+
2644
+ # ===================================================================== #
2645
+ # === :host
2646
+ # ===================================================================== #
2647
+ if i.has_key? :host
2648
+ set_host i.fetch(:host)
2649
+ # ===================================================================== #
2650
+ # === :remote_host
2651
+ # ===================================================================== #
2652
+ elsif i.has_key? :remote_host
2653
+ set_host i.fetch(:remote_host)
2654
+ elsif i.has_key? :to # :to is an alias to :host.
2655
+ set_host i.fetch(:to)
2656
+ elsif i.has_key? :remote_url
2657
+ set_host i.fetch(:remote_url)
2658
+ end
2659
+
2660
+ # ===================================================================== #
2661
+ # === :user_name
2662
+ # ===================================================================== #
2663
+ if i.has_key? :user_name
2664
+ set_user_name i.fetch(:user_name)
2665
+ elsif i.has_key? :login_name
2666
+ set_user_name i.fetch(:login_name)
2667
+ end
2668
+
2669
+ # ===================================================================== #
2670
+ # === :password
2671
+ # ===================================================================== #
2672
+ if i.has_key? :password
2673
+ set_password i.fetch(:password)
2674
+ # ===================================================================== #
2675
+ # === :login_password
2676
+ # ===================================================================== #
2677
+ elsif i.has_key? :login_password
2678
+ set_password i.fetch(:login_password)
2679
+ end
2680
+
2681
+ # ===================================================================== #
2682
+ # === :port
2683
+ # ===================================================================== #
2684
+ if i.has_key? :port
2685
+ set_port i.fetch(:port)
2686
+ end
2687
+ # ======================================================================= #
2688
+ # === Handle Array as input next
2689
+ # ======================================================================= #
2690
+ elsif i.is_a? Array # Example-Array: ["ftp.byethost33.com", "b33_14144659", "1aaaaaa", 21]
2691
+ set_host i.first
2692
+ set_user_name i[1]
2693
+ set_password i[2]
2694
+ set_port i[3]
2695
+ # ======================================================================= #
2696
+ # === Else, use simple toggle commands, such as 1,2,3,4,5 and so forth.
2697
+ # ======================================================================= #
2698
+ else # In the following case menu you can toggle your FTP.
2699
+ case i.to_s # Work on strings only. Assumes shortcuts as well.
2700
+ # ===================================================================== #
2701
+ # === bplaced
2702
+ # ===================================================================== #
2703
+ when '1',
2704
+ 'bplaced',
2705
+ /shevy/i,
2706
+ 'default',
2707
+ 'top' # Current default.
2708
+ dataset = YAML.load_file(FILE_ROEBE_FTP)['bplaced']
2709
+ set_host dataset['host']
2710
+ set_user_name dataset['user_name']
2711
+ set_password dataset['password']
2712
+ set_port dataset['port']
2713
+ # ===================================================================== #
2714
+ # === shevy
2715
+ #
2716
+ # This defaults to my home system.
2717
+ # ===================================================================== #
2718
+ when '2',
2719
+ 'square',
2720
+ 'square7',
2721
+ 'podserver'
2722
+ _ = FILE_ROEBE_FTP
2723
+ if File.exist? _
2724
+ data = YAML.load_file(_)['bplaced']
2725
+ set_host data['url']
2726
+ set_user_name data['user_name']
2727
+ this_password = data['password']
2728
+ this_password.chop! if this_password.end_with? '_'
2729
+ set_password this_password
2730
+ set_port data['port']
2731
+ end
2732
+ # ===================================================================== #
2733
+ # === a1
2734
+ # ===================================================================== #
2735
+ when '3',
2736
+ 'a1',
2737
+ 'a1_ftp' # A1 FTP host. No longer in use but still kept.
2738
+ set_host A1.first
2739
+ set_user_name A1[1]
2740
+ set_password A1[2]
2741
+ set_port A1[3]
2742
+ # ===================================================================== #
2743
+ # === zymix
2744
+ # ===================================================================== #
2745
+ when '4',
2746
+ 'zymix',
2747
+ 'standard'
2748
+ set_host ZYMIX.first
2749
+ set_user_name ZYMIX[1]
2750
+ set_password ZYMIX[2]
2751
+ set_port ZYMIX[3]
2752
+ # ===================================================================== #
2753
+ # === uniwien
2754
+ # ===================================================================== #
2755
+ when '5',
2756
+ 'univie',
2757
+ 'uniwien' # Uni Wien FTP Account.
2758
+ set_host UNIVIE.first
2759
+ set_user_name UNIVIE[1]
2760
+ set_password UNIVIE[2]
2761
+ set_port UNIVIE[3]
2762
+ # ===================================================================== #
2763
+ # === byte
2764
+ # ===================================================================== #
2765
+ when '6',
2766
+ 'byte',
2767
+ 'bytehost'
2768
+ dataset = YAML.load_file(FILE_ROEBE_FTP)['bytehost']
2769
+ set_host dataset['host']
2770
+ set_user_name dataset['user_name']
2771
+ set_password dataset['password']
2772
+ set_port dataset['port']
2773
+ else
2774
+ set_data(:default) # Go back to default again if not found.
2775
+ end
2776
+ end
2777
+ end
2778
+
2779
+ # ========================================================================= #
2780
+ # === upload_this_local_file
2781
+ # ========================================================================= #
2782
+ def upload_this_local_file(i)
2783
+ i = i.join if i.is_a? Array
2784
+ ftp_connection?.putbinaryfile(i)
2785
+ end; alias putbinaryfile upload_this_local_file # === putbinaryfile
2786
+
2787
+ # ========================================================================= #
2788
+ # === run (run tag)
2789
+ # ========================================================================= #
2790
+ def run
2791
+ do_connect
2792
+ end
2793
+
2794
+ end; end
2795
+
2796
+ if __FILE__ == $PROGRAM_NAME
2797
+ if FtpParadise.is_on_roebe?
2798
+ FtpParadise::Connection.new(ARGV) { :use_default_dataset }
2799
+ else
2800
+ FtpParadise::Connection.new(ARGV)
2801
+ end
2802
+ end # connection.rb