ftp_service 0.2.0 → 0.3.0

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.
data/.gitignore CHANGED
@@ -19,5 +19,7 @@ rdoc
19
19
  doc
20
20
  pkg
21
21
  .yardoc
22
+ tmp
22
23
 
23
24
  ## PROJECT::SPECIFIC
25
+ test_keys/random_seed
@@ -1,8 +1,16 @@
1
+ # v0.3.0 (2010-03-18)
2
+
3
+ * `FtpService#write_request` and `FtpService#read_response` support
4
+ encryption/decryption with gpg.
5
+ * `FtpService#write_request` uses an intermediate temp file while
6
+ uploading to avoid case where server might try and respond to an
7
+ in-progress upload of a large request.
8
+ * `FtpService#read_response` polls for a response.
9
+
1
10
  # v0.2.0 (2010-03-08)
2
11
 
3
12
  * Add `FtpService#write_request` and `FtpService#read_response` methods,
4
13
  making this thing actually usable.
5
-
6
14
  * Switch to Markdown + Yardoc for rdocs.
7
15
 
8
16
  # v0.1.1 (2010-03-08)
@@ -3,7 +3,7 @@
3
3
  An FTP Service is like a web service except stupid. You send your
4
4
  request by uploading an xml file and get your response by downloading
5
5
  another xml file. Have you ever had to deal with something like that? I
6
- have.
6
+ have. It sucks.
7
7
 
