filestore 0.0.19 → 0.0.20

Sign up to get free protection for your applications and to get access to all the features.
@@ -19,7 +19,9 @@ LIBS = [
19
19
  'uuidtools',
20
20
  'fileutils',
21
21
  'yaml',
22
- 'etc'
22
+ 'etc',
23
+ 'socket',
24
+ 'base64'
23
25
  ]
24
26
  FILESTORE_FILES = [
25
27
  #
@@ -31,7 +33,9 @@ FILESTORE_FILES = [
31
33
  'memory_meta',
32
34
  'simple_store',
33
35
  'multitenant_store',
34
- 'factory'
36
+ 'factory',
37
+ 'webdav/webdav',
38
+ 'webdav_store'
35
39
  ]
36
40
  #
37
41
  # Loads required 3rd party libs as defined in FileStore::LIBS
@@ -208,4 +208,47 @@ module FileStore
208
208
  end
209
209
  end
210
210
  end
211
+
212
+ module WebDAV
213
+ #
214
+ # WebDAVStore factory class
215
+ #
216
+ class WebDAVStoreFactory
217
+ #
218
+ # Creates a WebDAV file-store instance
219
+ #
220
+ # Arguments:
221
+ # root_path: The base path directory
222
+ # host: The WebDAV host
223
+ # prefix: The path prefix for any URL
224
+ # port (optional): The WebDAV port
225
+ # user (optional): HTTP user
226
+ # password (optional): HTTP password
227
+ # observable (optional): Determines wether this instance should support observation
228
+ # logger (optional): The logging facility
229
+ #
230
+ # Returns:
231
+ # A new instance of WebDAVStore
232
+ #
233
+ def self.create(root_path, host, prefix, port = 80, user = '', password = '', observable = false, logger = StdoutLogger)
234
+ store = nil
235
+
236
+ begin
237
+ store = WebDAVStore.new host, port, user, password, root_path, logger
238
+ store.connection.path_prefix = prefix
239
+
240
+ if observable then
241
+ logger.debug "Extending instance with module 'ObservedSubject'"
242
+
243
+ store.extend ObservedSubject
244
+ store.initialize_obs
245
+ end
246
+ rescue FileStoreException => e
247
+ logger.debug "Couldn't create webdav store.\nReason: #{e.message}"
248
+ end
249
+
250
+ return store
251
+ end
252
+ end
253
+ end
211
254
  end
@@ -11,9 +11,12 @@ module FileStore
11
11
  #
12
12
  class ObserverAction
13
13
  TYPE_DEFAULT = "DEFAULT"
14
+ TYPE_DAV_ADD = "WEBDAV_ADD_FILE"
15
+ TYPE_DAV_REMOVE = "WEBDAV_REMOVE_FILE"
14
16
  TYPE_STORE_ADD = "STORE_ADD_FILE"
15
17
  TYPE_STORE_REMOVE = "STORE_REMOVE_FILE"
16
18
  TYPE_STORE_GET = "STORE_GET_FILE"
19
+ TYPE_DAV_GET = "WEBDAV_GET_FILE"
17
20
  TYPE_STORE_RESTORE = "STORE_RESTORE_FILE"
18
21
  TYPE_STORE_SHUTDOWN = "STORE_SHUTDOWN"
19
22
  TYPE_MSTORE_CREATE = "MSTORE_CREATE_TENANT"
@@ -23,6 +26,7 @@ module FileStore
23
26
  TYPE_META_REMOVE = "META_REMOVE_FILE"
24
27
  TYPE_META_RESTORE = "META_RESTORE_FILE"
25
28
  TYPE_META_SHUTDOWN = "META_SHUTDOWN"
29
+ TYPE_DAV_SHUTDOWN = "DAV_SHUTDOWN"
26
30
  #
27
31
  # Attribute accessors for instance variable defining the type of
28
32
  # action
@@ -78,7 +78,7 @@ module FileStore
78
78
  (@logger.info("Copying file"); FileUtils.copy_file(file, dstPath))
79
79
 
80
80
  inform ObserverAction.new(:type => ObserverAction::TYPE_STORE_ADD,
81
- :objects => [file, meta], :msg => "Added file to file store") if self.is_a?(ObservedSubject)
81
+ :objects => { :file => file, :meta => meta }, :msg => "Added file to file store") if self.is_a?(ObservedSubject)
82
82
  rescue Exception => e
