lib/ftpd/telnet.rb in ftpd-0.9.0 vs lib/ftpd/telnet.rb in ftpd-0.10.0
- old
+ new
@@ -48,11 +48,11 @@
# Create a new instance with a command that may contain Telnet
# sequences.
# @param command [String]
def initialize(command)
- telnet_state_machine command
+ parse_command command
end
private
module Codes
@@ -64,54 +64,49 @@
IP = 244.chr # 0xf4
DM = 242.chr # 0xf2
end
include Codes
- def telnet_state_machine (command)
+ def accept(scanner)
+ @plain << scanner[1]
+ end
+
+ def reply_dont(scanner)
+ @reply << IAC + DONT + scanner[1]
+ end
+
+ def reply_wont(scanner)
+ @reply << IAC + WONT + scanner[1]
+ end
+
+ def ignore(scanner)
+ end
+
+ # Telnet sequences to handle, and how to handle them
+
+ SEQUENCES = [
+ [/#{IAC}(#{IAC})/, :accept],
+ [/#{IAC}#{WILL}(.)/m, :reply_dont],
+ [/#{IAC}#{WONT}(.)/m, :ignore],
+ [/#{IAC}#{DO}(.)/m, :reply_wont],
+ [/#{IAC}#{DONT}(.)/m, :ignore],
+ [/#{IAC}#{IP}/, :ignore],
+ [/#{IAC}#{DM}/, :ignore],
+ [/(.)/m, :accept],
+ ]
+
+ # Parse the the command. Sets @plain and @reply
+
+ def parse_command(command)
@plain = ''
@reply = ''
- state = :idle
- command.each_char do |c|
- case state
- when :idle
- if c == IAC
- state = :iac
- else
- @plain << c
+ scanner = StringScanner.new(command)
+ while !scanner.eos?
+ SEQUENCES.each do |regexp, method|
+ if scanner.scan(regexp)
+ send method, scanner
+ break
end
- when :iac
- case c
- when IAC
- @plain << c
- state = :idle
- when WILL
- state = :will
- when WONT
- state = :wont
- when DO
- state = :do
- when DONT
- state = :dont
- when IP
- state = :idle
- when DM
- state = :idle
- else
- @plain << IAC + c
- state = :idle
- end
- when :will
- @reply << IAC + DONT + c
- state = :idle
- when :wont
- state = :idle
- when :do
- @reply << IAC + WONT + c
- state = :idle
- when :dont
- state = :idle
- else
- raise "Unknown state #{state.inspect}"
end
end
end
end