-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwipftpscan.rb
232 lines (201 loc) · 6.4 KB
/
wipftpscan.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
require 'net/ftp'
require 'io/console'
require "fileutils"
require 'byebug'
$dats = []
$txts = []
$cues = []
$zips = []
$ignored = []
$last_release = "2018-06-20"
$current_path = nil
#unix ftp list regex
$unix_list_regex = /^(?<type>.{1})(?<mode>\S+)\s+(?<number>\d+)\s+(?<owner>\S+)\s+(?<group>\S+)\s+(?<size>\d+)\s+(?<mod_time>.{12})\s+(?<path>.+)$/
$cues_regex = /(\.cue$|\.img$|CUE)/i
$relevantzip_regex = /.*(dat|dats|\(TOSEC-v\d{4}-\d{2}-\d{2}).*\.(zip|rar|7z)$/i
def scan(ftp, dir)
begin
puts "Scanning: " + dir + "/."
#STDOUT.flush
begin
ftp.chdir(dir)
$current_path = ftp.pwd
entries = ftp.list('*')
rescue Net::FTPTempError, Timeout::Error, Net::OpenTimeout, EOFError, Errno::EPIPE, Errno::ECONNRESET => e
puts "Error during FTP scan (entering/listing): #{e.message}"
puts "current path: #{$current_path}"
puts "subdirectory trying to explore: #{dir}"
sleep 3
reconnect(ftp)
ftp.chdir(dir)
$current_path = ftp.pwd
entries = ftp.list('*')
end
entries.each do |entry|
entry_info = entry.match($unix_list_regex)
#byebug
if (entry_info[:type] == 'd')
# puts "dir#{entry_info[:path]}"
scan(ftp, dir+"/"+entry_info[:path])
elsif(Date.parse(entry_info[:mod_time])>Date.parse($last_release))
if (entry_info[:path].end_with?('.dat'))
#puts "new dat: #{entry_info[:path]}"
$dats << "#{$current_path}/#{entry_info[:path]}"
elsif (entry_info[:path].end_with?('.txt'))
#puts "new txt: #{entry_info[:path]}"
$txts << "#{$current_path}/#{entry_info[:path]}"
elsif (entry_info[:path].match($cues_regex).nil? == false)
# puts "new cuefiles: #{entry_info[:path]}"
$cues << "#{$current_path}/#{entry_info[:path]}"
elsif (entry_info[:path].match($relevantzip_regex).nil? == false && entry_info[:size].to_i < 20_000_000)
# puts "new cuefiles: #{entry_info[:path]}"
$zips << "#{$current_path}/#{entry_info[:path]}"
else
#puts "new file (ignored): #{entry_info[:path]}"
$ignored << "#{$current_path}/#{entry_info[:path]}"
end
end
end
begin
ftp.chdir('..')
rescue Net::FTPTempError, Timeout::Error, Net::OpenTimeout, EOFError, Errno::EPIPE, Errno::ECONNRESET => e
puts "Error during FTP scan (exiting folder): #{e.message}"
puts "current path: #{$current_path}"
puts "subdirectory trying to explore: #{dir}"
sleep 3
reconnect(ftp)
ftp.chdir(dir)
$current_path = ftp.pwd
ftp.chdir('..')
end
rescue Net::FTPPermError => e
puts "Error during FTP scan: #{e.message}"
puts "current path: #{$current_path}"
puts "subdirectory trying to explore: #{dir}"
puts e.backtrace.inspect
ftp.chdir('..')
rescue StandardError => e
puts e.message
puts e.backtrace.inspect
#byebug
end
end
def reconnect(ftp)
puts "Reconnecting... (obj.id: #{ftp.object_id})"
ftp.close
ftp.connect($server)
ftp.login($user, $pass)
end
def transfer_files(ftp, files, base_path)
FileUtils.makedirs files.map {|x| File.dirname(File.join(base_path, x))}.uniq
files.each do | file |
puts "Transfering: " + file
ftp.getbinaryfile(file, File.join(base_path, file))
end
end
# Determine if the user is asking for help.
helpArgs = ["h", "-h", "/h", "?", "-?", "/?"]
if helpArgs.index(ARGV[0]) != nil || ARGV.length < 5 then
puts <<-eos
------------------------------
TOSECdev FTP WIP dats scanner:
------------------------------
This script recursively scans an ftp directory and returns a list of
all files relevant* for a new TOSEC release.
*) as in newer than the given last release date
USAGE:
ruby wipftpscan.rb [ftpserver] [username] [password] [last_release] [transfer] [base_remote_folder]
EXAMPLES:
ruby wipftpscan.rb ftp.example.com user passwd 2018-06-20 n
ruby wipftpscan.rb ftp.example.com user passwd 2018-06-20 y
ruby wipftpscan.rb ftp.example.com user passwd 2018-06-20 y uploads/renamers-wip
eos
else
$server, $user, $pass, $last_release, batch_transfer, base_remote_folder = ARGV
$dest_folder = "wip dats"# if $dest_folder.nil?
base_remote_folder = '/' if base_remote_folder.nil?
puts <<-eos
TOSECdev FTP WIP dats scanner
This script will scan all FTP folders for relevant dats/cues/txts/archives
FTP: #{$server}
USER: #{$user}
LAST RELEASE DATE: #{$last_release}
FTP BASE FOLDER: #{base_remote_folder}
DEST FOLDER: #{$dest_folder}
eos
#STDOUT.sync = true # output to stdout in realtime (no buffering) - slower but can check logs faster
ftp = Net::FTP.new($server)
#ftp.passive = true
ftp.login($user, $pass)
puts "SERVER INFO: #{ftp.system}"
#puts ftp.status
#byebug
puts "Initializing FTP scan for: #{$server}"
ftp.chdir(base_remote_folder)
scan(ftp, ftp.pwd) # to get the full path even if the given base path is relative
puts <<-eos
FTP scan finished.
Relevant dats: #{$dats.size}
Relevant txts: #{$txts.size}
Relevant cues: #{$cues.size}
Possible relevant zip/rar/7z: #{$zips.size}
Ignored files: #{$ignored.size}
eos
puts "NEW DATS:"
puts $dats
puts "NEW TXTs:"
puts $txts
puts "NEW CUEs:"
puts $cues
puts "NEW (Possible relevant) zip/rar/7z files:"
puts $zips
puts "IGNORED files:"
puts $ignored
user_input = ''
if (batch_transfer.nil?)
loop do
puts "Proceed with transfer of dats/txts/cues? (y/n)"
user_input = STDIN.getc
break if user_input != "y" || user_input != "n"
end
else
user_input = batch_transfer
end
if (user_input == "y")
puts "\n\nFTP file transfer starting..."
FileUtils.makedirs $dest_folder
transfer_files ftp, $dats, File.join($dest_folder, 'dats')
transfer_files ftp, $txts, File.join($dest_folder, 'txts')
transfer_files ftp, $cues, File.join($dest_folder, 'cues')
transfer_files ftp, $zips, File.join($dest_folder, 'zips')
end
ftp.close
end
module Net
class FTP
def makepasv
if @sock.peeraddr[0] == 'AF_INET'
host, port = parse229(sendcmd('EPSV'))
else
host, port = parse227(sendcmd('EPSV'))
end
return host, port
end
end
end
# def is_ftp_file?(ftp, file_name)
# ftp.chdir(file_name)
# ftp.chdir('..')
# false
# rescue
# true
# end
# def is_ftp_file?(ftp, file_name)
# begin
# if ftp.size(file_name).is_a? Numeric
# true
# end
# rescue Net::FTPPermError
# return false
# end
# end