83
83
  raise FileStoreException, "Couldn't add file #{file} to store.", e.backtrace
84
84
  end
@@ -0,0 +1,211 @@
1
+ #
2
+ # webdav.rb
3
+ #
4
+ # author: Thomas Stätter
5
+ # date: 2014/02/01
6
+ #
7
+ module FileStore::WebDAV
8
+ #
9
+ # Class WebDAVException is used to identify errors occuring
10
+ # in WebDAV connections
11
+ #
12
+ class WebDAVException < Exception
13
+ end
14
+ #
15
+ # Class implementing easy accessor to HTTP response headers
16
+ #
17
+ class ResponseHeaders
18
+ attr_reader :headers, :http_version, :status, :response_text
19
+ #
20
+ # Initialize new ResponseHeaders instance
21
+ #
22
+ # Arguments:
23
+ # text: The raw response text
24
+ #
25
+ def initialize(text)
26
+ @headers = {}
27
+ @http_version = ''
28
+ @status = -1
29
+ @response_text = ''
30
+
31
+ parse text
32
+ end
33
+ #
34
+ # Determines wether the reponse body is XML
35
+ #
36
+ # Returns:
37
+ # true if content type is appilcation/xml, false otherwise
38
+ #
39
+ def is_xml?
40
+ not (@headers['Content-Type'] =~ /^application\/xml.*/).nil?
41
+ end
42
+ #
43
+ # Determines wether the reponse body is HTML
44
+ #
45
+ # Returns:
46
+ # true if content type is appilcation/html, false otherwise
47
+ #
48
+ def is_html?
49
+ not (@headers['Content-Type'] =~ /^application\/html.*/).nil?
50
+ end
51
+
52
+ private
53
+ #
54
+ # Parse the reponse text
55
+ #
56
+ def parse(text)
57
+ text.split("\n").each do |line|
58
+ if line =~ /^.*\:.*$/
59
+ s = line.split(":")
60
+
61
+ key = s[0].strip
62
+ value = s[1].strip
63
+
64
+ @headers[key] = value
65
+ else
66
+ s = line.split
67
+
68
+ @http_version = s[0]
69
+ @status = s[1].to_i
70
+ @response_text = s[2]
71
+ end
72
+ end
73
+ end
74
+ end
75
+ #
76
+ # Class implementing a connector to a HTTP resource via WebDAV
77
+ #
78
+ class WebDAV
79
+ include FileStore::Logger
80
+
81
+ attr_reader :host, :port, :protocol, :chunk_size
82
+ attr_accessor :credentials, :path_prefix
83
+
84
+ @socket = nil
85
+
86
+ def initialize(host,port=80,protocol='HTTP/1.1',chunk=8096)
87
+ @host = host.to_s
88
+ @port = port.to_i
89
+ @protocol = protocol
90
+ @chunk_size = chunk.to_i
91
+ @credentials = {}
92
+ end
93
+
94
+ def encode_credentials
95
+ Base64.encode64("#{credentials[:user]}:#{credentials[:password]}").strip
96
+ end
97
+
98
+ def build_header(method, path, content_length = nil)
99
+ header = "#{method} #{File.join(@path_prefix, path)} #{@protocol} \r\n"
100
+ header += "Content-Length: #{content_length}\r\n" unless content_length.nil?
101
+ header += "Host: #{@host}\r\n"
102
+ header += "Authorization: Basic #{encode_credentials}\r\n" unless @credentials.empty?
103
+ header += "User-Agent: WebDAV-Client/0.1\r\n"
104
+ header += "Connection: close\r\n\r\n"
105
+
106
+ return header
107
+ end
108
+
109
+ def request(method, path)
110
+ data = {}
111
+ buf = ''
112
+ begin
113
+ open
114
+ header = build_header(method, path)
115
+
116
+ if @socket.write(header) == header.length then
117
+ while line = @socket.gets # Read lines from socket
118
+ buf += line
119
+ end
120
+
121
+ data = {
122
+ header: ResponseHeaders.new(buf.split("\r\n\r\n")[0]),
123
+ body: buf.split("\r\n\r\n")[1]
124
+ }
125
+ else
126
+ raise WebDAVException.new "Couldn't send request headers"
127
+ end
128
+ rescue Exception => e
129
+ raise WebDAVException.new "Caught exception while sending request. #{e.message}"
130
+ ensure
131
+ close
132
+ end
133
+
134
+ return data
135
+ end
136
+
137
+ def delete(path)
138
+ request('DELETE', path)
139
+ end
140
+
141
+ def propfind(path)
142
+ request('PROPFIND', path)
143
+ end
144
+
145
+ def head(path)
146
+ request('HEAD', path)
147
+ end
148
+
149
+ def mkcol(path)
150
+ request('MKCOL', path)
151
+ end
152
+
153
+ def put(path, local_file, auto_head = true)
154
+ if !File.exists?(local_file) || !File.readable?(local_file)
155
+ raise WebDAVException.new "File not exists or not accessible for reading!"
156
+ end
157
+
158
+ open
159
+
160
+ datalen = File.size(local_file)
161
+ header = build_header('PUT', path, datalen)
162
+
163
+ begin
164
+ if @socket.write(header) == header.length then
165
+ written = 0
166
+ File.open(local_file,'r') do |f|
167
+ until f.eof? do
168
+ written += @socket.write f.read(@chunk_size)
169
+ end
170
+ end
171
+
172
+ if written == datalen
173
+ close
174
+ if !auto_head
175
+ return true
176
+ else
177
+ return head(path)
178
+ end
179
+ end
180
+ end
181
+ rescue Exception => e
182
+ raise WebDAVException.new "Caught exception in PUT request. #{e.message}"
183
+ ensure
184
+ close
185
+ end
186
+ end
187
+
188
+ def get(path)
189
+ request('GET', path)
190
+ end
191
+
192
+ def open
193
+ begin
194
+ @socket = TCPSocket.open(@host, @port)
195
+ return true
196
+ rescue Exception => e
197
+ raise WebDAVException.new "Caught exception while opening connection. #{e.message}"
198
+ end
199
+ end
200
+
201
+ def close
202
+ begin
203
+ return @socket.close
204
+ rescue
205
+ return false
206
+ end
207
+ end
208
+
209
+ end
210
+
211
+ end
@@ -0,0 +1,153 @@
1
+ #
2
+ # webdav_store.rb
3
+ #
4
+ # author: Thomas Stätter
5
+ # date: 2014/02/01
6
+ #
7
+ module FileStore::WebDAV
8
+ #
9
+ # Main library class implementing a WebDAV file store used for storing and managing
10
+ # arbitrary files
11
+ #
12
+ class WebDAVStore
13
+ include FileStore::Logger
14
+ #
15
+ # Accessors for important properties
16
+ #
17
+ attr_reader :host, :port, :root_path, :connection, :user, :password
18
+ #
19
+ # Initializes a new instance of SimpleFileStore
20
+ #
21
+ # Arguments:
22
+ # root_path: The path where the file store resides
23
+ # logger: The logging facility
24
+ #
25
+ def initialize(host, port, user, password, root_path = '/', logger = StdoutLogger)
26
+ @host = host
27
+ @port = port
28
+ @user = user
29
+ @password = password
30
+ @root_path = root_path
31
+
32
+ initialize_connection
33
+ end
34
+ #
35
+ # Adds a file to the store
36
+ #
37
+ # Arguments:
38
+ # file: The file to be stored
39
+ #
40
+ # Returns:
41
+ # The file path or nil
42
+ #
43
+ def add(file)
44
+ raise FileStoreException, "File #{file} not found" if not File.exists?(file)
45
+ raise FileStoreException, "File #{file} isn't readable" if not File.readable?(file)
46
+
47
+ f_path = File.basename file
48
+ remote_path = File.join @root_path, f_path
49
+
50
+ begin
51
+ result = @connection.put remote_path, file
52
+
53
+ raise "Couldn't upload file, response code isn't of type 2xx" unless (result[:header].status.to_s =~ /2\d{2}/)
54
+
55
+ inform ObserverAction.new(:type => ObserverAction::TYPE_DAV_ADD,
56
+ :objects => { :file => remote_path, :meta => meta }, :msg => "Added file to remote file store") if self.is_a?(ObservedSubject)
57
+ rescue Exception => e
58
+ raise FileStoreException, "Couldn't put file '#{file}' to remote store URL '#{remote_path}'.\n#{e.backtrace.join("\n")}"
59
+ end
60
+
61
+ return remote_path
62
+ end
63
+ #
64
+ # Retrieves a file identified by it's path
65
+ #
66
+ # Arguments:
67
+ # file: The file path to get from the remote store
68
+ #
69
+ # Returns:
70
+ # A hash of file object (:path) and corresponding meta data (:data)
71
+ # representing the file in the store
72
+ #
73
+ def get(file)
74
+ raise FileStoreException, "No file given" if file.nil? or file == ''
75
+
76
+ # Retrieve data from the store
77
+ result = @connection.get file
78
+
79
+ unless result[:body].nil?
80
+ inform ObserverAction.new(:type => ObserverAction::TYPE_DAV_GET,
81
+ :objects => [file], :msg => "Returning file from the remote store") if self.is_a?(ObservedSubject)
82
+
83
+ return { :path => file, :data => result[:body] }
84
+ else
85
+ return {}
86
+ end
87
+
88
+ end
89
+ #
90
+ # Deletes a file from the remote store
91
+ #
92
+ # Arguments:
93
+ # file: The remote file path
94
+ #
95
+ def remove(file)
96
+ raise FileStoreException, "No file given for removal" if (file == '' or file.nil?)
97
+
98
+ begin
99
+ result = @connection.delete file
100
+
101
+ if result[:header].status.to_s =~ /2\d{2}/
102
+ inform ObserverAction.new(:type => ObserverAction::TYPE_DAV_REMOVE,
103
+ :objects => [id], :msg => "Deleted file from remote store") if self.is_a?(ObservedSubject)
104
+ else
105
+ raise "Response code isn't of class 2xx"
106
+ end
107
+ rescue Exception => e
108
+ raise FileStoreException, "Couldn't remove file '#{file}' from remote store.\n#{e.message}"
109
+ end
110
+ end
111
+ #
112
+ # Shuts down the file store
113
+ #
114
+ def shutdown
115
+ @connection.close
116
+
117
+ inform ObserverAction.new(:type => ObserverAction::TYPE_DAV_SHUTDOWN,
118
+ :msg => "WebDAV store shutdown") if self.is_a?(ObservedSubject)
119
+ end
120
+
121
+ private
122
+ #
123
+ # Initialize the HTTP connection
124
+ #
125
+ def initialize_connection
126
+ @connection = WebDAV.new @host, @port
127
+ @connection.credentials = { :user => @user, :password => @password }
128
+ end
129
+ #
130
+ # Creates the directory if it doesn't exist
131
+ #
132
+ # Arguments:
133
+ # path: The path to be tested or created
134
+ #
135
+ def ensure_path(path)
136
+ ret = false
137
+ remote_path = File.join(@root_path, path)
138
+ result = @connection.propfind(remote_path)
139
+
140
+ if result[:header].status.to_s =~ /2\d{2}/
141
+ # Directory exists
142
+ ret = true
143
+ else
144
+ # Directory must be created
145
+ result = @connection.mkcol remote_path
146
+ ret = true if (result[:header].status.to_s =~ /2\d{2}/)
147
+ end
148
+
149
+ ret
150
+ end
151
+ end
152
+
153
+ end
@@ -0,0 +1,130 @@
1
+ #
2
+ # tc_webdav.rb
3
+ #
4
+ # @author Thomas Stätter
5
+ # @date 2014/02/01
6
+ # @description Test script
7
+ #
8
+ require './classes.rb'
9
+ require 'test/unit'
10
+
11
+ include FileStore::WebDAV
12
+
13
+ class TestWebDAV < Test::Unit::TestCase
14
+
15
+ def setup
16
+ @host = 'owncloud.strawanzen.at'
17
+ @credentials = { :user => 'demo', :password => 'demo' }
18
+ @path = '/files'
19
+ @test_file = 'testfile.txt'
20
+ @webdav = WebDAV.new @host
21
+ @remote_dir = File.join(@path, 'new@dir')
22
+
23
+ @webdav.logger = StdoutLogger
24
+ @webdav.credentials = @credentials
25
+ @webdav.path_prefix = '/remote.php/webdav/'
26
+
27
+ File.open(@test_file, "w+") do |f|
28
+ f.write("lorem ipsum")
29
+ end
30
+ end
31
+
32
+ def teardown
33
+ FileUtils.rm(@test_file) if File.exists?(@test_file)
34
+ end
35
+
36
+ def test_01_connect
37
+ puts "=" * 80
38
+ puts "TestWebDAV::test_connect"
39
+ puts "=" * 80
40
+ result = {}
41
+
42
+ assert_nothing_raised(Exception) { result = @webdav.propfind(@path) }
43
+ assert_not_nil(result[:header])
44
+ assert_not_nil(result[:body])
45
+ assert_match(/2\d{2}/, result[:header].status.to_s, "[TestWebDAV::test_connect] Response code isn't of class 2xx")
46
+ assert(result[:header].is_xml?, "[TestWebDAV::test_connect] Response is not XML")
47
+ end
48
+
49
+ def test_02_put
50
+ puts "=" * 80
51
+ puts "TestWebDAV::test_put"
52
+ puts "=" * 80
53
+
54
+ # result = {}
55
+ upload = File.join(@path, @test_file)
56
+
57
+ assert_nothing_raised(WebDAVException) {
58
+ puts "[TestWebDAV::test_put] Uploading file '#{@test_file}' to '#{upload}'"
59
+ result = @webdav.put upload, @test_file
60
+ }
61
+ # assert_match(/2\d{2}/, result[:header].status.to_s, "Response code isn't of class 2xx")
62
+ end
63
+
64
+ def test_03_propfind
65
+ puts "=" * 80
66
+ puts "TestWebDAV::test_propfind"
67
+ puts "=" * 80
68
+
69
+ upload = File.join(@path, @test_file)
70
+ result = {}
71
+
72
+ assert_nothing_raised(WebDAVException) {
73
+ puts "[TestWebDAV::test_propfind] Reading info for '#{upload}'"
74
+ result = @webdav.propfind upload
75
+ }
76
+ assert_match(/2\d{2}/, result[:header].status.to_s, "[TestWebDAV::test_propfind] Response code isn't of class 2xx")
77
+ end
78
+
79
+ def test_04_mkcol
80
+ puts "=" * 80
81
+ puts "TestWebDAV::test_mkcol"
82
+ puts "=" * 80
83
+
84
+ result = {}
85
+
86
+ assert_nothing_raised(WebDAVException) {
87
+ puts "[TestWebDAV::test_mkcol] Creating directory file '#{@remote_dir}'"
88
+ result = @webdav.mkcol @remote_dir
89
+ }
90
+ assert_match(/2\d{2}/, result[:header].status.to_s, "[TestWebDAV::test_mkcol] Response code isn't of class 2xx")
91
+ end
92
+
93
+ def test_05_get
94
+ puts "=" * 80
95
+ puts "TestWebDAV::test_get"
96
+ puts "=" * 80
97
+
98
+ result = {}
99
+ remote_file = File.join(@path, @test_file)
100
+
101
+ assert_nothing_raised(WebDAVException) {
102
+ puts "[TestWebDAV::test_get] Trying to get remote file '#{remote_file}'"
103
+ result = @webdav.get remote_file
104
+ puts "[TestWebDAV::test_get] Got file contents: #{result[:body]}"
105
+ }
106
+ assert_match(/2\d{2}/, result[:header].status.to_s, "[TestWebDAV::test_get] Response code isn't of class 2xx")
107
+ assert_not_nil(result[:body], "[TestWebDAV::test_get] No data given")
108
+ end
109
+
110
+ def test_06_delete
111
+ puts "=" * 80
112
+ puts "TestWebDAV::test_delete"
113
+ puts "=" * 80
114
+
115
+ upload = File.join(@path, @test_file)
116
+ result = {}
117
+
118
+ assert_nothing_raised(WebDAVException) {
119
+ puts "[TestWebDAV::test_delete] Deleting file '#{upload}'"
120
+ result = @webdav.delete upload
121
+ }
122
+ assert_match(/2\d{2}/, result[:header].status.to_s, "[TestWebDAV::test_delete] Response code isn't of class 2xx")
123
+ assert_nothing_raised(WebDAVException) {
124
+ puts "[TestWebDAV::test_delete] Deleting directory '#{@remote_dir}'"
125
+ result = @webdav.delete @remote_dir
126
+ }
127
+ assert_match(/2\d{2}/, result[:header].status.to_s, "[TestWebDAV::test_delete] Response code isn't of class 2xx")
128
+ end
129
+
130
+ end
@@ -0,0 +1,109 @@
1
+ #
2
+ # tc_webdav_store.rb
3
+ #
4
+ # @author Thomas Stätter
5
+ # @date 2014/02/01
6
+ # @description Test script
7
+ #
8
+ require './classes.rb'
9
+ require 'test/unit'
10
+
11
+ include FileStore::WebDAV
12
+
13
+ class TestWebDAVStore < FileStoreTest
14
+
15
+ def test_01_init_shutdown
16
+ puts "=" * 80
17
+ puts "TestWebDAVStore::test_init_shutdown"
18
+ puts "=" * 80
19
+
20
+ store = nil
21
+
22
+ assert_nothing_raised(FileStoreException) {
23
+ store = WebDAVStoreFactory::create 'files', 'owncloud.strawanzen.at', '/remote.php/webdav/', 80, 'demo', 'demo'
24
+ }
25
+ assert_nothing_raised(FileStoreException) {
26
+ store.shutdown
27
+ }
28
+ end
29
+
30
+ def test_02_observer_registration
31
+ puts "=" * 80
32
+ puts "TestWebDAVStore::test_observer_registration"
33
+ puts "=" * 80
34
+
35
+ store = nil
36
+
37
+ assert_nothing_raised(FileStoreException) {
38
+ o1 = ObserverClass.new
39
+ o1.logger = StdoutLogger
40
+
41
+ store = WebDAVStoreFactory::create 'files/', 'owncloud.strawanzen.at', '/remote.php/webdav/', 80, 'demo', 'demo', true
42
+
43
+ store.register o1
44
+ store.inform "Some test message"
45
+ store.shutdown
46
+ }
47
+ end
48
+
49
+ def test_03_actions_with_observer
50
+ # puts "=" * 80
51
+ # puts "TestWebDAVStore::test_actions_with_observer"
52
+ # puts "=" * 80
53
+ end
54
+
55
+ def test_04_upload
56
+ puts "=" * 80
57
+ puts "TestWebDAVStore::test_upload"
58
+ puts "=" * 80
59
+
60
+ assert_nothing_raised(FileStoreException) {
61
+ open(@testFileSimple, 'w') do |f|
62
+ f.write "lorem ipsum"
63
+ end
64
+
65
+ store = WebDAVStoreFactory::create 'files', 'owncloud.strawanzen.at', '/remote.php/webdav/', 80, 'demo', 'demo'
66
+ puts "[TestWebDAVStore::test_upload] Trying to upload '#{@testFileSimple}' to remote store"
67
+ file = store.add @testFileSimple
68
+
69
+ store.shutdown
70
+
71
+ puts "[TestWebDAVStore::test_upload] Added file '#{file}'"
72
+ }
73
+ end
74
+
75
+ def test_05_get
76
+ puts "=" * 80
77
+ puts "TestWebDAVStore::test_get"
78
+ puts "=" * 80
79
+
80
+ remote_file = 'files/testfile.txt'
81
+
82
+ assert_nothing_raised(FileStoreException) {
83
+ store = WebDAVStoreFactory::create 'files', 'owncloud.strawanzen.at', '/remote.php/webdav/', 80, 'demo', 'demo'
84
+ puts "[TestWebDAVStore::test_get] Trying to upload '#{remote_file}' to remote store"
85
+ file = store.get remote_file
86
+
87
+ store.shutdown
88
+
89
+ puts "[TestWebDAVStore::test_upload] Got file '#{file}'"
90
+ }
91
+ end
92
+
93
+ def test_06_remove
94
+ puts "=" * 80
95
+ puts "TestWebDAVStore::test_remove"
96
+ puts "=" * 80
97
+
98
+ remote_file = 'files/testfile.txt'
99
+
100
+ assert_nothing_raised(FileStoreException) {
101
+ store = WebDAVStoreFactory::create 'files', 'owncloud.strawanzen.at', '/remote.php/webdav/', 80, 'demo', 'demo'
102
+ puts "[TestWebDAVStore::test_remove] Trying to delete '#{remote_file}' from remote store"
103
+ store.remove remote_file
104
+
105
+ store.shutdown
106
+ }
107
+ end
108
+
109
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: filestore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.19
4
+ version: 0.0.20
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-01-05 00:00:00.000000000 Z
12
+ date: 2014-02-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: uuidtools
@@ -46,12 +46,16 @@ files:
46
46
  - lib/filestore/multitenant_store.rb
