diff --git a/README.markdown b/README.markdown index 1fbffd8..832a73e 100644 --- a/README.markdown +++ b/README.markdown @@ -98,6 +98,9 @@ yield the appropriate value: - an array of strings to join with the standard FTP line break and send to the client + mtime(path, &block) + - time of last modification or nil if the file doesn't exist + The driver MUST have one of the following methods. Each method MUST accept a block and yield the appropriate value: diff --git a/lib/em-ftpd/files.rb b/lib/em-ftpd/files.rb index e8b3986..73878e5 100644 --- a/lib/em-ftpd/files.rb +++ b/lib/em-ftpd/files.rb @@ -143,5 +143,21 @@ def cmd_stor_tempfile(target_path) end end + # return the file's mtime + def cmd_mdtm(param) + send_unauthorised and return unless logged_in? + send_param_required and return if param.nil? + + path = build_path(param) + + @driver.mtime(path) do |result| + if result.kind_of?(Time) + send_response result.strftime("213 %Y%m%d%H%M%S%L") + else + send_response "550 file not available" + end + end + end + end end diff --git a/lib/em-ftpd/server.rb b/lib/em-ftpd/server.rb index c71cd2c..fc2ead4 100644 --- a/lib/em-ftpd/server.rb +++ b/lib/em-ftpd/server.rb @@ -16,7 +16,7 @@ class Server < EM::Connection COMMANDS = %w[quit type user retr stor eprt port cdup cwd dele rmd pwd list size syst mkd pass xcup xpwd xcwd xrmd rest allo nlst - pasv epsv help noop mode rnfr rnto stru feat] + pasv epsv help noop mode rnfr rnto stru feat mdtm] attr_reader :root, :name_prefix attr_accessor :datasocket diff --git a/spec/server_spec.rb b/spec/server_spec.rb index 48cb3bc..2060084 100644 --- a/spec/server_spec.rb +++ b/spec/server_spec.rb @@ -847,3 +847,56 @@ end end + +describe EM::FTPD::Server, "MDTM" do + + before(:each) do + @c = EM::FTPD::Server.new(nil, TestDriver.new) + end + + it "should always respond with 530 when called by a non logged in user" do + @c.reset_sent! + @c.receive_line("MDTM one.txt") + @c.sent_data.should match(/530.+/) + end + + it "should always respond with 553 when called with no param" do + @c.receive_line("USER test") + @c.receive_line("PASS 1234") + @c.reset_sent! + @c.receive_line("MDTM") + @c.sent_data.should match(/553.+/) + end + + it "should always respond with 213 when called with a directory param" do + @c.receive_line("USER test") + @c.receive_line("PASS 1234") + @c.reset_sent! + @c.receive_line("MDTM files") + @c.sent_data.should match(/^213 20130421110000/) + end + + it "should always respond with 550 when called with a non-file param" do + @c.receive_line("USER test") + @c.receive_line("PASS 1234") + @c.reset_sent! + @c.receive_line("MDTM blah") + @c.sent_data.should match(/550.+/) + end + + it "should always respond with 213 when called with a valid file param" do + @c.receive_line("USER test") + @c.receive_line("PASS 1234") + @c.reset_sent! + @c.receive_line("MDTM one.txt") + @c.sent_data.should match(/^213 20130421120000/) + end + + it "should always respond with 213 when called with a valid file param" do + @c.receive_line("USER test") + @c.receive_line("PASS 1234") + @c.reset_sent! + @c.receive_line("MDTM files/two.txt") + @c.sent_data.should match(/^213 20130421130000/) + end +end diff --git a/spec/support/test_driver.rb b/spec/support/test_driver.rb index 8de27c6..afef129 100644 --- a/spec/support/test_driver.rb +++ b/spec/support/test_driver.rb @@ -64,6 +64,16 @@ def make_dir(path, &block) yield path == "/four" end + def mtime(path, &block) + yield case path + when "/files" then Time.utc(2013,4,21,11,0,0) + when "/one.txt" then Time.utc(2013,4,21,12,0,0) + when "/files/two.txt" then Time.utc(2013,4,21,13,0,0) + else + false + end + end + private def dir_item(name)