simple_dav 0.0.3 → 0.0.4
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/lib/simple_dav.rb +111 -88
- metadata +3 -3
data/lib/simple_dav.rb
CHANGED
@@ -19,12 +19,7 @@ PROFILE:VCARD
|
|
19
19
|
END:VCARD
|
20
20
|
EOF
|
21
21
|
|
22
|
-
GROUPVCF =
|
23
|
-
BEGIN:VCARD
|
24
|
-
VERSION:3.0
|
25
|
-
PRODID:-//IDFuze//SimpleDav//EN
|
26
|
-
END:VCARD
|
27
|
-
EOF
|
22
|
+
GROUPVCF = BASEVCF
|
28
23
|
|
29
24
|
class SimpleDav
|
30
25
|
attr_reader :headers, :uri, :client
|
@@ -38,7 +33,7 @@ class SimpleDav
|
|
38
33
|
begin
|
39
34
|
url = params[:ssl] ? "https://#{params[:server]}/" : "http://#{params[:server]}/"
|
40
35
|
url += case (@type = params[:type])
|
41
|
-
when "sogo" then "
|
36
|
+
when "sogo" then "SOGo/dav/#{params[:user]}/"
|
42
37
|
else ""
|
43
38
|
end
|
44
39
|
@uri = URI.parse(url)
|
@@ -59,31 +54,37 @@ class SimpleDav
|
|
59
54
|
end
|
60
55
|
|
61
56
|
class AddressBook < SimpleDav
|
62
|
-
|
63
|
-
def initialize(
|
57
|
+
attr_reader :group
|
58
|
+
def initialize(params)
|
59
|
+
abu = "personal"
|
64
60
|
@vcard = nil
|
65
61
|
super(params)
|
66
62
|
@abu = @type == "sogo" ? "Contacts/#{abu}/" : "#{abu}"
|
67
63
|
@uri.path += @abu
|
68
|
-
@group = nil
|
64
|
+
@group = nil #store group uid
|
65
|
+
Card.adb = self
|
69
66
|
end
|
70
67
|
|
71
68
|
# select address book
|
72
|
-
def
|
69
|
+
def change_group(abu)
|
73
70
|
#todo select uid or nil if personnal
|
74
|
-
|
75
|
-
|
71
|
+
# old style folders
|
72
|
+
#@uri.path -= @abu
|
73
|
+
#@uri.path += (@abu = abu)
|
74
|
+
# new style v4 group
|
75
|
+
groups = Card.where({"X-ADDRESSBOOKSERVER-KIND" => "group", "f" => abu})
|
76
|
+
@group = groups && groups.first && groups.first.uid
|
76
77
|
end
|
77
78
|
|
78
79
|
# list available address books
|
79
80
|
#find all X-ADDRESSBOOKSERVER-KIND
|
80
81
|
def list
|
81
|
-
where("X-ADDRESSBOOKSERVER-KIND"
|
82
|
+
Card.where("X-ADDRESSBOOKSERVER-KIND" => "group")
|
82
83
|
end
|
83
84
|
|
84
85
|
# find addresse resource by uid
|
85
86
|
def self.find(uid)
|
86
|
-
|
87
|
+
Card.find(self, uid)
|
87
88
|
end
|
88
89
|
|
89
90
|
# create collection : not working actually
|
@@ -124,9 +125,9 @@ class AddressBook < SimpleDav
|
|
124
125
|
def create(name, description = "")
|
125
126
|
uid = "#{gen_uid}"
|
126
127
|
|
127
|
-
@vcard =
|
128
|
+
@vcard = Card.new(GROUPVCF)
|
128
129
|
@vcard.add_attribute("X-ADDRESSBOOKSERVER-KIND", "group")
|
129
|
-
@vcard.add_attribute("rev", Time.now.utc.
|
130
|
+
@vcard.add_attribute("rev", Time.now.utc.iso8601(2))
|
130
131
|
@vcard.add_attribute("uid", uid)
|
131
132
|
@vcard.add_attribute(:f, name)
|
132
133
|
@vcard.add_attribute(:fn, description)
|
@@ -155,60 +156,6 @@ class AddressBook < SimpleDav
|
|
155
156
|
def vcard
|
156
157
|
@vcard
|
157
158
|
end
|
158
|
-
|
159
|
-
# find where RoR style
|
160
|
-
def where(conditions)
|
161
|
-
query = Nokogiri::XML::Builder.new(:encoding => "UTF-8") do |xml|
|
162
|
-
xml.send('C:addressbook-query', 'xmlns:D' => "DAV:", 'xmlns:C' => "urn:ietf:params:xml:ns:carddav") do
|
163
|
-
xml.send('D:prop') do
|
164
|
-
xml.send('D:getetag')
|
165
|
-
xml.send('C:address-data') do
|
166
|
-
xml.send('C:prop', 'name' => "UID")
|
167
|
-
conditions.each do |k,v|
|
168
|
-
xml.send('C:prop', 'name' => k.to_s.upcase)
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
xml.send('C:filter') do
|
173
|
-
conditions.each do |k,v|
|
174
|
-
xml.send('C:prop-filter', 'name' => k.to_s.upcase) do
|
175
|
-
xml.send('C:text-match', 'collation' => "i;unicode-casemap", 'match-type' => "equals") do
|
176
|
-
xml << v
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
183
|
-
headers = {
|
184
|
-
"content-Type" => "text/xml; charset=\"utf-8\"",
|
185
|
-
"depth" => 1
|
186
|
-
}
|
187
|
-
|
188
|
-
content = @client.request('REPORT', @uri, nil, query.to_xml.to_s, headers)
|
189
|
-
#puts "#{content.body}"
|
190
|
-
xml = Nokogiri::XML(content.body)
|
191
|
-
vcards = []
|
192
|
-
xml.xpath('//C:address-data').each do |card|
|
193
|
-
vcards << Vcard.new(self, card.text)
|
194
|
-
end
|
195
|
-
return vcards
|
196
|
-
end
|
197
|
-
|
198
|
-
def method_missing(meth, *args, &block)
|
199
|
-
if meth.to_s =~ /^find_by_(.+)$/
|
200
|
-
run_find_by_method($1, *args, &block)
|
201
|
-
else
|
202
|
-
super
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
def run_find_by_method(attrs, *args, &block)
|
207
|
-
attrs = attrs.split('_and_')
|
208
|
-
attrs_with_args = [attrs, args].transpose
|
209
|
-
conditions = Hash[attrs_with_args]
|
210
|
-
where(conditions)
|
211
|
-
end
|
212
159
|
|
213
160
|
def debug_dev=(dev)
|
214
161
|
@client.debug_dev = dev
|
@@ -218,21 +165,22 @@ end
|
|
218
165
|
|
219
166
|
# attributes : n|email|title|nickname|tel|bday|fn|org|note|uid
|
220
167
|
# todo change for another vcard managment class
|
221
|
-
class
|
222
|
-
|
168
|
+
class Card
|
169
|
+
class << self; attr_accessor :adb end
|
170
|
+
@adb = nil
|
223
171
|
|
224
|
-
def initialize(
|
172
|
+
def initialize(text = BASEVCF)
|
225
173
|
@plain = text
|
226
|
-
@ab = ab
|
227
174
|
return self
|
228
175
|
end
|
229
176
|
|
230
177
|
def self.find(uid)
|
231
|
-
|
178
|
+
where(:uid => uid)
|
232
179
|
end
|
233
180
|
|
234
181
|
# create address resource
|
235
182
|
def self.create(params)
|
183
|
+
@vcard = Card.new
|
236
184
|
params.each do |k,v|
|
237
185
|
@vcard.update_attribute(k,v)
|
238
186
|
end
|
@@ -242,16 +190,16 @@ class Vcard
|
|
242
190
|
"Content-Type" => "text/vcard",
|
243
191
|
"Content-Length" => @vcard.to_s.size
|
244
192
|
}
|
245
|
-
uid = "#{
|
193
|
+
uid = "#{adb.gen_uid}.vcf"
|
246
194
|
|
247
195
|
@vcard.update_attribute(:uid, uid)
|
248
|
-
if
|
249
|
-
@vcard.add_attribute("X-ADDRESSBOOKSERVER-MEMBER", "urn:uuid:#{
|
196
|
+
if adb && adb.group
|
197
|
+
@vcard.add_attribute("X-ADDRESSBOOKSERVER-MEMBER", "urn:uuid:#{adb.group}")
|
250
198
|
end
|
251
199
|
|
252
|
-
unc =
|
200
|
+
unc = adb.uri.clone
|
253
201
|
unc.path += uid
|
254
|
-
res =
|
202
|
+
res = adb.client.request('PUT', unc, nil, @vcard.to_s, headers)
|
255
203
|
|
256
204
|
if res.status < 200 or res.status >= 300
|
257
205
|
@uid = nil
|
@@ -273,9 +221,9 @@ class Vcard
|
|
273
221
|
}
|
274
222
|
uid = self.uid
|
275
223
|
|
276
|
-
unc =
|
224
|
+
unc = Card.adb.uri.clone
|
277
225
|
unc.path += uid
|
278
|
-
res =
|
226
|
+
res = Card.adb.client.request('PUT', unc, nil, @plain, headers)
|
279
227
|
|
280
228
|
if res.status < 200 or res.status >= 300
|
281
229
|
@uid = nil
|
@@ -287,15 +235,15 @@ class Vcard
|
|
287
235
|
end
|
288
236
|
|
289
237
|
def delete
|
290
|
-
if @uid &&
|
238
|
+
if @uid && Card.adb
|
291
239
|
|
292
240
|
headers = {
|
293
241
|
#"If-None-Match" => "*",
|
294
242
|
"Content-Type" => "text/xml; charset=\"utf-8\""
|
295
243
|
}
|
296
|
-
unc =
|
244
|
+
unc = adb.uri.clone
|
297
245
|
unc.path += @uid
|
298
|
-
res =
|
246
|
+
res = adb.client.request('DELETE', unc, nil, nil, headers)
|
299
247
|
|
300
248
|
if res.status < 200 or res.status >= 300
|
301
249
|
@uid = nil
|
@@ -309,6 +257,23 @@ class Vcard
|
|
309
257
|
end
|
310
258
|
end
|
311
259
|
|
260
|
+
def retreive
|
261
|
+
path = "#{self.uid}.vcf"
|
262
|
+
unc = adb.uri.clone
|
263
|
+
unc.path += path
|
264
|
+
res = adb.client.request('GET', unc)
|
265
|
+
|
266
|
+
if res.status < 200 or res.status >= 300
|
267
|
+
@uid = nil
|
268
|
+
raise "delete failed: #{res.inspect}"
|
269
|
+
else
|
270
|
+
puts res.body
|
271
|
+
@plain = res.body
|
272
|
+
@uid = uid
|
273
|
+
true
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
312
277
|
def update_attribute(a, v)
|
313
278
|
@plain.match(/^#{a.to_s.upcase}:(.+)$/) ? @plain.gsub!(/^#{a.to_s.upcase}:(.+)$/, "#{a.to_s.upcase}:#{v}") : add_attribute(a, v)
|
314
279
|
end
|
@@ -318,8 +283,11 @@ class Vcard
|
|
318
283
|
end
|
319
284
|
|
320
285
|
def method_missing(meth, *args, &block)
|
321
|
-
|
322
|
-
|
286
|
+
case meth.to_s
|
287
|
+
when /^((n|email|title|nickname|tel|bday|fn|org|note|uid|X-ADDRESSBOOKSERVER-KIND)=?)$/
|
288
|
+
run_on_field($1, *args, &block)
|
289
|
+
when /^find_by_(.+)$/
|
290
|
+
run_find_by_method($1, *args, &block)
|
323
291
|
else
|
324
292
|
super
|
325
293
|
end
|
@@ -341,6 +309,61 @@ class Vcard
|
|
341
309
|
end
|
342
310
|
end
|
343
311
|
|
312
|
+
# find where RoR style
|
313
|
+
def self.where(conditions)
|
314
|
+
limit = 1
|
315
|
+
query = Nokogiri::XML::Builder.new(:encoding => "UTF-8") do |xml|
|
316
|
+
xml.send('B:addressbook-query', 'xmlns:B' => "urn:ietf:params:xml:ns:carddav") do
|
317
|
+
xml.send('A:prop', 'xmlns:A' => "DAV:",) do
|
318
|
+
xml.send('A:getetag')
|
319
|
+
xml.send('B:address-data')
|
320
|
+
|
321
|
+
end
|
322
|
+
#xml.send('C:filter', 'test' => "anyof") do
|
323
|
+
xml.send('B:filter', 'test' => 'anyof') do
|
324
|
+
conditions.each do |k,v|
|
325
|
+
xml.send('B:prop-filter', 'test' => 'allof','name' => k.to_s) do
|
326
|
+
#xml.send('C:text-match', 'collation' => "i;unicode-casemap", 'match-type' => "contains") do
|
327
|
+
xml.send('B:text-match', 'collation' => "i;unicode-casemap", 'match-type' => "contains") do
|
328
|
+
xml << v
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
if limit
|
334
|
+
xml.send('C:limit') do
|
335
|
+
xml.send('C:nresults') do
|
336
|
+
xml << "#{limit}"
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
end
|
342
|
+
|
343
|
+
end
|
344
|
+
headers = {
|
345
|
+
"content-Type" => "text/xml; charset=\"utf-8\"",
|
346
|
+
"depth" => 1,
|
347
|
+
"Content-Length" => "#{query.to_xml.to_s.size}"
|
348
|
+
}
|
349
|
+
puts ">>>> #{adb.uri}\n"
|
350
|
+
content = adb.client.request('REPORT', adb.uri, nil, query.to_xml.to_s, headers)
|
351
|
+
puts "#{content.body}\n\n#{query.to_xml}\n\n"
|
352
|
+
xml = Nokogiri::XML(content.body)
|
353
|
+
vcards = []
|
354
|
+
xml.xpath('//C:address-data').each do |card|
|
355
|
+
vcards << Card.new(card.text)
|
356
|
+
end
|
357
|
+
return vcards
|
358
|
+
end
|
359
|
+
|
360
|
+
def run_find_by_method(attrs, *args, &block)
|
361
|
+
attrs = attrs.split('_and_')
|
362
|
+
attrs_with_args = [attrs, args].transpose
|
363
|
+
conditions = Hash[attrs_with_args]
|
364
|
+
where(conditions)
|
365
|
+
end
|
366
|
+
|
344
367
|
def to_s
|
345
368
|
@plain.to_s
|
346
369
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 4
|
9
|
+
version: 0.0.4
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Olivier DIRRENBERGER
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2012-10-
|
17
|
+
date: 2012-10-05 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|