xcapclient 1.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/ERRORS.rdoc +123 -0
- data/LICENSE.txt +674 -0
- data/README.rdoc +172 -0
- data/lib/xcapclient/application.rb +62 -0
- data/lib/xcapclient/client.rb +584 -0
- data/lib/xcapclient/document.rb +40 -0
- data/lib/xcapclient/errors.rb +21 -0
- data/lib/xcapclient.rb +30 -0
- data/test/PRES_RULES_EXAMPLE.xml +49 -0
- data/test/test_unit_01.rb +352 -0
- metadata +74 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
<?xml version='1.0' encoding='UTF-8'?>
|
2
|
+
<cp:ruleset xmlns:pr="urn:ietf:params:xml:ns:pres-rules" xmlns:cp="urn:ietf:params:xml:ns:common-policy">
|
3
|
+
<cp:rule id="pres_whitelist">
|
4
|
+
<cp:conditions>
|
5
|
+
<cp:identity>
|
6
|
+
<cp:one id="sip:alice@example.org"/>
|
7
|
+
<cp:one id="sip:bob@example.org"/>
|
8
|
+
<cp:one id="sip:carol@example2.net"/>
|
9
|
+
</cp:identity>
|
10
|
+
</cp:conditions>
|
11
|
+
<cp:actions>
|
12
|
+
<pr:sub-handling>allow</pr:sub-handling>
|
13
|
+
</cp:actions>
|
14
|
+
<cp:transformations>
|
15
|
+
<pr:provide-services>
|
16
|
+
<pr:all-services/>
|
17
|
+
</pr:provide-services>
|
18
|
+
<pr:provide-persons>
|
19
|
+
<pr:all-persons/>
|
20
|
+
</pr:provide-persons>
|
21
|
+
<pr:provide-devices>
|
22
|
+
<pr:all-devices/>
|
23
|
+
</pr:provide-devices>
|
24
|
+
<pr:provide-all-attributes/>
|
25
|
+
</cp:transformations>
|
26
|
+
</cp:rule>
|
27
|
+
<cp:rule id="pres_blacklist">
|
28
|
+
<cp:conditions>
|
29
|
+
<cp:identity>
|
30
|
+
<cp:one id="sip:bill@microsoft.com"/>
|
31
|
+
</cp:identity>
|
32
|
+
</cp:conditions>
|
33
|
+
<cp:actions>
|
34
|
+
<pr:sub-handling>block</pr:sub-handling>
|
35
|
+
</cp:actions>
|
36
|
+
<cp:transformations/>
|
37
|
+
</cp:rule>
|
38
|
+
<cp:rule id="pres_polite_blacklist">
|
39
|
+
<cp:conditions>
|
40
|
+
<cp:identity>
|
41
|
+
<cp:one id="sip:steve@apple.com"/>
|
42
|
+
</cp:identity>
|
43
|
+
</cp:conditions>
|
44
|
+
<cp:actions>
|
45
|
+
<pr:sub-handling>polite-block</pr:sub-handling>
|
46
|
+
</cp:actions>
|
47
|
+
<cp:transformations/>
|
48
|
+
</cp:rule>
|
49
|
+
</cp:ruleset>
|
@@ -0,0 +1,352 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
|
4
|
+
# IMPORTANT: Configure these values with your own setting.
|
5
|
+
#
|
6
|
+
XCAP_ROOT = "https://xcap.example.org/xcap-root"
|
7
|
+
USER = "sip:user@example.org"
|
8
|
+
AUTH_USER = "user"
|
9
|
+
PASSWORD = "xxxx"
|
10
|
+
SSL_VERIFY_CERT = false
|
11
|
+
|
12
|
+
|
13
|
+
# Let's check that the user has customized the above settings.
|
14
|
+
if USER == "sip:user@example.org"
|
15
|
+
STDERR.puts "ERROR: You must configure the settings with your own values. Edit the top lines of this script."
|
16
|
+
exit 1
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
require "test/unit"
|
21
|
+
require "rubygems"
|
22
|
+
require "xcapclient"
|
23
|
+
|
24
|
+
|
25
|
+
include XCAPClient
|
26
|
+
|
27
|
+
|
28
|
+
# This test unit checks XCAPClient's and XCAP server's behaviour according to specifications in RFC 4825.
|
29
|
+
# It's focused on OpenXCAP[http://www.openxcap.org] server. In fact, some tests fail due to known bugs in OpenXCAP.
|
30
|
+
#
|
31
|
+
class TestXCAPClient < Test::Unit::TestCase
|
32
|
+
|
33
|
+
|
34
|
+
PRES_RULES = File.new(File.join(File.dirname(__FILE__), "PRES_RULES_EXAMPLE.xml")).read
|
35
|
+
NS = {"pr"=>"urn:ietf:params:xml:ns:pres-rules", "cp"=>"urn:ietf:params:xml:ns:common-policy"}
|
36
|
+
|
37
|
+
|
38
|
+
def setup
|
39
|
+
|
40
|
+
xcap_conf = {
|
41
|
+
:xcap_root => XCAP_ROOT,
|
42
|
+
:user => USER,
|
43
|
+
:auth_user => AUTH_USER,
|
44
|
+
:password => PASSWORD,
|
45
|
+
:ssl_verify_cert => SSL_VERIFY_CERT
|
46
|
+
}
|
47
|
+
|
48
|
+
xcap_apps = {
|
49
|
+
"pres-rules" => {
|
50
|
+
:xmlns => "urn:ietf:params:xml:ns:pres-rules",
|
51
|
+
:mime_type => "application/auth-policy+xml",
|
52
|
+
:document_name => "pres-rules"
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
@client = Client.new(xcap_conf, xcap_apps)
|
57
|
+
@client.application("pres-rules").document.plain = PRES_RULES
|
58
|
+
|
59
|
+
@doc = @client.application("pres-rules").document
|
60
|
+
|
61
|
+
reset_document
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
def teardown
|
67
|
+
reset_document
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
def test_01_get
|
72
|
+
show "Fetching the document (correct ETag) => 304"
|
73
|
+
begin
|
74
|
+
assert @client.get("pres-rules")
|
75
|
+
rescue => e
|
76
|
+
assert_equal( HTTPDocumentNotModified, e.class )
|
77
|
+
else
|
78
|
+
should_fail
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
def test_02_get
|
84
|
+
show "Fetching the document (wrong ETag) => 200"
|
85
|
+
@doc.etag = "wrongETag"
|
86
|
+
assert @client.get("pres-rules")
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
def test_03_put
|
91
|
+
show "Replace the document (correct ETag)=> 2XX"
|
92
|
+
assert @client.put("pres-rules")
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
def test_04_put
|
97
|
+
show "Replace the document (wrong ETag) => 412"
|
98
|
+
begin
|
99
|
+
@doc.etag = "wrongETag"
|
100
|
+
@client.put("pres-rules")
|
101
|
+
rescue => e
|
102
|
+
assert_equal( HTTPNoMatchingETag, e.class )
|
103
|
+
else
|
104
|
+
should_fail
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
def test_05_put
|
110
|
+
show "Replace the document (no ETag) => 200"
|
111
|
+
assert @client.put("pres-rules", nil, check_etag=false)
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
def test_06_delete
|
116
|
+
show "Deleting the document (correct ETag) => 200"
|
117
|
+
assert @client.delete("pres-rules")
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
def test_07_delete
|
122
|
+
show "Deleting a non existing document (no ETag) => 404"
|
123
|
+
@client.delete("pres-rules")
|
124
|
+
begin
|
125
|
+
@client.delete("pres-rules")
|
126
|
+
rescue => e
|
127
|
+
assert_equal( HTTPDocumentNotFound, e.class )
|
128
|
+
else
|
129
|
+
should_fail
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
def test_08_delete
|
135
|
+
show "Deleting the document (wrong ETag) => 412"
|
136
|
+
begin
|
137
|
+
@doc.etag = "wrongETag"
|
138
|
+
@client.delete("pres-rules")
|
139
|
+
rescue => e
|
140
|
+
assert_equal( HTTPNoMatchingETag, e.class )
|
141
|
+
else
|
142
|
+
should_fail
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
def test_09_delete
|
148
|
+
show "Deleting the document (no ETag) => 200"
|
149
|
+
assert @client.delete("pres-rules", nil, check_etag=false)
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
def test_10_get_element
|
154
|
+
show "Fetching a node (no ETag) => 200"
|
155
|
+
assert @client.get_element("pres-rules", nil,
|
156
|
+
'/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:bob@example.org"]',
|
157
|
+
NS,
|
158
|
+
check_etag=false)
|
159
|
+
end
|
160
|
+
|
161
|
+
|
162
|
+
def test_11_get_element
|
163
|
+
show "Fetching a node (correct ETag) => 304"
|
164
|
+
begin
|
165
|
+
@client.get_element("pres-rules", nil,
|
166
|
+
'/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:alice@example.org"]',
|
167
|
+
NS,
|
168
|
+
check_etag=true)
|
169
|
+
rescue => e
|
170
|
+
assert_equal( HTTPDocumentNotModified, e.class )
|
171
|
+
else
|
172
|
+
should_fail
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
# NOTE: OpenXCAP doesn't implement fetching element attributes.
|
178
|
+
# BUG in OpenXCAP: http://openxcap.org/ticket/122
|
179
|
+
def test_12_get_element
|
180
|
+
show "Fetching an attribute (no ETag) => 200 (fails in OpenXCAP, bug http://openxcap.org/ticket/122)"
|
181
|
+
assert @client.get_element("pres-rules", nil,
|
182
|
+
'/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:alice@example.org"]/@id',
|
183
|
+
NS,
|
184
|
+
check_etag=false)
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
def test_13_put_element
|
189
|
+
show "Creating a node (no ETag) => 201"
|
190
|
+
assert @client.put_element("pres-rules", nil,
|
191
|
+
'/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:new-1@new.net"]',
|
192
|
+
'<cp:one id="sip:new-1@new.net"/>',
|
193
|
+
NS,
|
194
|
+
check_etag=false)
|
195
|
+
end
|
196
|
+
|
197
|
+
|
198
|
+
def test_14_put_element
|
199
|
+
show "Creating a node (wrong ETag) => 412"
|
200
|
+
begin
|
201
|
+
@doc.etag = "wrongETag"
|
202
|
+
@client.put_element("pres-rules", nil,
|
203
|
+
'/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:condition/cp:identity/cp:one[@id="sip:new-2@new.net"]',
|
204
|
+
'<cp:one id="sip:new-2@new.net"/>',
|
205
|
+
NS,
|
206
|
+
check_etag=true)
|
207
|
+
rescue => e
|
208
|
+
assert_equal( HTTPNoMatchingETag, e.class )
|
209
|
+
else
|
210
|
+
should_fail
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
|
215
|
+
def test_15_put_element
|
216
|
+
show "Creating a node in wrong position => 409"
|
217
|
+
begin
|
218
|
+
@client.put_element("pres-rules", nil,
|
219
|
+
'/cp:ruleset/cp:rule[@id="non_existing"]/cp:condition/cp:identity/cp:one[@id="sip:new-3@new.net"]',
|
220
|
+
'<cp:one id="sip:new-3@new.net"/>',
|
221
|
+
NS,
|
222
|
+
check_etag=false)
|
223
|
+
rescue => e
|
224
|
+
assert_equal( HTTPConflictError, e.class )
|
225
|
+
else
|
226
|
+
should_fail
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
|
231
|
+
def test_16_put_element
|
232
|
+
show "Creating a node using different NS prefixes than the used in the server document (no ETag) => 409/500"
|
233
|
+
begin
|
234
|
+
@client.put_element("pres-rules", nil,
|
235
|
+
'/ccpp:ruleset/ccpp:rule[@id="pres_whitelist"]/ccpp:conditions/ccpp:identity/ccpp:one[@id="sip:new-4@new.net"]',
|
236
|
+
'<ccpp:one id="sip:new-4@new.net"/>',
|
237
|
+
{"pprr"=>"urn:ietf:params:xml:ns:pres-rules", "ccpp"=>"urn:ietf:params:xml:ns:common-policy"},
|
238
|
+
check_etag=false)
|
239
|
+
rescue => e
|
240
|
+
assert_equal_options( [ HTTPServerError, HTTPConflictError ], e.class )
|
241
|
+
else
|
242
|
+
should_fail
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
|
247
|
+
# NOTE: This should fail since the selector doesn't match an unique node, but OpenXCAP allows it.
|
248
|
+
# BUG in OpenXCAP: http://openxcap.org/ticket/123
|
249
|
+
def test_17_put_element
|
250
|
+
show "Creating a node using using a non unique selector (no ETag) => 409 (fails in OpenXCAP, bug http://openxcap.org/ticket/123)"
|
251
|
+
begin
|
252
|
+
@client.put_element("pres-rules", nil,
|
253
|
+
'/cp:ruleset/cp:rule/cp:conditions/cp:identity/cp:one[@id="sip:new-5@new.net"]',
|
254
|
+
'<cp:one id="sip:new-5@new.net"/>',
|
255
|
+
NS,
|
256
|
+
check_etag=false)
|
257
|
+
rescue
|
258
|
+
assert_equal( HTTPConflictError, e.class )
|
259
|
+
else
|
260
|
+
should_fail
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
|
265
|
+
def test_18_delete_element
|
266
|
+
show "Deleting an element (no ETag) => 200"
|
267
|
+
assert @client.delete_element("pres-rules", nil,
|
268
|
+
'/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:bob@example.org"]',
|
269
|
+
NS,
|
270
|
+
check_etag=false)
|
271
|
+
end
|
272
|
+
|
273
|
+
|
274
|
+
def test_19_delete_element
|
275
|
+
show "Deleting an element (wrong ETag) => 412"
|
276
|
+
begin
|
277
|
+
@doc.etag = "wrongETag"
|
278
|
+
@client.delete_element("pres-rules", nil,
|
279
|
+
'/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:condition/cp:identity/cp:one[@id="sip:bob@example.org"]',
|
280
|
+
NS,
|
281
|
+
check_etag=true)
|
282
|
+
rescue => e
|
283
|
+
assert_equal( HTTPNoMatchingETag, e.class )
|
284
|
+
else
|
285
|
+
should_fail
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
def test_20_delete_element
|
291
|
+
show "Deleting a no existing element (correct ETag) => 404"
|
292
|
+
@client.delete_element("pres-rules", nil,
|
293
|
+
'/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:alice@example.org"]',
|
294
|
+
NS)
|
295
|
+
begin
|
296
|
+
@client.delete_element("pres-rules", nil,
|
297
|
+
'/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:alice@example.org"]',
|
298
|
+
NS)
|
299
|
+
rescue => e
|
300
|
+
assert_equal( HTTPDocumentNotFound, e.class )
|
301
|
+
else
|
302
|
+
should_fail
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
|
307
|
+
# NOTE: OpenXCAP doesn't implement fetching namespaces.
|
308
|
+
# BUG in OpenXCAP: http://openxcap.org/ticket/124
|
309
|
+
def test_21_get_element_namespaces
|
310
|
+
show "Fetching the namespaces associated to a document node => 200 (fails in OpenXCAP, bug http://openxcap.org/ticket/124)"
|
311
|
+
assert @client.get_element_namespaces("pres-rules", nil,
|
312
|
+
'/ccpp:ruleset/ccpp:rule[@id="pres_whitelist"]/ccpp:conditions/ccpp:identity',
|
313
|
+
{"ccpp"=>"urn:ietf:params:xml:ns:common-policy"},
|
314
|
+
check_etag=false)
|
315
|
+
assert_equal( @client.application("pres-rules").document.last_response.header["Content-Type"], "application/xcap-ns+xml" )
|
316
|
+
end
|
317
|
+
|
318
|
+
|
319
|
+
def test_22_get_xcap_auids
|
320
|
+
show "Fetching the XCAP server available 'auids' => 200"
|
321
|
+
assert @client.get_xcap_auids
|
322
|
+
end
|
323
|
+
|
324
|
+
|
325
|
+
def reset_document
|
326
|
+
@doc.plain = PRES_RULES
|
327
|
+
@doc.etag = nil
|
328
|
+
@client.put("pres-rules", nil, check_etag=false) # Upload without cheking ETag.
|
329
|
+
end
|
330
|
+
|
331
|
+
|
332
|
+
def show(text)
|
333
|
+
puts "\n\n[#{name}] #{text}"
|
334
|
+
end
|
335
|
+
|
336
|
+
|
337
|
+
def should_fail
|
338
|
+
raise RuntimeError, "It should fail but didn't"
|
339
|
+
end
|
340
|
+
|
341
|
+
|
342
|
+
def assert_false(object, message="")
|
343
|
+
assert_equal(object, false, message)
|
344
|
+
end
|
345
|
+
|
346
|
+
|
347
|
+
def assert_equal_options(options, element)
|
348
|
+
assert options.include?(element)
|
349
|
+
end
|
350
|
+
|
351
|
+
|
352
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: xcapclient
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "1.0"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "I\xC3\xB1aki Baz Castillo"
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-07-31 00:00:00 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: httpclient
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description: XCAP (RFC 4825) is a protocol on top of HTTP which allows a client (usually a VoIP/SIP device) to manipulate the contents of Presence Information Data Format (PIDF) based presence documents. These documents are stored in a server in XML format. Ruby xcapclient library implements the XCAP protocol in client side, allowing the applications to get, store, modify and delete XML documents in the server.'
|
26
|
+
email: ibc@aliax.net
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README.rdoc
|
33
|
+
- ERRORS.rdoc
|
34
|
+
- LICENSE.txt
|
35
|
+
- test/PRES_RULES_EXAMPLE.xml
|
36
|
+
files:
|
37
|
+
- LICENSE.txt
|
38
|
+
- lib/xcapclient/client.rb
|
39
|
+
- lib/xcapclient.rb
|
40
|
+
- lib/xcapclient/errors.rb
|
41
|
+
- lib/xcapclient/application.rb
|
42
|
+
- lib/xcapclient/document.rb
|
43
|
+
- test/PRES_RULES_EXAMPLE.xml
|
44
|
+
- README.rdoc
|
45
|
+
- ERRORS.rdoc
|
46
|
+
has_rdoc: true
|
47
|
+
homepage: http://dev.sipdoc.net/projects/ruby-xcap-client/wiki/
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options:
|
50
|
+
- --main
|
51
|
+
- README.rdoc
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: 1.8.1
|
59
|
+
version:
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: "0"
|
65
|
+
version:
|
66
|
+
requirements: []
|
67
|
+
|
68
|
+
rubyforge_project: xcapclient
|
69
|
+
rubygems_version: 1.3.1
|
70
|
+
signing_key:
|
71
|
+
specification_version: 2
|
72
|
+
summary: XCAP client library
|
73
|
+
test_files:
|
74
|
+
- test/test_unit_01.rb
|