xcapclient 1.0 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ERRORS.rdoc +8 -2
- data/README.rdoc +16 -9
- data/lib/xcapclient/client.rb +113 -24
- data/lib/xcapclient/errors.rb +1 -0
- data/lib/xcapclient.rb +1 -1
- metadata +5 -3
data/ERRORS.rdoc
CHANGED
@@ -14,7 +14,7 @@ The XCAPClient library includes custom Ruby exceptions. All these exceptions inh
|
|
14
14
|
* WrongAUID
|
15
15
|
* DocumentError
|
16
16
|
* HTTPError
|
17
|
-
|
17
|
+
* HTTPAuthenticationError
|
18
18
|
* HTTPNoMatchingETag
|
19
19
|
* HTTPConflictError
|
20
20
|
* HTTPDocumentNotModified
|
@@ -22,6 +22,7 @@ The XCAPClient library includes custom Ruby exceptions. All these exceptions inh
|
|
22
22
|
* HTTPWrongContentType
|
23
23
|
* HTTPBadRequest
|
24
24
|
* HTTPServerError
|
25
|
+
* HTTPNotImplemented
|
25
26
|
* HTTPUnknownError
|
26
27
|
* XMLParsingError
|
27
28
|
|
@@ -109,7 +110,12 @@ The server replied "400 Bad Request". The request was malformed.
|
|
109
110
|
|
110
111
|
==== HTTPServerError < HTTPError
|
111
112
|
|
112
|
-
The server replied "500 Internal Server Error". The server encountered an unexpected condition which prevented it from fulfilling the request.
|
113
|
+
The server replied "500 Internal Server Error" or "503 Service Unavailable". The server encountered an unexpected condition which prevented it from fulfilling the request.
|
114
|
+
|
115
|
+
|
116
|
+
==== HTTPNotImplemented < HTTPError
|
117
|
+
|
118
|
+
The server replied "501 Not Implemented". The server doesn't implement the request method.
|
113
119
|
|
114
120
|
|
115
121
|
==== HTTPUnknownError < HTTPError
|
data/README.rdoc
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= XCAPClient
|
1
|
+
= XCAPClient (version 1.1.X)
|
2
2
|
|
3
3
|
* http://dev.sipdoc.net/projects/ruby-xcapclient/wiki/
|
4
4
|
* http://rubyforge.org/projects/xcapclient/
|
@@ -15,11 +15,11 @@ XCAPClient library implements the XCAP protocol in client side, allowing the app
|
|
15
15
|
|
16
16
|
The library implements the following features:
|
17
17
|
|
18
|
-
* Fetch, create/replace and delete a document.
|
19
|
-
* Fetch, create/replace and delete a
|
20
|
-
* Fetch, create/replace and delete
|
18
|
+
* Fetch, create/replace and delete a XML document.
|
19
|
+
* Fetch, create/replace and delete a XML node.
|
20
|
+
* Fetch, create/replace and delete a XML node attribute.
|
21
21
|
* Full configurable parameters allowing customized fields for each XCAP application, such auid, XML namespace, MIME-Type, scope (:user or :global) and default document name ("index" if not set).
|
22
|
-
* Fetch the namespaces and prefixes of a document node as they are used in the server.
|
22
|
+
* Fetch the namespaces and prefixes of a document/node node as they are used in the server.
|
23
23
|
* Manage of multiple documents per XCAP application.
|
24
24
|
* Fetch the XCAP server auids, extensions and namespaces ("xcap-caps" application).
|
25
25
|
* SSL.
|
@@ -115,20 +115,27 @@ By default, the methods accesing the XCAP server include the ETag if it's availa
|
|
115
115
|
@xcapclient.put("pres-rules", "vacation-rules")
|
116
116
|
|
117
117
|
|
118
|
-
==== Fetch
|
118
|
+
==== Fetch a node (with "id" = "sip:alice@example.org")
|
119
119
|
|
120
|
-
@xcapclient.
|
120
|
+
@xcapclient.get_node("pres-rules", nil,
|
121
121
|
'/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:alice@example.org"]',
|
122
122
|
{"cp" => "urn:ietf:params:xml:ns:common-policy"})
|
123
123
|
|
124
124
|
|
125
|
-
==== Add a new
|
125
|
+
==== Add a new node (a new allowed user in "pres-rules" document)
|
126
126
|
|
127
|
-
@xcapclient.
|
127
|
+
@xcapclient.put_node("pres-rules", nil,
|
128
128
|
'/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:bob@example.org"]',
|
129
129
|
'<cp:one id="sip:bob@example.org"/>',
|
130
130
|
{"cp"=>"urn:ietf:params:xml:ns:common-policy"})
|
131
131
|
|
132
|
+
==== Fetch a node attribute (node "name" from node with "id" = "sip:alice@example.org")
|
133
|
+
|
134
|
+
@xcapclient.get_attribute("pres-rules", nil,
|
135
|
+
'/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:alice@example.org"]',
|
136
|
+
"name",
|
137
|
+
{"cp" => "urn:ietf:params:xml:ns:common-policy"})
|
138
|
+
|
132
139
|
|
133
140
|
== ToDo
|
134
141
|
|
data/lib/xcapclient/client.rb
CHANGED
@@ -40,7 +40,7 @@ module XCAPClient
|
|
40
40
|
USER_AGENT = "Ruby-XCAPClient"
|
41
41
|
COMMON_HEADERS = {
|
42
42
|
"User-Agent" => "#{USER_AGENT}/#{VERSION}",
|
43
|
-
"Connection" => "
|
43
|
+
"Connection" => "open"
|
44
44
|
}
|
45
45
|
GLOBAL_XUI = "global"
|
46
46
|
XCAP_CAPS_XMLNS = "urn:ietf:params:xml:ns:xcap-caps"
|
@@ -247,18 +247,18 @@ module XCAPClient
|
|
247
247
|
end
|
248
248
|
|
249
249
|
|
250
|
-
# Fetch
|
250
|
+
# Fetch a node from the document stored in the server.
|
251
251
|
#
|
252
|
-
# Example:
|
252
|
+
# Example, fetching the node with "id" = "sip:alice@example.org":
|
253
253
|
#
|
254
|
-
# @xcapclient.
|
254
|
+
# @xcapclient.get_node("pres-rules", nil,
|
255
255
|
# '/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:alice@example.org"]',
|
256
256
|
# {"cp" => "urn:ietf:params:xml:ns:common-policy"})
|
257
257
|
#
|
258
258
|
# If success:
|
259
|
-
# * The method returns the
|
259
|
+
# * The method returns the node as a String.
|
260
260
|
#
|
261
|
-
def
|
261
|
+
def get_node(auid, document, selector, xml_namespaces=nil, check_etag=true)
|
262
262
|
|
263
263
|
application, document = get_app_doc(auid, document)
|
264
264
|
response = send_request(:get, application, document, selector, nil, xml_namespaces, nil, check_etag)
|
@@ -270,11 +270,11 @@ module XCAPClient
|
|
270
270
|
|
271
271
|
end
|
272
272
|
|
273
|
-
# Create/replace
|
273
|
+
# Create/replace a node in the document stored in the server.
|
274
274
|
#
|
275
|
-
# Example:
|
275
|
+
# Example, creating/replacing the node with "id" = "sip:alice@example.org":
|
276
276
|
#
|
277
|
-
# @xcapclient.
|
277
|
+
# @xcapclient.put_node("pres-rules", nil,
|
278
278
|
# '/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:bob@example.org"]',
|
279
279
|
# '<cp:one id="sip:bob@example.org"/>',
|
280
280
|
# {"cp"=>"urn:ietf:params:xml:ns:common-policy"})
|
@@ -283,7 +283,7 @@ module XCAPClient
|
|
283
283
|
# * The method returns true.
|
284
284
|
# * Local plain document and ETag are deleted (as the document has changed).
|
285
285
|
#
|
286
|
-
def
|
286
|
+
def put_node(auid, document, selector, selector_body, xml_namespaces=nil, check_etag=true)
|
287
287
|
|
288
288
|
application, document = get_app_doc(auid, document)
|
289
289
|
response = send_request(:put, application, document, selector, selector_body, xml_namespaces, "application/xcap-el+xml", check_etag)
|
@@ -297,11 +297,11 @@ module XCAPClient
|
|
297
297
|
end
|
298
298
|
|
299
299
|
|
300
|
-
# Delete
|
300
|
+
# Delete a node in the document stored in the server.
|
301
301
|
#
|
302
|
-
# Example:
|
302
|
+
# Example, deleting the node with "id" = "sip:alice@example.org":
|
303
303
|
#
|
304
|
-
# @xcapclient.
|
304
|
+
# @xcapclient.delete_node("pres-rules", nil,
|
305
305
|
# '/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:alice@example.org"]',
|
306
306
|
# {"cp" => "urn:ietf:params:xml:ns:common-policy"})
|
307
307
|
#
|
@@ -309,7 +309,7 @@ module XCAPClient
|
|
309
309
|
# * The method returns true.
|
310
310
|
# * Local plain document and ETag are deleted (as the document has changed).
|
311
311
|
#
|
312
|
-
def
|
312
|
+
def delete_node(auid, document, selector, xml_namespaces=nil, check_etag=true)
|
313
313
|
|
314
314
|
application, document = get_app_doc(auid, document)
|
315
315
|
response = send_request(:delete, application, document, selector, nil, xml_namespaces, nil, check_etag)
|
@@ -323,15 +323,101 @@ module XCAPClient
|
|
323
323
|
end
|
324
324
|
|
325
325
|
|
326
|
-
# Fetch the
|
326
|
+
# Fetch a node attribute from the document stored in the server.
|
327
|
+
#
|
328
|
+
# Example, fetching the "name" attribute of the node with
|
329
|
+
# "id" = "sip:alice@example.org":
|
330
|
+
#
|
331
|
+
# @xcapclient.get_attribute("pres-rules", nil,
|
332
|
+
# '/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:alice@example.org"]',
|
333
|
+
# "name",
|
334
|
+
# {"cp" => "urn:ietf:params:xml:ns:common-policy"})
|
335
|
+
#
|
336
|
+
# If success:
|
337
|
+
# * The method returns the attribute as a String.
|
338
|
+
#
|
339
|
+
def get_attribute(auid, document, selector, attribute_name, xml_namespaces=nil, check_etag=true)
|
340
|
+
|
341
|
+
application, document = get_app_doc(auid, document)
|
342
|
+
response = send_request(:get, application, document, selector + "/@#{attribute_name}", nil, xml_namespaces, nil, check_etag)
|
343
|
+
|
344
|
+
# Check Content-Type.
|
345
|
+
check_content_type(response, "application/xcap-att+xml")
|
346
|
+
|
347
|
+
return response.body.content
|
348
|
+
|
349
|
+
end
|
350
|
+
|
351
|
+
|
352
|
+
# Create/replace a node attribute in the document stored in the server.
|
353
|
+
#
|
354
|
+
# Example, creating/replacing the "name" attribute of the node with
|
355
|
+
# "id" = "sip:alice@example.org" with new value "Alice Yeah":
|
356
|
+
#
|
357
|
+
# @xcapclient.put_attribute("pres-rules", nil,
|
358
|
+
# '/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:alice@example.org"]',
|
359
|
+
# "name",
|
360
|
+
# "Alice Yeah",
|
361
|
+
# {"cp" => "urn:ietf:params:xml:ns:common-policy"})
|
327
362
|
#
|
328
|
-
# If
|
363
|
+
# If success:
|
364
|
+
# * The method returns true.
|
365
|
+
# * Local plain document and ETag are deleted (as the document has changed).
|
366
|
+
#
|
367
|
+
def put_attribute(auid, document, selector, attribute_name, attribute_value, xml_namespaces=nil, check_etag=true)
|
368
|
+
|
369
|
+
application, document = get_app_doc(auid, document)
|
370
|
+
response = send_request(:put, application, document, selector + "/@#{attribute_name}", attribute_value, xml_namespaces, "application/xcap-att+xml", check_etag)
|
371
|
+
|
372
|
+
# Reset local plain document and ETag as we have modified it.
|
373
|
+
document.plain = nil
|
374
|
+
document.etag = nil
|
375
|
+
|
376
|
+
return true
|
377
|
+
|
378
|
+
end
|
379
|
+
|
380
|
+
|
381
|
+
# Delete a node attribute in the document stored in the server.
|
382
|
+
#
|
383
|
+
# Example, deleting the "name" attribute of the node with
|
384
|
+
# "id" = "sip:alice@example.org":
|
385
|
+
#
|
386
|
+
# @xcapclient.delete_attribute("pres-rules", nil,
|
387
|
+
# '/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:alice@example.org"]',
|
388
|
+
# "name",
|
389
|
+
# {"cp" => "urn:ietf:params:xml:ns:common-policy"})
|
390
|
+
#
|
391
|
+
# If success:
|
392
|
+
# * The method returns true.
|
393
|
+
# * Local plain document and ETag are deleted (as the document has changed).
|
394
|
+
#
|
395
|
+
def delete_attribute(auid, document, selector, attribute_name, xml_namespaces=nil, check_etag=true)
|
396
|
+
|
397
|
+
application, document = get_app_doc(auid, document)
|
398
|
+
response = send_request(:delete, application, document, selector + "/@#{attribute_name}", nil, xml_namespaces, nil, check_etag)
|
399
|
+
|
400
|
+
# Reset local plain document and ETag as we have modified it
|
401
|
+
document.plain = nil
|
402
|
+
document.etag = nil
|
403
|
+
|
404
|
+
return true
|
405
|
+
|
406
|
+
end
|
407
|
+
|
408
|
+
|
409
|
+
# Fetch the namespace prefixes of a node.
|
410
|
+
#
|
411
|
+
# If the client wants to create/replace a node, the body of the PUT
|
412
|
+
# request must use the same namespaces and prefixes as those used in
|
413
|
+
# the document stored in the server. This methods allows the client
|
414
|
+
# to fetch these namespaces and prefixes.
|
329
415
|
#
|
330
416
|
# Related documentation: {RFC 4825 section 7.10}[http://tools.ietf.org/html/rfc4825#section-7.10], {RFC 4825 section 10}[http://tools.ietf.org/html/rfc4825#section-10]
|
331
417
|
#
|
332
418
|
# Example:
|
333
419
|
#
|
334
|
-
# @xcapclient.
|
420
|
+
# @xcapclient.get_node_namespaces("pres-rules", nil,
|
335
421
|
# '/ccpp:ruleset/ccpp:rule[@id="pres_whitelist"]',
|
336
422
|
# { "ccpp" => "urn:ietf:params:xml:ns:common-policy" })
|
337
423
|
#
|
@@ -347,7 +433,7 @@ module XCAPClient
|
|
347
433
|
# {"pr"=>"urn:ietf:params:xml:ns:pres-rules", "cp"=>"urn:ietf:params:xml:ns:common-policy"}
|
348
434
|
# If not, the method returns the response body as a String and the application must parse it.
|
349
435
|
#
|
350
|
-
def
|
436
|
+
def get_node_namespaces(auid, document, selector, xml_namespaces=nil, check_etag=true)
|
351
437
|
|
352
438
|
application, document = get_app_doc(auid, document)
|
353
439
|
response = send_request(:get, application, document, selector + "/namespace::*", nil, xml_namespaces, nil, check_etag)
|
@@ -373,7 +459,7 @@ module XCAPClient
|
|
373
459
|
#
|
374
460
|
def get_xcap_auids
|
375
461
|
|
376
|
-
body =
|
462
|
+
body = get_node("xcap-caps", nil, '/xcap-caps/auids')
|
377
463
|
|
378
464
|
return case NOKOGIRI_INSTALLED
|
379
465
|
when true
|
@@ -391,7 +477,7 @@ module XCAPClient
|
|
391
477
|
#
|
392
478
|
def get_xcap_extensions
|
393
479
|
|
394
|
-
body =
|
480
|
+
body = get_node("xcap-caps", nil, '/xcap-caps/extensions')
|
395
481
|
|
396
482
|
return case NOKOGIRI_INSTALLED
|
397
483
|
when true
|
@@ -409,7 +495,7 @@ module XCAPClient
|
|
409
495
|
#
|
410
496
|
def get_xcap_namespaces
|
411
497
|
|
412
|
-
body =
|
498
|
+
body = get_node("xcap-caps", nil, '/xcap-caps/namespaces')
|
413
499
|
|
414
500
|
return case NOKOGIRI_INSTALLED
|
415
501
|
when true
|
@@ -498,7 +584,7 @@ module XCAPClient
|
|
498
584
|
|
499
585
|
# Body (just in case of PUT).
|
500
586
|
body = ( selector_body || document.plain || nil ) if method == :put
|
501
|
-
raise ArgumentError, "PUT body
|
587
|
+
raise ArgumentError, "PUT body must be a String" unless String === body if method == :put
|
502
588
|
|
503
589
|
begin
|
504
590
|
response = @http_client.request(method, uri, nil, body, extra_headers)
|
@@ -532,11 +618,14 @@ module XCAPClient
|
|
532
618
|
when "412"
|
533
619
|
raise HTTPNoMatchingETag
|
534
620
|
|
535
|
-
when
|
621
|
+
when /^50[03]$/
|
536
622
|
raise HTTPServerError
|
623
|
+
|
624
|
+
whe "501"
|
625
|
+
raise HTTPNotImplemented
|
537
626
|
|
538
627
|
else
|
539
|
-
raise HTTPUnknownError, "Unknown
|
628
|
+
raise HTTPUnknownError, "Unknown Error [#{response.status} #{response.reason}]"
|
540
629
|
|
541
630
|
end
|
542
631
|
|
data/lib/xcapclient/errors.rb
CHANGED
@@ -15,6 +15,7 @@ module XCAPClient
|
|
15
15
|
class HTTPWrongContentType < HTTPError ; end
|
16
16
|
class HTTPBadRequest < HTTPError ; end
|
17
17
|
class HTTPServerError < HTTPError ; end
|
18
|
+
class HTTPNotImplemented < HTTPError ; end
|
18
19
|
class HTTPUnknownError < HTTPError ; end
|
19
20
|
class XMLParsingError < XCAPClientError ; end
|
20
21
|
|
data/lib/xcapclient.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xcapclient
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "1.
|
4
|
+
version: "1.1"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "I\xC3\xB1aki Baz Castillo"
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-11-09 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -44,11 +44,13 @@ files:
|
|
44
44
|
- README.rdoc
|
45
45
|
- ERRORS.rdoc
|
46
46
|
has_rdoc: true
|
47
|
-
homepage: http://dev.sipdoc.net/projects/ruby-
|
47
|
+
homepage: http://dev.sipdoc.net/projects/ruby-xcapclient/wiki/
|
48
48
|
post_install_message:
|
49
49
|
rdoc_options:
|
50
50
|
- --main
|
51
51
|
- README.rdoc
|
52
|
+
- --title
|
53
|
+
- XCAPClient Documentation
|
52
54
|
require_paths:
|
53
55
|
- lib
|
54
56
|
required_ruby_version: !ruby/object:Gem::Requirement
|