open-uri-and-write 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2012 Thomas Flemming
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md CHANGED
@@ -3,9 +3,10 @@ OpenUriAndWrite
3
3
 
4
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
5
 
6
- # Examples
6
+ Examples
7
+ --------
7
8
 
8
- It is possible to open an http, https URL and write to it as though it were a file:
9
+ It is possible to open an http/https URL and write to it as though it were a local file:
9
10
 
10
11
  ```ruby
11
12
  open("http://www.ruby-lang.org/open_uri_and_write.html","w") {|f|
@@ -13,7 +14,7 @@ It is possible to open an http, https URL and write to it as though it were a fi
13
14
  }
14
15
  ```
15
16
 
16
- A more compact way would be:
17
+ With method chaining it gets more compact:
17
18
 
18
19
  ```ruby
19
20
  open("http://www.ruby-lang.org/open_uri_and_write.html","w").puts "<h1>OpenUriAndWrite</h1>"
@@ -25,46 +26,31 @@ Files can be deleted as local files:
25
26
  File.delete("http://www.ruby-lang.org/open_uri_and_write.html")
26
27
  ```
27
28
 
28
- Directories are created the same way as local files.
29
+ Directories are created the same way as local files:
29
30
 
30
31
  ```ruby
31
32
  Dir.mkdir("http://www.ruby-lang.org/open_uri_and_write")
32
33
  ```
33
34
 
34
- # Proppatch and Propfind
35
+ Authentication
36
+ --------------
37
+ By default the scripts prompts the user for username and password. The username and hostname are stored in the file ~/.open-uri-and-write-usernames, so the next time only the password has to be typed in. On OSX the password is stored encrypted in the keychain.
35
38
 
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().
39
+ Credentials can also supplied as environment variables or options.
37
40
 
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.
41
+ Default behaviour if no username or password is set:
60
42
 
61
43
  ```
62
44
  $ ruby webdav_test.rb
63
45
  Username for www.example.com: scott
64
46
  Password for 'scott@www.example.com: *****
47
+ Username and hostname stored in /Users/thomasf/.open-uri-and-write-usernames
48
+
49
+ $ ruby webdav_test.rb
50
+ Password for 'scott@www.example.com: *****
65
51
  ```
66
52
 
67
- Credentials can be supplied with the DAVUSER and DAVPASS environment variables.
53
+ Supplying credentials with the DAVUSER and DAVPASS environment variables:
68
54
 
69
55
  ```
70
56
  $ export DAVUSER=scott
@@ -72,19 +58,20 @@ Credentials can be supplied with the DAVUSER and DAVPASS environment variables.
72
58
  $ ruby webdav_test.rb
73
59
  ```
74
60
 
61
+ Setting username and password in ruby:
62
+
75
63
  ```ruby
76
64
  ENV['DAVUSER'] = 'scott'
77
65
  ENV['DAVPASS'] = 'tiger'
78
66
  ```
79
67
 
80
-
81
- Another option is to supply username and password as arguments to open():
68
+ Another option is to supply username and password as arguments to open:
82
69
 
83
70
  ```ruby
84
71
  file = open('https://www.example.com/', 'w', :username => 'scott', :password => 'tiger')
85
72
  ```
86
73
 
87
- On OS X passwords typed in by user will be stored encrypted in the Keychain and reused later.
74
+ On OS X passwords typed in by the user will be stored encrypted in the Keychain and reused later.
88
75
 
89
76
  ```
90
77
  $ export DAVUSER=scott
@@ -93,24 +80,93 @@ On OS X passwords typed in by user will be stored encrypted in the Keychain and
93
80
  Password for 'scott@www.example.com' stored on OS X KeyChain.
94
81
  ```
95
82
 
96
- The next time this script is executed, it will not prompt for password.
83
+ The next time this script is executed, it will not prompt for username and password.
84
+
85
+ Proppatch and Propfind
86
+ ----------------------
97
87
 
98
- # Install
88
+ In difference to files and directories on local filesystems, files and directories on WebDAV servers can have many custom properties. Properties can be read with til propfindare set as a xml snippet with proppatch() and accessed with propfind().
99
89
 
100
- This is work in progress, and not pushed as a gem yet.
90
+ ```ruby
91
+ file = File.open('http://www.ruby-lang.org/open_uri_and_write.html','w')
92
+ file.proppatch('<D:Author>Thomas Flemming</D:Author>')
93
+ properties_as_xml = Dir.propfind("http://www.ruby-lang.org")
94
+ ```
95
+
96
+ Interoperability with OpenURI
97
+ -----------------------------
101
98
 