8
8
  RDocs on [rdoc.info](http://rdoc.info/projects/blaix/ftp_service).
9
9
 
@@ -18,20 +18,15 @@ Source code on [github](http://github.com/blaix/ftp_service).
18
18
  require 'ftp_service'
19
19
 
20
20
  FtpService.open('host', 'user', 'pass') do |service|
21
- path = '/the/remote/path'
22
- service.write_request("#{path}/request.xml", '<foo>bar</foo>')
23
- response = service.read_response("#{path}/response.xml")
21
+ service.write_request('<foo>bar</foo>', "/request/path.xml")
22
+ response = service.read_response("/response/path.xml")
24
23
  end
25
24
 
26
- * `read_response` will block while it polls the server waiting for a
27
- response.
28
- * Temp files are created for the local request and response files and
29
- deleted when no longer needed.
30
-
31
25
  For more details, see the
32
- [RDocs](http://rdoc.info/projects/blaix/ftp_service) (sike they are
33
- really yardocs!).
26
+ [RDocs](http://rdoc.info/projects/blaix/ftp_service).
34
27
 
35
28
  ## Copyright
36
29
 
37
- Copyright (c) 2010 Justin Blake. See LICENSE for details.
30
+ Copyright (c) 2010 Justin Blake. See
31
+ [LICENSE](http://github.com/blaix/ftp_service/raw/master/LICENSE) for
32
+ details.
data/Rakefile CHANGED
@@ -10,9 +10,11 @@ begin
10
10
  gem.email = "justin@megablaix.com"
11
11
  gem.homepage = "http://github.com/blaix/ftp_service"
12
12
  gem.authors = ["Justin Blake"]
13
+ gem.add_dependency "ruby_gpg", ">= 0.2.0"
13
14
  gem.add_development_dependency "rspec", ">= 1.2.9"
14
15
  gem.add_development_dependency "mocha", ">= 0.9.8"
15
- gem.add_development_dependency "yard", ">= 0"
16
+ gem.add_development_dependency "yard", ">= 0.5.3"
17
+ gem.add_development_dependency "cucumber", ">= 0.6.3"
16
18
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
19
  end
18
20
  Jeweler::GemcutterTasks.new
@@ -26,6 +28,9 @@ Spec::Rake::SpecTask.new(:spec) do |spec|
26
28
  spec.spec_files = FileList['spec/**/*_spec.rb']
27
29
  end
28
30
 
31
+ require 'cucumber/rake/task'
32
+ Cucumber::Rake::Task.new(:features)
33
+
29
34
  namespace :spec do
30
35
  Spec::Rake::SpecTask.new(:doc) do |spec|
31
36
  spec.libs << 'lib' << 'spec'
@@ -47,7 +52,7 @@ task :default => :spec
47
52
  begin
48
53
  require 'yard'
49
54
  YARD::Rake::YardocTask.new do |y|
50
- y.files << '-' << 'CHANGELOG.*'
55
+ y.files << '-' << 'CHANGELOG.*' << 'TODO.*'
51
56
  end
52
57
  rescue LoadError
53
58
  task :yardoc do
@@ -0,0 +1,4 @@
1
+ # For v1.0.0
2
+
3
+ * Log everything
4
+ * Cleanup remote files on close
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
@@ -0,0 +1 @@
1
+ default: features
@@ -0,0 +1,19 @@
1
+ # To run, you must have an FTP server running and accessible by the
2
+ # credentials defined in features/support/ftp_helper.rb
3
+
4
+ Feature: Making a request
5
+ In order to take advantage of a web service over FTP
6
+ As a poor unfortunate soul
7
+ I want to make a request
8
+
9
+ Background:
10
+ Given I connect to an FTP service
11
+
12
+ Scenario: send a request
13
+ When I send the request "request" to the path "request_path"
14
+ Then the request "request" should exist at "request_path"
15
+
16
+ Scenario: read a response
17
+ When the server responds with "response" at the path "response_path"
18
+ Then I can read the response at the path "response_path"
19
+ And the response should be "response"
@@ -0,0 +1,25 @@
1
+ # To run, you must have an FTP server running and accessible by the
2
+ # credentials defined in features/support/ftp_helper.rb
3
+
4
+ # The encryption uses the gpg keys in the test_keys dir.
5
+
6
+ Feature: GPG Encryption
7
+ In order to keep my request secure over insecure FTP
8
+ As a user
9
+ I want to use gpg to encrypt and decrypt my request and response files
10
+
11
+ Background:
12
+ Given I connect to an FTP service
13
+
14
+ Scenario: send a request
15
+ When I send the request "secret content" to the path "request_path.gpg" with gpg recipient "Slow Joe Crow"
16
+ Then a binary request should exist at "request_path.gpg"
17
+ And the binary request at "request_path.gpg" should not contain "secret content"
18
+ When I download the binary request at "request_path.gpg" to "downloaded_request.gpg"
19
+ And I decrypt the file "downloaded_request.gpg" with passphrase "test"
20
+ Then the file "downloaded_request" should contain "secret content"
21
+
22
+ Scenario: read a response
23
+ When the server responds with "secret response" encrypted for "Slow Joe Crow" at the path "response_path.gpg"
24
+ Then I can read the response at the path "response_path.gpg" with the passphrase "test"
25
+ And the response should be "secret response"
@@ -0,0 +1,68 @@
1
+ Given /^I connect to an FTP service$/ do
2
+ @service = FtpService.new(FtpHelper::SERVER, FtpHelper::USER, FtpHelper::PASS)
3
+ end
4
+
5
+ When /^I send the request "([^\"]*)" to the path "([^\"]*)"$/ do |request, remote_path|
6
+ @service.write_request(request, remote_path)
7
+ end
8
+
9
+ When /^I send the request "([^\"]*)" to the path "([^\"]*)" with gpg recipient "([^\"]*)"$/ do |request, remote_path, gpg_recipient|
10
+ @service.write_request(request, remote_path, :gpg_recipient => gpg_recipient)
11
+ end
12
+
13
+ When /^the server responds with "([^\"]*)" at the path "([^\"]*)"$/ do |response, remote_path|
14
+ response = StringIO.new(response)
15
+ ftp.storlines("STOR #{remote_path}", response)
16
+ end
17
+
18
+ When /^the server responds with "([^\"]*)" encrypted for "([^\"]*)" at the path "([^\"]*)"$/ do |response, gpg_recipient, remote_path|
19
+ # Cheating a bit here to mimic a ftp service response by sending a request...
20
+ @service.write_request(response, remote_path, :gpg_recipient => gpg_recipient)
21
+ end
22
+
23
+ When /^I download the binary request at "([^\"]*)" to "([^\"]*)"$/ do |remote_path, local_path|
24
+ File.delete(local_path) if File.exist?(local_path)
25
+ ftp.getbinaryfile(remote_path, "#{TMP_PATH}/#{local_path}")
26
+ end
27
+
28
+ When /^I decrypt the file "([^\"]*)" with passphrase "([^\"]*)"$/ do |filename, passphrase|
29
+ RubyGpg.decrypt("#{TMP_PATH}/#{filename}", passphrase)
30
+ end
31
+
32
+ Then /^the request "([^\"]*)" should exist at "([^\"]*)"$/ do |request, remote_path|
33
+ actual_request = ""
34
+ ftp.retrlines("RETR #{remote_path}") { |line| actual_request << line }
35
+ actual_request.should == request
36
+ end
37
+
38
+ Then /^a binary request should exist at "([^\"]*)"$/ do |remote_path|
39
+ lambda {
40
+ ftp.retrbinary("RETR #{remote_path}", 128) {}
41
+ }.should_not raise_error
42
+ end
43
+
44
+ Then /^the binary request at "([^\"]*)" should not contain "([^\"]*)"$/ do |remote_path, request|
45
+ actual = ""
46
+ ftp.retrbinary("RETR #{remote_path}", 128) { |chunk| actual << chunk }
47
+ actual.strip.should_not == request.strip
48
+ end
49
+
50
+ Then /^I can read the response at the path "([^\"]*)"$/ do |remote_path|
51
+ @actual_response = @service.read_response(remote_path)
52
+ end
53
+
54
+ Then /^I can read the response at the path "([^\"]*)" with the passphrase "([^\"]*)"$/ do |remote_path, gpg_passphrase|
55
+ @actual_response = @service.read_response(remote_path, :gpg_passphrase => gpg_passphrase)
56
+ end
57
+
58
+ Then /^the response should be "([^\"]*)"$/ do |response|
59
+ @actual_response.strip.should == response
60
+ end
61
+
62
+ Then /^the file "([^\"]*)" should contain "([^\"]*)"$/ do |filename, contents|
63
+ File.read("#{TMP_PATH}/#{filename}").strip.should == contents.strip
64
+ end
65
+
66
+ After do
67
+ @service.close if @service
68
+ end
@@ -0,0 +1,6 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'ftp_service'
3
+
4
+ RubyGpg.config.homedir = File.dirname(__FILE__) + '/../../test_keys'
5
+
6
+ TMP_PATH = File.dirname(__FILE__) + '/../../tmp'
@@ -0,0 +1,13 @@
1
+ require 'net/ftp'
2
+
3
+ module FtpHelper
4
+ SERVER = 'localhost'
5
+ USER = 'cucumber'
6
+ PASS = 'cucumber_pass123'
7
+
8
+ def ftp
9
+ @connection ||= Net::FTP.new(SERVER, USER, PASS)
10
+ end
11
+ end
12
+
13
+ World(FtpHelper)
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ftp_service}
8
- s.version = "0.2.0"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Justin Blake"]
12
- s.date = %q{2010-03-08}
12
+ s.date = %q{2010-03-18}
13
13
  s.description = %q{An FTP Service is like a web service except stupid. You send your request by uploading an xml file and get your response by downloading another xml file.}
14
14
  s.email = %q{justin@megablaix.com}
15
15
  s.extra_rdoc_files = [
@@ -22,14 +22,25 @@ Gem::Specification.new do |s|
22
22
  "LICENSE",
23
23
  "README.markdown",
24
24
  "Rakefile",
25
+ "TODO.markdown",
25
26
  "VERSION",
27
+ "cucumber.yml",
28
+ "features/basic_request.feature",
29
+ "features/encrypted_request.feature",
30
+ "features/step_definitions/ftp_request_steps.rb",
31
+ "features/support/env.rb",
32
+ "features/support/ftp_helper.rb",
26
33
  "ftp_service.gemspec",
27
34
  "lib/ftp_service.rb",
35
+ "lib/ftp_service/encryption.rb",
28
36
  "lib/tempfile_helper.rb",
29
37
  "spec/ftp_service_spec.rb",
30
38
  "spec/spec.opts",
31
39
  "spec/spec_helper.rb",
32
- "spec/tempfile_helper_spec.rb"
40
+ "spec/tempfile_helper_spec.rb",
41
+ "test_keys/pubring.gpg",
42
+ "test_keys/secring.gpg",
43
+ "test_keys/trustdb.gpg"
33
44
  ]
34
45
  s.homepage = %q{http://github.com/blaix/ftp_service}
35
46
  s.rdoc_options = ["--charset=UTF-8"]
@@ -47,18 +58,24 @@ Gem::Specification.new do |s|
47
58
  s.specification_version = 3
48
59
 
49
60
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
61
+ s.add_runtime_dependency(%q<ruby_gpg>, [">= 0.2.0"])
50
62
  s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
51
63
  s.add_development_dependency(%q<mocha>, [">= 0.9.8"])
52
- s.add_development_dependency(%q<yard>, [">= 0"])
64
+ s.add_development_dependency(%q<yard>, [">= 0.5.3"])
65
+ s.add_development_dependency(%q<cucumber>, [">= 0.6.3"])
53
66
  else
67
+ s.add_dependency(%q<ruby_gpg>, [">= 0.2.0"])
54
68
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
55
69
  s.add_dependency(%q<mocha>, [">= 0.9.8"])
56
- s.add_dependency(%q<yard>, [">= 0"])
70
+ s.add_dependency(%q<yard>, [">= 0.5.3"])
71
+ s.add_dependency(%q<cucumber>, [">= 0.6.3"])
57
72
  end
58
73
  else
74
+ s.add_dependency(%q<ruby_gpg>, [">= 0.2.0"])
59
75
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
60
76
  s.add_dependency(%q<mocha>, [">= 0.9.8"])
61
- s.add_dependency(%q<yard>, [">= 0"])
77
+ s.add_dependency(%q<yard>, [">= 0.5.3"])
78
+ s.add_dependency(%q<cucumber>, [">= 0.6.3"])
62
79
  end
63
80
  end
64
81
 
@@ -1,5 +1,6 @@
1
1
  require 'net/ftp'
2
2
  require 'tempfile_helper'
3
+ require 'ftp_service/encryption'
3
4
 
4
5
  # Class for dealing with a service that acts like a web service, except
5
6
  # over FTP. Meaning an xml request is uploaded as a file, and the
@@ -21,6 +22,7 @@ require 'tempfile_helper'
21
22
  # response = service.read_response("#{path}/response.xml")
22
23
  # service.close
23
24
  class FtpService
25
+ include Encryption
24
26
 
25
27
  # Open a connection to the FTP server and return an FtpService object.
26
28
  # The object must be closed explicitely. See FtpServier#open for a
@@ -42,18 +44,49 @@ class FtpService
42
44
  end
43
45
  end
44
46
 
45
- # Write `request` to a local temp file and upload it to `remote_path`
47
+ # Write +request+ to a local temp file and upload it to +remote_path+
46
48
  # on the FTP server.
47
- def write_request(request, remote_path)
48
- tmp = TempfileHelper.write(request, 'request')
49
- @ftp.puttextfile(tmp.path, remote_path)
49
+ #
50
+ # ftp_service.write_request('<foo>bar</foo>', '/remote/path.xml')
51
+ #
52
+ # You can encrypt the request using GPG:
53
+ #
54
+ # ftp_service.write_request('<secret>stuff</secret>', '/remote/path.xml.gpg', :gpg_recipient => 'recipient@email.com')
55
+ #
56
+ # You must have +gpg+ installed and have a public key available for
57
+ # the intended recipient. This uses the +ruby_gpg+ gem. To configure
58
+ # the gpg settings, see {http://rdoc.info/projects/blaix/ruby_gpg}.
59
+ def write_request(request, remote_path, options = {})
60
+ request = TempfileHelper.write(request, 'request')
61
+ remote_temp_path = remote_path + ".tmp"
62
+ if options[:gpg_recipient]
63
+ encrypt(request, options[:gpg_recipient])
64
+ @ftp.putbinaryfile(request.path, remote_temp_path)
65
+ else
66
+ @ftp.puttextfile(request.path, remote_temp_path)
67
+ end
68
+ @ftp.rename(remote_temp_path, remote_path)
50
69
  end
51
70
 
52
- # Download the file at `remote_path` from the FTP server to a local
53
- # temp file and return its contents.
54
- def read_response(remote_path)
55
- TempfileHelper.read('response') do |tmp|
56
- @ftp.gettextfile(remote_path, tmp.path)
71
+ # Download the file at +remote_path+ from the FTP server to a local
72
+ # temp file and return its contents. If +remote_path+ doesn't exist,
73
+ # keep trying for 2 minutes before raising a Timeout::Error.
74
+ #
75
+ # response = ftp_service.read_response('/remote/path.xml')
76
+ #
77
+ # If you expect the response to be encrypted for you with gpg:
78
+ #
79
+ # response = ftp_service.read_response('/remote/path.xml.gpg', :gpg_passphrase => "my_passphrase")
80
+ #
81
+ # You must have +gpg+ installed and have the necessarry private key.
82
+ # This uses the +ruby_gpg+ gem. To configure the gpg settings, see
83
+ # {http://rdoc.info/projects/blaix/ruby_gpg}.
84
+ def read_response(remote_path, options = {})
85
+ response = download_and_read_response(remote_path, options)
86
+ if options[:gpg_passphrase]
87
+ RubyGpg.decrypt_string(response, options[:gpg_passphrase])
88
+ else
89
+ response
57
90
  end
58
91
  end
59
92
 
@@ -61,4 +94,38 @@ class FtpService
61
94
  def close
62
95
  @ftp.close
63
96
  end
97
+
98
+ private
99
+
100
+ def download_and_read_response(remote_path, options = {})
101
+ TempfileHelper.read('response') do |tmp|
102
+ Timeout::timeout(120) do
103
+ loop_until_downloaded(remote_path, tmp.path, options)
104
+ end
105
+ end
106
+ end
107
+
108
+ def loop_until_downloaded(remote_path, local_path, options = {})
109
+ loop do
110
+ begin
111
+ download(remote_path, local_path, options)
112
+ break
113
+ rescue Net::FTPPermError => e
114
+ raise unless e.message.include?("No such file")
115
+ rest_between_requests
116
+ end
117
+ end
118
+ end
119
+
120
+ def download(remote_path, local_path, options = {})
121
+ if options[:gpg_passphrase]
122
+ @ftp.getbinaryfile(remote_path, local_path)
123
+ else
124
+ @ftp.gettextfile(remote_path, local_path)
125
+ end
126
+ end
127
+
128
+ def rest_between_requests
129
+ sleep(2)
130
+ end
64
131
  end
@@ -0,0 +1,17 @@
1
+ begin
2
+ require 'ruby_gpg'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'ruby_gpg'
6
+ end
7
+
8
+ class FtpService
9
+ module Encryption
10
+ private
11
+ # Expects a tempfile object and a string for the recipient.
12
+ def encrypt(file, recipient)
13
+ RubyGpg.encrypt(file.path, recipient)
14
+ file.path << ".gpg"
15
+ end
16
+ end
17
+ end
@@ -54,9 +54,28 @@ describe "FtpService" do
54
54
  @service.write_request('request', '/remote/path')
55
55
  end
56
56
 
57
- it "uploads the request to `path` on the FTP server" do
57
+ it "encrypts the request if passed a gpg recipient" do
58
58
  TempfileHelper.stubs(:write).returns(@tempfile)
59
- @ftp.expects(:puttextfile).with('/local/path', '/remote/path')
59
+ RubyGpg.expects(:encrypt).with('/local/path', 'recipient')
60
+ @service.write_request('request', '/remote/path.gpg', :gpg_recipient => 'recipient')
61
+ end
62
+
63
+ it "uploads the request to a temp path on the FTP server" do
64
+ TempfileHelper.stubs(:write).returns(@tempfile)
65
+ @ftp.expects(:puttextfile).with('/local/path', '/remote/path.tmp')
66
+ @service.write_request('request', '/remote/path')
67
+ end
68
+
69
+ it "uploads the request as binary if passed a gpg recipient" do
70
+ TempfileHelper.stubs(:write).returns(@tempfile)
71
+ RubyGpg.stubs(:encrypt)
72
+ @ftp.expects(:putbinaryfile).with('/local/path.gpg', '/remote/path.gpg.tmp')
73
+ @service.write_request('request', '/remote/path.gpg', :gpg_recipient => 'recipient')
74
+ end
75
+
76
+ it "renames the temp path on the FTP server to the passed `path`" do
77
+ TempfileHelper.stubs(:write).returns(@tempfile)
78
+ @ftp.expects(:rename).with('/remote/path.tmp', '/remote/path')
60
79
  @service.write_request('request', '/remote/path')
61
80
  end
62
81
  end
@@ -65,7 +84,10 @@ describe "FtpService" do
65
84
  before do
66
85
  tempfile = stub('tempfile', :path => '/local/path')
67
86
  TempfileHelper.stubs(:read).returns('response').yields(tempfile)
87
+
68
88
  @service = FtpService.new('host', 'user', 'pass')
89
+ # No need to be nice to the "server" during testing...
90
+ @service.stubs(:rest_between_requests)
69
91
  end
70
92
 
71
93
  it "downloads the response at `path` from the FTP server" do
@@ -73,9 +95,45 @@ describe "FtpService" do
73
95
  @service.read_response('/remote/path')
74
96
  end
75
97
 
98
+ it "downloads the response as binary if passed a gpg passphrase" do
99
+ RubyGpg.stubs(:decrypt_string)
100
+ @ftp.expects(:getbinaryfile).with('/remote/path.gpg', '/local/path')
101
+ @service.read_response('/remote/path.gpg', :gpg_passphrase => "my_passphrase")
102
+ end
103
+
104
+ it "decrypts the response if passed a gpg passphrase" do
105
+ RubyGpg.expects(:decrypt_string).with('response', 'my_passphrase')
106
+ @service.read_response('/remote/path.gpg', :gpg_passphrase => "my_passphrase")
107
+ end
108
+
76
109
  it "returns the contents of the downloaded response" do
77
110
  @service.read_response('/remote/path').should == "response"
78
111
  end
112
+
113
+ it "polls until response shows up" do
114
+ error = Net::FTPPermError.new("No such file")
115
+ # Raise error on the first two calls...
116
+ @ftp.expects(:gettextfile).times(3).raises(error).then.raises(error).then.returns(nil)
117
+ lambda {
118
+ @service.read_response('/remote/path')
119
+ }.should_not raise_error
120
+ end
121
+
122
+ it "times out if response takes longer than 2 minutes to show up" do
123
+ # TODO: Less brittle way to test this?
124
+ # Currently depends on inner workings of Timeout.
125
+ Timeout.expects(:sleep).with(120)
126
+ lambda {
127
+ @service.read_response('/remote/path')
128
+ }.should raise_error(Timeout::Error)
129
+ end
130
+
131
+ it "doesn't gobble up every FTP exception" do
132
+ @ftp.stubs(:gettextfile).raises(Net::FTPPermError.new("Permission denied")).then.returns(nil)
133
+ lambda {
134
+ @service.read_response('/remote/path')
135
+ }.should raise_error(Net::FTPPermError, "Permission denied")
136
+ end
79
137
  end
80
138
 
81
139
  describe '#close' do
Binary file
Binary file
Binary file
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 2
7
+ - 3
8
8
  - 0
9
- version: 0.2.0
9
+ version: 0.3.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Justin Blake
@@ -14,13 +14,27 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-08 00:00:00 -05:00
17
+ date: 2010-03-18 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
- name: rspec
21
+ name: ruby_gpg
22
22
  prerelease: false
23
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ - 2
30
+ - 0
31
+ version: 0.2.0
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rspec
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
24
38
  requirements:
25
39
  - - ">="
26
40
  - !ruby/object:Gem::Version
@@ -30,11 +44,11 @@ dependencies:
30
44
  - 9
31
45
  version: 1.2.9
32
46
  type: :development
33
- version_requirements: *id001
47
+ version_requirements: *id002
34
48
  - !ruby/object:Gem::Dependency
35
49
  name: mocha
36
50
  prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
51
+ requirement: &id003 !ruby/object:Gem::Requirement
38
52
  requirements:
39
53
  - - ">="
40
54
  - !ruby/object:Gem::Version
@@ -44,19 +58,35 @@ dependencies:
44
58
  - 8
45
59
  version: 0.9.8
46
60
  type: :development
47
- version_requirements: *id002
61
+ version_requirements: *id003
48
62
  - !ruby/object:Gem::Dependency
49
63
  name: yard
50
64
  prerelease: false
51
- requirement: &id003 !ruby/object:Gem::Requirement
65
+ requirement: &id004 !ruby/object:Gem::Requirement
52
66
  requirements:
53
67
  - - ">="
54
68
  - !ruby/object:Gem::Version
55
69
  segments:
56
70
  - 0
57
- version: "0"
71
+ - 5
72
+ - 3
73
+ version: 0.5.3
58
74
  type: :development
59
- version_requirements: *id003
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ name: cucumber
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ segments:
84
+ - 0
85
+ - 6
86
+ - 3
87
+ version: 0.6.3
88
+ type: :development
89
+ version_requirements: *id005
60
90
  description: An FTP Service is like a web service except stupid. You send your request by uploading an xml file and get your response by downloading another xml file.
61
91
  email: justin@megablaix.com
62
92
  executables: []
@@ -72,14 +102,25 @@ files:
72
102
  - LICENSE
73
103
  - README.markdown
74
104
  - Rakefile
105
+ - TODO.markdown
75
106
  - VERSION
107
+ - cucumber.yml
108
+ - features/basic_request.feature
109
+ - features/encrypted_request.feature
110
+ - features/step_definitions/ftp_request_steps.rb
111
+ - features/support/env.rb
112
+ - features/support/ftp_helper.rb
76
113
  - ftp_service.gemspec
77
114
  - lib/ftp_service.rb
115
+ - lib/ftp_service/encryption.rb
78
116
  - lib/tempfile_helper.rb
79
117
  - spec/ftp_service_spec.rb
80
118
  - spec/spec.opts
81
119
  - spec/spec_helper.rb
82
120
  - spec/tempfile_helper_spec.rb
121
+ - test_keys/pubring.gpg
122
+ - test_keys/secring.gpg
123
+ - test_keys/trustdb.gpg
83
124
  has_rdoc: true
84
125
  homepage: http://github.com/blaix/ftp_service
85
126
  licenses: []