open-uri-and-write 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/README.md +116 -0
- data/Rakefile +10 -0
- data/autotest.rb +21 -0
- data/lib/open-uri-and-write/version.rb +4 -0
- data/lib/open-uri-and-write.rb +240 -0
- data/open-uri-and-write.gemspec +25 -0
- data/spec/integration/dav4rack_testserver.rb +104 -0
- data/spec/integration/open-uri-and-write-spec.rb +174 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +62 -0
- metadata +116 -0
data/.gitignore
ADDED
data/README.md
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
OpenUriAndWrite
|
2
|
+
===============
|
3
|
+
|
4
|
+
OpenUriAndWrite is an easy to use wrapper for Net::Dav, making it as easy to write to WebDAV enabled webservers as local files.
|
5
|
+
|
6
|
+
# Examples
|
7
|
+
|
8
|
+
It is possible to open an http, https URL and write to it as though it were a file:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
open("http://www.ruby-lang.org/open_uri_and_write.html","w") {|f|
|
12
|
+
f.puts "<h1>OpenUriAndWrite</h1>"
|
13
|
+
}
|
14
|
+
```
|
15
|
+
|
16
|
+
A more compact way would be:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
open("http://www.ruby-lang.org/open_uri_and_write.html","w").puts "<h1>OpenUriAndWrite</h1>"
|
20
|
+
```
|
21
|
+
|
22
|
+
Files can be deleted as local files:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
File.delete("http://www.ruby-lang.org/open_uri_and_write.html")
|
26
|
+
```
|
27
|
+
|
28
|
+
Directories are created the same way as local files.
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
Dir.mkdir("http://www.ruby-lang.org/open_uri_and_write")
|
32
|
+
```
|
33
|
+
|
34
|
+
# Proppatch and Propfind
|
35
|
+
|
36
|
+
The only difference between local files and directories and remote files and directories on webdav servers, is that they both can have an infinite amount of properties. Properties are set as a xml snippet with proppatch() and accessed with propfind().
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
File.open("http://www.ruby-lang.org/open_uri_and_write.html","w").proppatch('<o:Author>Douglas Groncki</o:Author>')
|
40
|
+
props = Dir.propfind("http://www.ruby-lang.org") # Returns XML
|
41
|
+
```
|
42
|
+
|
43
|
+
# Interoperability with OpenURI
|
44
|
+
|
45
|
+
To not interfer with the 'open-uri' standard library, the 'open-uri-and-write' gem is only active in file modes 'w','a','w+' and 'a+':
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
open("http://www.ruby-lang.org/open_uri_and_write.html","w").puts("<h1>HTML</h1>") # open-uri-and-write
|
49
|
+
```
|
50
|
+
|
51
|
+
If not any filemode is supplied, 'open-uri' is used:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
puts open("http://www.ruby-lang.org").read() # open-uri
|
55
|
+
```
|
56
|
+
|
57
|
+
# Authentication
|
58
|
+
|
59
|
+
By default 'open-uri-and-write' will prompt for username and password.
|
60
|
+
|
61
|
+
```
|
62
|
+
$ ruby webdav_test.rb
|
63
|
+
Username for www.example.com: scott
|
64
|
+
Password for 'scott@www.example.com: *****
|
65
|
+
```
|
66
|
+
|
67
|
+
Credentials can be supplied with the DAVUSER and DAVPASS environment variables.
|
68
|
+
|
69
|
+
```
|
70
|
+
$ export DAVUSER=scott
|
71
|
+
$ export DAVPASS=tiger
|
72
|
+
$ ruby webdav_test.rb
|
73
|
+
```
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
ENV['DAVUSER'] = 'scott'
|
77
|
+
ENV['DAVPASS'] = 'tiger'
|
78
|
+
```
|
79
|
+
|
80
|
+
|
81
|
+
Another option is to supply username and password as arguments to open():
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
file = open('https://www.example.com/', 'w', :username => 'scott', :password => 'tiger')
|
85
|
+
```
|
86
|
+
|
87
|
+
On OS X passwords typed in by user will be stored encrypted in the Keychain and reused later.
|
88
|
+
|
89
|
+
```
|
90
|
+
$ export DAVUSER=scott
|
91
|
+
$ ruby webdav_test.rb
|
92
|
+
Password for 'scott@www.example.com': *****
|
93
|
+
Password for 'scott@www.example.com' stored on OS X KeyChain.
|
94
|
+
```
|
95
|
+
|
96
|
+
The next time this script is executed, it will not prompt for password.
|
97
|
+
|
98
|
+
# Install
|
99
|
+
|
100
|
+
This is work in progress, and not pushed as a gem yet.
|
101
|
+
|
102
|
+
# Testing
|
103
|
+
|
104
|
+
To run all tests:
|
105
|
+
|
106
|
+
```
|
107
|
+
$ rake spec
|
108
|
+
```
|
109
|
+
|
110
|
+
The tests will start a webserver at startup, and close it down before finishing.
|
111
|
+
|
112
|
+
# Credits
|
113
|
+
|
114
|
+
* Tanaka Akira for the inspiration taken from 'open-uri' standard library.
|
115
|
+
* Miron Cuperman for the 'net/dav' gem used to access webdav servers.
|
116
|
+
|
data/Rakefile
ADDED
data/autotest.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'filewatcher'
|
3
|
+
require 'paint'
|
4
|
+
|
5
|
+
def run_tests
|
6
|
+
puts Paint['Testing', :yellow]
|
7
|
+
output = %x[ruby test/test-open-uri-and-write.rb]
|
8
|
+
if(output[/Failure:/])
|
9
|
+
puts output
|
10
|
+
puts Paint['Failure', :red, :bright]
|
11
|
+
else
|
12
|
+
puts output
|
13
|
+
puts Paint['Ok', :green, :bright]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
run_tests
|
18
|
+
files = ["lib/open-uri-and-write.rb", "test/test-open-uri-and-write.rb"]
|
19
|
+
FileWatcher.new(files).watch(0.5) do |filename|
|
20
|
+
run_tests
|
21
|
+
end
|
@@ -0,0 +1,240 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'uri'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'net/dav'
|
5
|
+
require 'highline/import'
|
6
|
+
|
7
|
+
|
8
|
+
# A wrapper for Net::Dav that acts as a replacement for the File class
|
9
|
+
class WebDavAgent < StringIO
|
10
|
+
|
11
|
+
alias_method :original_puts, :puts
|
12
|
+
attr_accessor :dav
|
13
|
+
|
14
|
+
def initialize(url, rest)
|
15
|
+
super("")
|
16
|
+
@url = url
|
17
|
+
@uri = URI.parse(url)
|
18
|
+
if(rest.size > 0)
|
19
|
+
if(rest.first.to_s[/^[wa]/])
|
20
|
+
@dav = Net::DAV.new(@url)
|
21
|
+
options = rest[1]
|
22
|
+
if(options && options[:username] && options[:password])
|
23
|
+
@dav.credentials(options[:username], options[:password])
|
24
|
+
else
|
25
|
+
set_credentials
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
if(rest.first.to_s[/^a/])
|
30
|
+
write(@dav.get(@url)) # write to stringIO
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def set_credentials
|
37
|
+
if(ENV['DAVUSER'])
|
38
|
+
username = ENV['DAVUSER']
|
39
|
+
# elsif(ENV['USER'])
|
40
|
+
# username = ENV['USER']
|
41
|
+
else
|
42
|
+
username = ask("Username for #{@uri.host}: ")
|
43
|
+
end
|
44
|
+
|
45
|
+
if(ENV['DAVPASS'])
|
46
|
+
password = ENV['DAVPASS']
|
47
|
+
else
|
48
|
+
osx = (RUBY_PLATFORM =~ /darwin/)
|
49
|
+
osx_keychain = false
|
50
|
+
if(osx)
|
51
|
+
begin
|
52
|
+
require 'osx_keychain'
|
53
|
+
osx_keychain = true
|
54
|
+
rescue LoadError
|
55
|
+
end
|
56
|
+
end
|
57
|
+
if(osx_keychain)then
|
58
|
+
keychain = OSXKeychain.new
|
59
|
+
password = keychain[@uri.host, username ]
|
60
|
+
if(!password)
|
61
|
+
password = ask("Password for '#{username}@#{@uri.host}: ") {|q| q.echo = "*"}
|
62
|
+
keychain[@uri.host, username] = password
|
63
|
+
puts "Password for '#{username}@#{@uri.host}' stored on OS X KeyChain."
|
64
|
+
end
|
65
|
+
|
66
|
+
else
|
67
|
+
password = ask("Password for '#{username}@#{@uri.host}: ") {|q| q.echo = "*"}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
@dav.credentials(username, password)
|
71
|
+
end
|
72
|
+
|
73
|
+
def puts(string)
|
74
|
+
super(string)
|
75
|
+
@dav.put_string(@url, string)
|
76
|
+
end
|
77
|
+
|
78
|
+
def read
|
79
|
+
@dav.get(@url)
|
80
|
+
end
|
81
|
+
|
82
|
+
def proppatch(xml_snippet)
|
83
|
+
@dav.proppatch(@uri, xml_snippet)
|
84
|
+
end
|
85
|
+
|
86
|
+
def propfind
|
87
|
+
@dav.propfind(@url)
|
88
|
+
end
|
89
|
+
|
90
|
+
def close
|
91
|
+
@dav.put_string(@url, string)
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
# Kernel extensions
|
97
|
+
# Careful monkeypatching
|
98
|
+
module Kernel
|
99
|
+
private
|
100
|
+
alias open_uri_and_write_original open # :nodoc:
|
101
|
+
|
102
|
+
def open(name, *rest, &block) # :doc:
|
103
|
+
if name.respond_to?(:open)
|
104
|
+
name.open(*rest, &block)
|
105
|
+
elsif name.respond_to?(:to_s) and
|
106
|
+
name[/^(https?):\/\//] and
|
107
|
+
rest.size > 0 and
|
108
|
+
rest.first.to_s[/^[rwa]/] and
|
109
|
+
not (rest.first.to_s == 'r' or rest.first.to_s == 'rb')
|
110
|
+
webdav_agent = WebDavAgent.new(name, rest)
|
111
|
+
if(block)
|
112
|
+
yield webdav_agent
|
113
|
+
else
|
114
|
+
return webdav_agent
|
115
|
+
end
|
116
|
+
else
|
117
|
+
open_uri_and_write_original(name, *rest, &block)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
module_function :open
|
122
|
+
end
|
123
|
+
|
124
|
+
# Store credentials for later use in sesssion.
|
125
|
+
class WebDavCredentialsPool
|
126
|
+
|
127
|
+
def self.get_connection_for_url(url)
|
128
|
+
hostname = URI.parse(url).host.to_s
|
129
|
+
if(!$_webdav_credentials_pool)
|
130
|
+
$_webdav_credentials_pool = { }
|
131
|
+
end
|
132
|
+
if($_webdav_credentials_pool[hostname])
|
133
|
+
return $_webdav_credentials_pool[hostname]
|
134
|
+
else(!$_webdav_credentials_pool[hostname])
|
135
|
+
agent = WebDavAgent.new(url, ['w'])
|
136
|
+
$_webdav_credentials_pool[hostname] = agent.dav
|
137
|
+
return agent.dav
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
# More monkeypatching
|
145
|
+
class Dir
|
146
|
+
|
147
|
+
class << self
|
148
|
+
alias original_mkdir mkdir
|
149
|
+
alias original_rmddir rmdir
|
150
|
+
end
|
151
|
+
|
152
|
+
def self.mkdir(name)
|
153
|
+
if name.respond_to?(:to_s) and name[/^(https?):\/\//]
|
154
|
+
dav = WebDavCredentialsPool.get_connection_for_url(name)
|
155
|
+
dav.mkdir(name)
|
156
|
+
else
|
157
|
+
self.original_mkdir(name)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def self.rmdir(name)
|
162
|
+
if name.respond_to?(:to_s) and name[/^(https?):\/\//]
|
163
|
+
dav = WebDavCredentialsPool.get_connection_for_url(name)
|
164
|
+
dav.delete(name)
|
165
|
+
else
|
166
|
+
self.original_rmdir(name)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def self.propfind(name)
|
171
|
+
if name.respond_to?(:to_s) and name[/^(https?):\/\//]
|
172
|
+
dav = WebDavCredentialsPool.get_connection_for_url(name)
|
173
|
+
dav.propfind(name)
|
174
|
+
else
|
175
|
+
# TODO Throw illegal action exception
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def self.proppatch(name,xml_snippet)
|
180
|
+
if name.respond_to?(:to_s) and name[/^(https?):\/\//]
|
181
|
+
dav = WebDavCredentialsPool.get_connection_for_url(name)
|
182
|
+
dav.propfind(name, xml_snippet)
|
183
|
+
else
|
184
|
+
# TODO Throw illegal action exception
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
# Even more monkeypatching
|
191
|
+
class File
|
192
|
+
|
193
|
+
class << self
|
194
|
+
alias original_delete delete
|
195
|
+
alias original_open open
|
196
|
+
alias original_exists? exists?
|
197
|
+
end
|
198
|
+
|
199
|
+
def self.exists?(name)
|
200
|
+
if(name[/https?:\/\//])
|
201
|
+
dav = WebDavCredentialsPool.get_connection_for_url(name)
|
202
|
+
dav.exists?(name)
|
203
|
+
else
|
204
|
+
self.original_exists?(name)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def self.delete(names)
|
209
|
+
filenames = []
|
210
|
+
if(names.class == String)
|
211
|
+
filenames << names
|
212
|
+
elsif(names.class = Array)
|
213
|
+
filenames = names
|
214
|
+
end
|
215
|
+
filenames.each do |filename|
|
216
|
+
if(filename[/^(https?):\/\//])
|
217
|
+
dav = WebDavCredentialsPool.get_connection_for_url(filename)
|
218
|
+
dav.delete(filename)
|
219
|
+
else
|
220
|
+
self.original_delete(filename)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def self.open(name, *rest, &block)
|
226
|
+
if name.respond_to?(:open)
|
227
|
+
name.open(*rest, &block)
|
228
|
+
elsif name.respond_to?(:to_s) and name[/^(https?):\/\//] and rest.size > 0 and rest.first.to_s[/^w/]
|
229
|
+
webdav_agent = WebDavAgent.new(name, rest)
|
230
|
+
if(block)
|
231
|
+
yield webdav_agent
|
232
|
+
else
|
233
|
+
return webdav_agent
|
234
|
+
end
|
235
|
+
else
|
236
|
+
self.original_open(name, *rest, &block)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "open-uri-and-write/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "open-uri-and-write"
|
7
|
+
s.version = OpenUriAndWrite::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Thomas Flemming"]
|
10
|
+
s.email = ["thomas.flemming@gmail.com"]
|
11
|
+
s.homepage = "https://github.com/thomasfl/open-uri-and-write"
|
12
|
+
s.summary = %q{An easy to use wrapper for Net::Dav, for writing files to WebDAV enabled web servers.}
|
13
|
+
s.description = %q{Use normal file operations to write files to WebDAV enabled web servers.}
|
14
|
+
|
15
|
+
s.add_runtime_dependency "highline", "~>1.6.9"
|
16
|
+
s.add_runtime_dependency "net_dav", "~>0.5.0"
|
17
|
+
s.add_development_dependency "rspec", "~>2.5.0"
|
18
|
+
s.add_development_dependency "pry", "~>0.9.8.4"
|
19
|
+
s.add_development_dependency "dav4rack", "~>0.2.10"
|
20
|
+
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
23
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
24
|
+
s.require_paths = ["lib"]
|
25
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'dav4rack'
|
3
|
+
require 'dav4rack/file_resource'
|
4
|
+
# require 'unicorn'
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
|
8
|
+
$publish_dates = { } # Global hashmap to hold publish-dates for all resources
|
9
|
+
|
10
|
+
class DAV4Rack::Controller
|
11
|
+
|
12
|
+
alias_method :original_proppatch, :proppatch
|
13
|
+
|
14
|
+
# Monkeypatch the proppatch method, so we can proppatch custom properties
|
15
|
+
def proppatch
|
16
|
+
input = request.body.read
|
17
|
+
|
18
|
+
req = Nokogiri::XML(input)
|
19
|
+
# puts "PROPPATCH"
|
20
|
+
# puts input
|
21
|
+
|
22
|
+
publish_date = req.xpath("//publish-date","D" => "DAV").text
|
23
|
+
if(publish_date != "")
|
24
|
+
# puts request.path + " = " + publish_date
|
25
|
+
$publish_dates[request.path] = publish_date
|
26
|
+
end
|
27
|
+
|
28
|
+
request.body.rewind
|
29
|
+
original_proppatch
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
# Custom DAV4Rack resourceclass to handle PROPPATCH
|
35
|
+
class MyResource < DAV4Rack::FileResource
|
36
|
+
|
37
|
+
def property_names
|
38
|
+
super << 'publish-date'
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_property(name)
|
42
|
+
if(name == "publish-date")
|
43
|
+
if($publish_dates[path])
|
44
|
+
return $publish_dates[path]
|
45
|
+
else
|
46
|
+
return nil
|
47
|
+
end
|
48
|
+
else
|
49
|
+
super(name)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# TODO: Can't figure out why this method is never called.
|
54
|
+
def set_property(name, value)
|
55
|
+
puts "Debug 2: setting property #{name}:#{value}"
|
56
|
+
super(name)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
# Starts a WebDAV server using dav4rack and unicorn
|
63
|
+
def start_dav4rack(port, root)
|
64
|
+
options = {:resource_class => MyResource, :root => root }
|
65
|
+
|
66
|
+
app = Rack::Builder.new do
|
67
|
+
use Rack::ShowExceptions
|
68
|
+
# use Rack::CommonLogger # Display all requests
|
69
|
+
use Rack::Reloader
|
70
|
+
use Rack::Lint
|
71
|
+
run DAV4Rack::Handler.new(options)
|
72
|
+
end.to_app
|
73
|
+
|
74
|
+
runners = []
|
75
|
+
|
76
|
+
runners << lambda do |x|
|
77
|
+
puts 'Starting WEBrick'
|
78
|
+
Rack::Handler::WEBrick.run(x, :Port => port)
|
79
|
+
end
|
80
|
+
|
81
|
+
begin
|
82
|
+
runner = runners.shift
|
83
|
+
runner.call(app)
|
84
|
+
rescue LoadError
|
85
|
+
puts 'FAILED'
|
86
|
+
retry unless runners.empty?
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
if __FILE__ == $0
|
92
|
+
|
93
|
+
port = "3003"
|
94
|
+
options = {}
|
95
|
+
# options[:username] = "davuser"
|
96
|
+
# options[:password] = "davpass"
|
97
|
+
path = '/tmp/webdav_server_root'
|
98
|
+
puts "Starting server in " + path
|
99
|
+
options[:root] = path
|
100
|
+
|
101
|
+
start_dav4rack(port, options)
|
102
|
+
end
|
103
|
+
|
104
|
+
# start_dav4rack(3003)
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/dav4rack_testserver')
|
3
|
+
|
4
|
+
# To run:
|
5
|
+
# $ rake spec
|
6
|
+
|
7
|
+
describe "OpenUriAndWrite" do
|
8
|
+
|
9
|
+
before(:all) do
|
10
|
+
start_webdav_server(:port => 3003)
|
11
|
+
@base_uri = "http://localhost:3003/"
|
12
|
+
end
|
13
|
+
|
14
|
+
after(:all) do
|
15
|
+
# Shut down webdav server:
|
16
|
+
stop_webdav_server
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should write to local file normally" do
|
20
|
+
timestamp = Time.now.to_s
|
21
|
+
filename = '/tmp/local_test_file.txt'
|
22
|
+
file = open(filename,'w')
|
23
|
+
file.puts timestamp
|
24
|
+
file.close
|
25
|
+
|
26
|
+
open(filename).read.strip.should == timestamp
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should write files to webdav server and standard lib open-uri" do
|
30
|
+
timestamp = Time.now.to_s
|
31
|
+
webdav_url = @base_uri + 'webdav_test_1.txt'
|
32
|
+
file = open(webdav_url,'w')
|
33
|
+
file.puts timestamp
|
34
|
+
file.close
|
35
|
+
|
36
|
+
file = open(webdav_url).read.strip.should == timestamp
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should write to files with block syntax" do
|
40
|
+
timestamp = Time.now.to_s
|
41
|
+
webdav_url = @base_uri + 'webdav_test_2.txt'
|
42
|
+
open(webdav_url,'w') do |file|
|
43
|
+
file.puts timestamp
|
44
|
+
end
|
45
|
+
|
46
|
+
file = open(webdav_url).read.strip.should == timestamp
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should open write to file with the file class and flush with close" do
|
50
|
+
timestamp = Time.now.to_s
|
51
|
+
webdav_url = @base_uri + 'webdav_test_3.txt'
|
52
|
+
file = File.open(webdav_url,'w')
|
53
|
+
file.puts(timestamp)
|
54
|
+
file.puts('XYZ')
|
55
|
+
file.close
|
56
|
+
|
57
|
+
open(webdav_url,'w').read.strip.should == timestamp + "\nXYZ"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should read properties of files" do
|
61
|
+
filename = 'webdav_test_4.txt'
|
62
|
+
webdav_url = @base_uri + filename
|
63
|
+
open(webdav_url,'w').puts(Time.now.to_s)
|
64
|
+
|
65
|
+
properties = open(webdav_url,'w').propfind
|
66
|
+
displayname = properties.xpath("//d:displayname", "d" => "DAV:").text
|
67
|
+
displayname.should == filename
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should set properties on files" do
|
71
|
+
filename = 'webdav_test_5.txt'
|
72
|
+
webdav_url = @base_uri + filename
|
73
|
+
open(webdav_url,'w').puts(Time.now.to_s)
|
74
|
+
|
75
|
+
publish_date = Time.now.httpdate.to_s
|
76
|
+
open(webdav_url,'w').proppatch("<D:publish-date>#{publish_date}</D:publish-date>")
|
77
|
+
properties = open(webdav_url,'w').propfind
|
78
|
+
property = properties.to_s[/publish-date>([^<]*)/,1]
|
79
|
+
property.should == publish_date
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should append to files" do
|
83
|
+
file = open(@base_uri + "append_file_test.txt", "w")
|
84
|
+
file.puts "Line 1"
|
85
|
+
file.puts "Line 2"
|
86
|
+
file.close
|
87
|
+
|
88
|
+
file = open(@base_uri + "append_file_test.txt", "a")
|
89
|
+
file.puts "Line 3"
|
90
|
+
file.puts "Line 4"
|
91
|
+
file.close
|
92
|
+
|
93
|
+
file = open(@base_uri + "append_file_test.txt")
|
94
|
+
lines = file.readlines
|
95
|
+
file.close
|
96
|
+
lines[3].should eql("Line 4\n")
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should create and delete directory" do
|
100
|
+
# timestamp = Time.now.to_s
|
101
|
+
webdav_url = @base_uri + 'new_test_folder'
|
102
|
+
Dir.mkdir(webdav_url)
|
103
|
+
File.exists?(webdav_url).should == true
|
104
|
+
|
105
|
+
Dir.rmdir(webdav_url)
|
106
|
+
# There seems to be a bug in our testserver that prevent it from deleting files
|
107
|
+
# File.exists?(webdav_url).should == false
|
108
|
+
end
|
109
|
+
|
110
|
+
# TODO Test this in a separate script just to be sure
|
111
|
+
it "should not matter which order the rubygems 'open-uri' and 'open-uri-and-write' is loaded" do
|
112
|
+
# http://ruby-doc.org/core-1.9.3/Object.html
|
113
|
+
# http://stackoverflow.com/questions/335530/how-do-you-detect-that-monkey-patching-has-occurred-in-ruby
|
114
|
+
# http://blog.sidu.in/2007/12/rubys-methodadded.html
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should handle username and password supplied as parameter to open" do
|
118
|
+
webdav_url = @base_uri + 'yet_another_testfile.txt'
|
119
|
+
file = open(webdav_url, 'w', :username => 'username', :password => 'secret')
|
120
|
+
file.puts "Content"
|
121
|
+
file.close
|
122
|
+
|
123
|
+
begin
|
124
|
+
file = open(webdav_url, 'w+', :username => 'username', :password => 'secret')
|
125
|
+
file.read
|
126
|
+
should fail
|
127
|
+
rescue Exception => e
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# TODO Test all modes:
|
132
|
+
|
133
|
+
# r
|
134
|
+
# Read-only mode. The file pointer is placed at the beginning of
|
135
|
+
# the file. This is the default mode.
|
136
|
+
#
|
137
|
+
# r+
|
138
|
+
# Read-write mode. The file pointer will be at the beginning of the file.
|
139
|
+
#
|
140
|
+
# w
|
141
|
+
# Write-only mode.
|
142
|
+
# - Overwrites the file if the file exists.
|
143
|
+
# - If the file does not exist, creates a new file for writing.
|
144
|
+
#
|
145
|
+
# w+
|
146
|
+
# Read-write mode.
|
147
|
+
# - Overwrites the existing file if the file exists.
|
148
|
+
# - If the file does not exist, creates a new file for reading and writing.
|
149
|
+
#
|
150
|
+
# a
|
151
|
+
# Write-only mode.
|
152
|
+
# - The file pointer is at the end of the file if the file exists.
|
153
|
+
# - That is, the file is in the append mode.
|
154
|
+
# - If the file does not exist, it creates a new file for writing.
|
155
|
+
#
|
156
|
+
# a+
|
157
|
+
# Read and write mode.
|
158
|
+
# - The file pointer is at the end of the file if the file exists.
|
159
|
+
# - The file opens in the append mode.
|
160
|
+
# - If the file does not exist, it creates a new file for reading and writing.
|
161
|
+
#
|
162
|
+
# r+, w+, and a+ all do read-write. w+ truncates the file. a+ appends.
|
163
|
+
# w+ and a+ both create the file if it does not exist.)
|
164
|
+
|
165
|
+
# # TODO test authentication
|
166
|
+
|
167
|
+
after(:each) do
|
168
|
+
url = @base_uri + 'webdav_test.txt'
|
169
|
+
if(File.exists?(url))
|
170
|
+
File.delete(url)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'rubygems'
|
4
|
+
require 'open-uri-and-write'
|
5
|
+
require 'rspec'
|
6
|
+
require 'net/http'
|
7
|
+
require 'uri'
|
8
|
+
require 'pathname'
|
9
|
+
require 'nokogiri'
|
10
|
+
require 'pry'
|
11
|
+
|
12
|
+
|
13
|
+
ENV['DAVUSER'] = 'dummy'
|
14
|
+
ENV['DAVPASS'] = 'dummy'
|
15
|
+
|
16
|
+
RSpec.configure do |config|
|
17
|
+
end
|
18
|
+
|
19
|
+
def stop_webdav_server
|
20
|
+
Process.kill('SIGKILL', $pid) rescue nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def start_webdav_server(*args)
|
24
|
+
port = args.first[:port].to_s
|
25
|
+
@base_uri = "http://localhost:#{port}/"
|
26
|
+
|
27
|
+
server_root = '/tmp/open_uri_and_write_test'
|
28
|
+
%x[rm -r #{server_root}]
|
29
|
+
%x[mkdir #{server_root}]
|
30
|
+
|
31
|
+
if(not(server_up?(@base_uri)))
|
32
|
+
options = {}
|
33
|
+
|
34
|
+
# Start webdav server in subprocess
|
35
|
+
$pid = fork do
|
36
|
+
start_dav4rack(port, server_root)
|
37
|
+
end
|
38
|
+
|
39
|
+
wait_for_server(@base_uri)
|
40
|
+
else
|
41
|
+
puts "Server is running."
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
def server_up?(address)
|
47
|
+
begin
|
48
|
+
return Net::HTTP.get_response(URI(address)).code == "200"
|
49
|
+
rescue Exception => e
|
50
|
+
puts e.to_s
|
51
|
+
return false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def wait_for_server(address)
|
56
|
+
puts "Waiting for WebDAV server to start#{address}"
|
57
|
+
sleep(0.5)
|
58
|
+
while(not(server_up?(address)))
|
59
|
+
puts "retrying"
|
60
|
+
sleep(0.5)
|
61
|
+
end
|
62
|
+
end
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: open-uri-and-write
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Thomas Flemming
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: highline
|
16
|
+
requirement: &70101881835880 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.6.9
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70101881835880
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: net_dav
|
27
|
+
requirement: &70101881835200 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.5.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70101881835200
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec
|
38
|
+
requirement: &70101881834480 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.5.0
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70101881834480
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: pry
|
49
|
+
requirement: &70101881833800 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.9.8.4
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70101881833800
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: dav4rack
|
60
|
+
requirement: &70101881833060 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 0.2.10
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70101881833060
|
69
|
+
description: Use normal file operations to write files to WebDAV enabled web servers.
|
70
|
+
email:
|
71
|
+
- thomas.flemming@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- README.md
|
78
|
+
- Rakefile
|
79
|
+
- autotest.rb
|
80
|
+
- lib/open-uri-and-write.rb
|
81
|
+
- lib/open-uri-and-write/version.rb
|
82
|
+
- open-uri-and-write.gemspec
|
83
|
+
- spec/integration/dav4rack_testserver.rb
|
84
|
+
- spec/integration/open-uri-and-write-spec.rb
|
85
|
+
- spec/spec.opts
|
86
|
+
- spec/spec_helper.rb
|
87
|
+
homepage: https://github.com/thomasfl/open-uri-and-write
|
88
|
+
licenses: []
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ! '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 1.8.11
|
108
|
+
signing_key:
|
109
|
+
specification_version: 3
|
110
|
+
summary: An easy to use wrapper for Net::Dav, for writing files to WebDAV enabled
|
111
|
+
web servers.
|
112
|
+
test_files:
|
113
|
+
- spec/integration/dav4rack_testserver.rb
|
114
|
+
- spec/integration/open-uri-and-write-spec.rb
|
115
|
+
- spec/spec.opts
|
116
|
+
- spec/spec_helper.rb
|