102
- # Testing
99
+ If no filemode is specified when using open on url, standard 'open-uri' will be used.
100
+
101
+ ```ruby
102
+ puts open("http://www.ruby-lang.org").read() # Use 'open-uri'
103
+ open('http://www.ruby-lang.org/my_page.html','w').puts("<h1>HTML</h1>") # Use 'open-uri-and-write'
104
+ ```
103
105
 
106
+ To not interfer with the 'open-uri' standard library, the 'open-uri-and-write' gem is only active in file modes 'w','a','w+','a+' and 'r+'.
107
+
108
+ Supported file access modes
109
+ ===========================
110
+
111
+ Unspported file access modes
112
+ ============================
113
+
114
+ * r Read-only mode. The file pointer is placed at the beginning of the file. This is the default mode.
115
+
116
+ * r+ Read-write mode. The file pointer will be at the beginning of the file.
117
+
118
+ * w Write-only mode. Overwrites the file if the file exists. If the file does not exist, creates a new file for writing.
119
+
120
+ * w+ Read-write mode. Overwrites the existing file if the file exists. If the file does not exist, creates a new file for reading and writing.
121
+
122
+ * a Write-only mode. The file pointer is at the end of the file if the file exists. That is, the file is in the append mode. If the file does not exist, it creates a new file for writing.
123
+
124
+ * a+ Read and write mode. The file pointer is at the end of the file if the file exists. The file opens in the append mode. If the file does not exist, it creates a new file for reading and writing.
125
+
126
+
127
+
128
+ Install
129
+ -------
130
+
131
+ ```
132
+ $ gem install open-uri-and-write
133
+ ```
134
+
135
+ For OSX users this will store password on the keychain.
136
+
137
+ ```
138
+ $ gem install keychain_services
139
+ ```
140
+
141
+ Note that if you have stored a misspelled password on the OSX Keychain, then you will have to delete it manually with Keychain Access application.
142
+
143
+ Testing
144
+ -------
104
145
  To run all tests:
105
146
 
106
147
  ```
107
148
  $ rake spec
108
149
  ```
109
150
 