47
47
  - lib/filestore/observer.rb
48
48
  - lib/filestore/simple_store.rb
49
+ - lib/filestore/webdav/webdav.rb
50
+ - lib/filestore/webdav_store.rb
49
51
  - lib/filestore.rb
50
52
  - test/classes.rb
51
53
  - test/tc_filestore.rb
52
54
  - test/tc_meta.rb
53
55
  - test/tc_module.rb
54
56
  - test/tc_multitenant.rb
57
+ - test/tc_webdav.rb
58
+ - test/tc_webdav_store.rb
55
59
  - test/ts_all.rb
56
60
  homepage: https://github.com/tstaetter/filestore-gem
57
61
  licenses: []
@@ -72,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
76
  - !ruby/object:Gem::Version
73
77
  version: '0'
74
78
  requirements:
75
- - gem uuidtools, log4r
79
+ - gem uuidtools
76
80
  rubyforge_project:
77
81
  rubygems_version: 1.8.24
78
82
  signing_key:
@@ -84,4 +88,6 @@ test_files:
84
88
  - test/tc_meta.rb
85
89
  - test/tc_module.rb
86
90
  - test/tc_multitenant.rb
91
+ - test/tc_webdav.rb
92
+ - test/tc_webdav_store.rb
87
93
  - test/ts_all.rb