110
- The tests will start a webserver at startup, and close it down before finishing.
151
+ The tests will start a webserver with webdav at startup, and close it down before finishing.
152
+
153
+ Future work
154
+ -----------
155
+ This is work in progress. You can write files and crate directories, but there's still work to do on reading directories and at the time one filemodes "r", "w" and "a" is supported.
156
+
157
+ More protocols like FTP, SCP and Amazon S3 would be useful.
158
+
159
+ Credits
160
+ -------
161
+
162
+ * Tanaka Akira for the inspirational ['open-uri'](https://github.com/ruby/ruby/blob/trunk/lib/open-uri.rb) standard ruby library.
163
+ * Miron Cuperman for the ['net/dav'](https://github.com/devrandom/net_dav) gem used to access webdav servers.
164
+ * Chris Roberts and the rest of the DAV4Rack for the WebDAV implementation in ruby used for testing this gem.
111
165
 
112
- # Credits
166
+ Author
167
+ ------
113
168
 
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.
169
+ Thomas Flemming
116
170
 
171
+ * [@thomasfl](https://twitter.com/#!/thomasfl)
172
+ * [http://github.com/thomasfl/](http://github.com/thomasfl/)
@@ -4,237 +4,9 @@ require 'open-uri'
4
4
  require 'net/dav'
5
5
  require 'highline/import'
6
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
7
+ require 'open-uri-and-write/handle'
8
+ require 'open-uri-and-write/usernames'
9
+ require 'open-uri-and-write/credentials_store'
10
+ require 'open-uri-and-write/file_extensions'
11
+ require 'open-uri-and-write/dir_extensions'
12
+ require 'open-uri-and-write/kernel_extensions'
@@ -0,0 +1,23 @@
1
+ # Store credentials for later use in sesssion.
2
+
3
+ module OpenUriAndWrite
4
+
5
+ class CredentialsStore
6
+
7
+ def self.get_connection_for_url(url)
8
+ hostname = URI.parse(url).host.to_s
9
+ if(!$_webdav_credentials_pool)
10
+ $_webdav_credentials_pool = { }
11
+ end
12
+ if($_webdav_credentials_pool[hostname])
13
+ return $_webdav_credentials_pool[hostname]
14
+ else(!$_webdav_credentials_pool[hostname])
15
+ agent = OpenUriAndWrite::Handle.new(url, ['w'])
16
+ $_webdav_credentials_pool[hostname] = agent.dav
17
+ return agent.dav
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,46 @@
1
+ # Extensions and modifications (monkeypatching) to the Dir class:
2
+
3
+ class Dir
4
+
5
+ class << self
6
+ alias original_mkdir mkdir
7
+ alias original_rmddir rmdir
8
+ end
9
+
10
+ def self.mkdir(name, *args)
11
+ if name.respond_to?(:to_s) and name[/^(https?):\/\//]
12
+ dav = OpenUriAndWrite::CredentialsStore.get_connection_for_url(name)
13
+ dav.mkdir(name)
14
+ else
15
+ self.original_mkdir(name, *args)
16
+ end
17
+ end
18
+
19
+ def self.rmdir(name)
20
+ if name.respond_to?(:to_s) and name[/^(https?):\/\//]
21
+ dav = OpenUriAndWrite::CredentialsStore.get_connection_for_url(name)
22
+ dav.delete(name)
23
+ else
24
+ self.original_rmdir(name)
25
+ end
26
+ end
27
+
28
+ def self.propfind(name)
29
+ if name.respond_to?(:to_s) and name[/^(https?):\/\//]
30
+ dav = OpenUriAndWrite::CredentialsStore.get_connection_for_url(name)
31
+ dav.propfind(name)
32
+ else
33
+ raise IOError.new(true), "Illegal action: Can't do propfind #{name}"
34
+ end
35
+ end
36
+
37
+ def self.proppatch(name,xml_snippet)
38
+ if name.respond_to?(:to_s) and name[/^(https?):\/\//]
39
+ dav = OpenUriAndWrite::CredentialsStore.get_connection_for_url(name)
40
+ dav.propfind(name, xml_snippet)
41
+ else
42
+ raise IOError.new(true), "Illegal action: Can't do proppatch on #{name}"
43
+ end
44
+ end
45
+
46
+ end
@@ -0,0 +1,52 @@
1
+ # Extensions and modifications (monkeypatching) to the File class:
2
+
3
+ class File
4
+
5
+ class << self
6
+ alias original_delete delete
7
+ alias original_open open
8
+ alias original_exists? exists?
9
+ end
10
+
11
+ def self.exists?(name)
12
+ if(name[/https?:\/\//])
13
+ dav = OpenUriAndWrite::CredentialsStore.get_connection_for_url(name)
14
+ dav.exists?(name)
15
+ else
16
+ self.original_exists?(name)
17
+ end
18
+ end
19
+
20
+ def self.delete(names)
21
+ filenames = []
22
+ if(names.class == String)
23
+ filenames << names
24
+ elsif(names.class = Array)
25
+ filenames = names
26
+ end
27
+ filenames.each do |filename|
28
+ if(filename[/^(https?):\/\//])
29
+ dav = OpenUriAndWrite::CredentialsStore.get_connection_for_url(filename)
30
+ dav.delete(filename)
31
+ else
32
+ self.original_delete(filename)
33
+ end
34
+ end
35
+ end
36
+
37
+ def self.open(name, *rest, &block)
38
+ if name.respond_to?(:open)
39
+ name.open(*rest, &block)
40
+ elsif name.respond_to?(:to_s) and name[/^(https?):\/\//] and rest.size > 0 and rest.first.to_s[/^w/]
41
+ webdav_agent = OpenUriAndWrite::Handle.new(name, rest)
42
+ if(block)
43
+ yield webdav_agent
44
+ else
45
+ return webdav_agent
46
+ end
47
+ else
48
+ self.original_open(name, *rest, &block)
49
+ end
50
+ end
51
+
52
+ end
@@ -0,0 +1,106 @@
1
+ # OpenUriAndWrite file handler. Does authentication upon initialize
2
+
3
+ module OpenUriAndWrite
4
+
5
+ class Handle < StringIO
6
+
7
+ alias_method :original_puts, :puts
8
+ attr_accessor :dav, :filemode
9
+
10
+ def initialize(url, rest)
11
+ super("")
12
+ @url = url
13
+ @uri = URI.parse(url)
14
+ if(rest.size > 0)
15
+ @filemode = rest.first.to_s
16
+ if(@filemode[/^[rwa]/])
17
+ @dav = Net::DAV.new(@url)
18
+ options = rest[1]
19
+ if(options && options[:username] && options[:password])
20
+ @dav.credentials(options[:username], options[:password])
21
+ else
22
+ set_credentials
23
+ end
24
+ end
25
+
26
+ if(@filemode[/^a/])
27
+ write(@dav.get(@url)) # Write to StringIO
28
+ end
29
+
30
+ end
31
+ end
32
+
33
+ def set_credentials
34
+ if(ENV['DAVUSER'])
35
+ username = ENV['DAVUSER']
36
+ else
37
+ usernames = OpenUriAndWrite::Usernames.new()
38
+ username = usernames.username_for_host(@uri.host)
39
+ if(not(username))
40
+ username = ask("Username for #{@uri.host}: ")
41
+ usernames.save_username_and_host(username,@uri.host)
42
+ STDOUT.puts "Username and hostname stored in #{usernames.usernamesfile}"
43
+ end
44
+ end
45
+
46
+ password = nil
47
+ if(ENV['DAVPASS'])
48
+ password = ENV['DAVPASS']
49
+ else
50
+ osx = (RUBY_PLATFORM =~ /darwin/)
51
+ osx_keychain = false
52
+ if(osx)
53
+ begin
54
+ require 'keychain'
55
+ osx_keychain = true
56
+ rescue LoadError
57
+ end
58
+ end
59
+ if(osx_keychain)then
60
+ item = Keychain.items.find { |item| item.label =~ /#{@uri.host}/ }
61
+ if(item)
62
+ password = item.password
63
+ end
64
+
65
+ if(!password)
66
+ password = ask("Password for '#{username}@#{@uri.host}: ") {|q| q.echo = "*"}
67
+ Keychain.add_internet_password(@uri.host, '', username, '', password)
68
+ STDOUT.puts "Password for '#{username}@#{@uri.host}' stored on OSX KeyChain."
69
+ end
70
+
71
+ else
72
+ password = ask("Password for '#{username}@#{@uri.host}: ") {|q| q.echo = "*"}
73
+ end
74
+ end
75
+ @dav.credentials(username, password)
76
+ end
77
+
78
+ def puts(string)
79
+ if(@filemode[/^r/])
80
+ raise IOError.new(true), "not opened for writing"
81
+ end
82
+
83
+ super(string)
84
+ @dav.put_string(@url, string)
85
+ end
86
+
87
+ def read
88
+ @dav.get(@url)
89
+ end
90
+
91
+ def proppatch(xml_snippet)
92
+ @dav.proppatch(@uri, xml_snippet)
93
+ end
94
+
95
+ def propfind
96
+ @dav.propfind(@url)
97
+ end
98
+
99
+ def close
100
+ @dav.put_string(@url, string)
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+
@@ -0,0 +1,28 @@
1
+ # Kernel extensions
2
+ # Careful monkeypatching
3
+ module Kernel
4
+ private
5
+ alias open_uri_and_write_original open # :nodoc:
6
+
7
+ def open(name, *rest, &block) # :doc:
8
+ if name.respond_to?(:open)
9
+ name.open(*rest, &block)
10
+ elsif name.respond_to?(:to_s) and
11
+ name[/^(https?):\/\//] and
12
+ rest.size > 0 and
13
+ rest.first.to_s[/^[rwa]/]
14
+ webdav_agent = OpenUriAndWrite::Handle.new(name, rest)
15
+ if(block)
16
+ yield webdav_agent
17
+ else
18
+ return webdav_agent
19
+ end
20
+ else
21
+ open_uri_and_write_original(name, *rest, &block)
22
+ end
23
+ end
24
+
25
+ module_function :open
26
+ end
27
+
28
+
@@ -0,0 +1,51 @@
1
+ # For storing usernames and hostnames in ~/.open-uri-and-write-usernames
2
+
3
+ module OpenUriAndWrite
4
+
5
+ class Usernames
6
+
7
+ def homedir
8
+ if(Dir.respond_to?("home"))
9
+ Dir.home
10
+ else
11
+ File.expand_path("~")
12
+ end
13
+ end
14
+
15
+ def usernamesfile
16
+ homedir + "/.open-uri-and-write-usernames"
17
+ end
18
+
19
+ def read_usernames_and_hosts
20
+ usernames = {}
21
+ if(File.exist?(usernamesfile))
22
+ open(usernamesfile).readlines.each do |line|
23
+ username, host = line.split(':')
24
+ usernames[host.strip] = username.strip
25
+ end
26
+ end
27
+ return usernames
28
+ end
29
+
30
+ def save_username_and_host(username,host)
31
+ usernames = read_usernames_and_hosts
32
+ usernames[host] = username
33
+ store_username_and_host(usernames)
34
+ end
35
+
36
+ def store_username_and_host(usernames)
37
+ file = open(usernamesfile, "w")
38
+ usernames.keys.each do |key|
39
+ file.puts "#{usernames[key]}:#{key}"
40
+ end
41
+ file.close
42
+ end
43
+
44
+ def username_for_host(host)
45
+ usernames = read_usernames_and_hosts
46
+ return usernames[host]
47
+ end
48
+
49
+ end
50
+ end
51
+
@@ -1,4 +1,4 @@
1
1
  module OpenUriAndWrite
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
4
4
 
@@ -128,11 +128,34 @@ describe "OpenUriAndWrite" do
128
128
  end
129
129
  end
130
130
 
131
+ it "should not use 'open-uri' to read file in 'r' filemode" do
132
+ timestamp = Time.now.to_s
133
+ webdav_url = @base_uri + 'webdav_r_filemode_test.txt'
134
+ file = open(webdav_url,'w')
135
+ file.puts timestamp
136
+ file.class.should == OpenUriAndWrite::Handle
137
+ file.close
138
+
139
+ file = open(webdav_url)
140
+ file.class.should == StringIO # StringIO means 'open-uri' gem is beeing used
141
+ file.read.strip.should == timestamp
142
+
143
+ file = open(webdav_url,'r')
144
+ file.class.should == OpenUriAndWrite::Handle
145
+ file.read.strip.should == timestamp
146
+ begin
147
+ file.puts("this should not be written")
148
+ fail
149
+ rescue IOError => ioError
150
+ end
151
+ file.close
152
+ end
153
+
131
154
  # TODO Test all modes:
132
155
 
133
- # r
134
- # Read-only mode. The file pointer is placed at the beginning of
135
- # the file. This is the default mode.
156
+ # OK r
157
+ # Read-only mode. The file pointer is placed at the beginning of
158
+ # the file. This is the default mode.
136
159
  #
137
160
  # r+
138
161
  # Read-write mode. The file pointer will be at the beginning of the file.
@@ -162,6 +185,8 @@ describe "OpenUriAndWrite" do
162
185
  # r+, w+, and a+ all do read-write. w+ truncates the file. a+ appends.
163
186
  # w+ and a+ both create the file if it does not exist.)
164
187
 
188
+ # TODO: Store username and hostname in .open-uri-and-write-hosts
189
+
165
190
  # # TODO test authentication
166
191
 
167
192
  after(:each) do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: open-uri-and-write
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-23 00:00:00.000000000 Z
12
+ date: 2012-06-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: highline
16
- requirement: &70101881835880 !ruby/object:Gem::Requirement
16
+ requirement: &70128528057900 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.6.9
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70101881835880
24
+ version_requirements: *70128528057900
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: net_dav
27
- requirement: &70101881835200 !ruby/object:Gem::Requirement
27
+ requirement: &70128537727960 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.5.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70101881835200
35
+ version_requirements: *70128537727960
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &70101881834480 !ruby/object:Gem::Requirement
38
+ requirement: &70128537727120 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 2.5.0
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70101881834480
46
+ version_requirements: *70128537727120
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: pry
49
- requirement: &70101881833800 !ruby/object:Gem::Requirement
49
+ requirement: &70128537726640 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 0.9.8.4
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70101881833800
57
+ version_requirements: *70128537726640
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: dav4rack
60
- requirement: &70101881833060 !ruby/object:Gem::Requirement
60
+ requirement: &70128537726080 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: 0.2.10
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70101881833060
68
+ version_requirements: *70128537726080
69
69
  description: Use normal file operations to write files to WebDAV enabled web servers.
70
70
  email:
71
71
  - thomas.flemming@gmail.com
@@ -74,10 +74,17 @@ extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
76
  - .gitignore
77
+ - LICENSE
77
78
  - README.md
78
79
  - Rakefile
79
80
  - autotest.rb
80
81
  - lib/open-uri-and-write.rb
82
+ - lib/open-uri-and-write/credentials_store.rb
83
+ - lib/open-uri-and-write/dir_extensions.rb
84
+ - lib/open-uri-and-write/file_extensions.rb
85
+ - lib/open-uri-and-write/handle.rb
86
+ - lib/open-uri-and-write/kernel_extensions.rb
87
+ - lib/open-uri-and-write/usernames.rb
81
88
  - lib/open-uri-and-write/version.rb
82
89
  - open-uri-and-write.gemspec
83
90
  - spec/integration/dav4rack_testserver.rb