xcapclient 1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,172 @@
1
+ = XCAPClient
2
+
3
+ * http://dev.sipdoc.net/projects/ruby-xcapclient/wiki/
4
+ * http://rubyforge.org/projects/xcapclient/
5
+
6
+
7
+ == Description
8
+
9
+ XCAP ({RFC 4825}[http://tools.ietf.org/html/rfc4825]) is a protocol on top of HTTP which allows a client to manipulate the contents of Presence Information Data Format (PIDF) based presence documents. These documents are stored in a server in XML format and are fetched, modified, replaced or deleted by the client. The protocol allows multiple clients to manipulate the data, provided that they are authorized to do so. XCAP is already used in SIMPLE-based presence systems for manipulation of presence lists and presence authorization policies.
10
+
11
+ XCAPClient library implements the XCAP protocol in client side, allowing the applications to get, store, modify and delete XML documents in the server.
12
+
13
+
14
+ == Features
15
+
16
+ The library implements the following features:
17
+
18
+ * Fetch, create/replace and delete a document.
19
+ * Fetch, create/replace and delete a document element (XML node).
20
+ * Fetch, create/replace and delete an element attribute.
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.
23
+ * Manage of multiple documents per XCAP application.
24
+ * Fetch the XCAP server auids, extensions and namespaces ("xcap-caps" application).
25
+ * SSL.
26
+ * Digest and Basic HTTP authentication.
27
+ * Raise custom Ruby exception for each HTTP error response.
28
+
29
+
30
+ Ruby XCAPClient works in Ruby 1.8 and 1.9.
31
+
32
+
33
+ == Support
34
+
35
+ The XCAPClient mailing list is available here:
36
+
37
+ * http://rubyforge.org/mailman/listinfo/xcapclient-devel
38
+
39
+ The bug tracker is available here:
40
+
41
+ * http://dev.sipdoc.net/projects/ruby-xcapclient/issues
42
+
43
+
44
+ == API
45
+
46
+ A developer interested in this library should study the following documents:
47
+ * XCAPClient::Client
48
+ * XCAPClient::Application
49
+ * XCAPClient::Document
50
+ * ERRORS.rdoc
51
+
52
+
53
+ == Synopsis
54
+
55
+ require 'rubygems'
56
+ require 'xcapclient'
57
+
58
+
59
+ ==== Create a client
60
+
61
+ xcap_conf = {
62
+ :xcap_root => "https://xcap.myserver.org/xcap-root",
63
+ :user => "sip:me@mydomain.org",
64
+ :auth_user => "me",
65
+ :password => "xxxxxx",
66
+ :ssl_verify_cert => true
67
+ }
68
+
69
+ xcap_apps = {
70
+ "pres-rules" => {
71
+ :xmlns => "urn:ietf:params:xml:ns:pres-rules",
72
+ :mime_type => "application/auth-policy+xml",
73
+ :scope => :user,
74
+ :document_name => "index"
75
+ }
76
+ }
77
+
78
+ @xcapclient = Client.new(xcap_conf, xcap_apps)
79
+
80
+
81
+ ==== Fetch the "pres-rules" document from the server
82
+
83
+ @xcapclient.get("pres-rules")
84
+
85
+
86
+ ==== Fetch again the "pres-rules" document (now including the stored ETag)
87
+
88
+ By default, the methods accesing the XCAP server include the ETag if it's available. Since it was already got on the previous request, it's included in the new request. If the document has not been modified in the server by other client, the server replies "304 Not Modified" and the method generates a XCAPClient::XCAPClientError::HTTPDocumentNotModified exception.
89
+
90
+ begin
91
+ @xcapclient.get("pres-rules")
92
+ rescue XCAPClientError::HTTPDocumentNotModified
93
+ puts "The document has not been modified in the server."
94
+ end
95
+
96
+
97
+ ==== Replace the local document and upload it to the server
98
+
99
+ @xcapclient.application("pres-rules").document.reset
100
+ @xcapclient.application("pres-rules").document.plain = "<?xml version='1.0' encoding='UTF-8'?> ..."
101
+ @xcapclient.put("pres-rules")
102
+
103
+
104
+ ==== Delete the document in the server
105
+
106
+ @xcapclient.delete("pres-rules")
107
+
108
+
109
+ ==== Create a new document and upload it (a new "vacation-rules" document for "pres-rules" application)
110
+
111
+ my_pres_rules_2 = @xcapclient.application("pres-rules).add_document("vacation-rules")
112
+ my_pres_rules_2.plain = "<?xml version='1.0' encoding='UTF-8'?> ..."
113
+ @xcapclient.put("pres-rules", my_pres_rules_2)
114
+ # or
115
+ @xcapclient.put("pres-rules", "vacation-rules")
116
+
117
+
118
+ ==== Fetch an element
119
+
120
+ @xcapclient.get_element("pres-rules", nil,
121
+ '/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:alice@example.org"]',
122
+ {"cp" => "urn:ietf:params:xml:ns:common-policy"})
123
+
124
+
125
+ ==== Add a new element (a new allowed user in "pres-rules" document)
126
+
127
+ @xcapclient.put_element("pres-rules", nil,
128
+ '/cp:ruleset/cp:rule[@id="pres_whitelist"]/cp:conditions/cp:identity/cp:one[@id="sip:bob@example.org"]',
129
+ '<cp:one id="sip:bob@example.org"/>',
130
+ {"cp"=>"urn:ietf:params:xml:ns:common-policy"})
131
+
132
+
133
+ == ToDo
134
+
135
+ * Parse 409 error response ("application/xcap-error+xml") as it contains the explanation of the conflict ({RFC 4825 section 11}[http://tools.ietf.org/html/rfc4825#section-11]).
136
+
137
+
138
+ == Requeriments
139
+
140
+ * Ruby 1.8 or 1.9
141
+ * HTTPClient[http://dev.ctor.org/http-access2]
142
+ * Nokogiri[http://wiki.github.com/tenderlove/nokogiri] (optional, it provides some non vital features)
143
+
144
+
145
+ == Install
146
+
147
+ gem install xcapclient
148
+
149
+
150
+ == Test Unit
151
+
152
+ The GEM includes a Test Unit script located in "test" directory name "test_unit_01.rb". It performs various XCAP queries against a XCAP server using the test/PRES_RULES_EXAMPLE.xml document.
153
+
154
+ *NOTE:* You must edit the settings with your own values (edit the top lines of the script).
155
+
156
+
157
+ == License
158
+
159
+ GNU GENERAL PUBLIC LICENSE
160
+ Version 3, 29 June 2007
161
+
162
+ (see LICENSE.txt)
163
+
164
+
165
+ == Author
166
+
167
+ Iñaki Baz Castillo
168
+
169
+ * mailto:ibc@aliax.net
170
+ * http://dev.sipdoc.net
171
+
172
+
@@ -0,0 +1,62 @@
1
+ module XCAPClient
2
+
3
+ class Application
4
+
5
+ attr_reader :auid, :xmlns, :mime_type, :document_name, :scope
6
+
7
+ def initialize(auid, data={}) #:nodoc:
8
+
9
+ @auid = auid
10
+
11
+ # Check application data.
12
+ raise ConfigError, "Application `data' must be a hash ('#{@auid}')" unless (Hash === data)
13
+
14
+ @xmlns = data[:xmlns].freeze
15
+ @mime_type = data[:mime_type].freeze
16
+ @document_name = data[:document_name] || "index"
17
+ @scope = data[:scope] || :user
18
+ @scope.freeze
19
+
20
+ # Check auid.
21
+ raise ConfigError, "Application `auid' must be a non empty string ('#{@auid}')" unless String === @auid && ! @auid.empty?
22
+
23
+ # Check xmlns.
24
+ raise ConfigError, "Application `xmlns' must be a non empty string ('#{@auid}')" unless String === @xmlns && ! @xmlns.empty?
25
+
26
+ # Check mime-type.
27
+ raise ConfigError, "Application `mime_type' must be a non empty string ('#{@auid}')" unless String === @mime_type && ! @mime_type.empty?
28
+
29
+ # Check document_name
30
+ raise ConfigError, "Application `document_name' must be a non empty string ('#{@auid}')" unless String === @document_name && ! @document_name.empty?
31
+
32
+ # Check scope.
33
+ raise ConfigError, "Application `scope' must be :user or :global ('#{@auid}')" unless [:user, :global].include?(@scope)
34
+
35
+ # Create first document.
36
+ @documents = {}
37
+ @documents[@document_name] = Document.new(@document_name)
38
+
39
+ end
40
+
41
+ # Get the XCAPClient::Document with name _document_name_ within this application. If the parameter is not set, the default document is got.
42
+ #
43
+ def document(document_name=nil)
44
+ @documents[document_name || @document_name]
45
+ end
46
+
47
+ # Get an Array containing all the documents created for this application.
48
+ def documents
49
+ @documents
50
+ end
51
+
52
+ # Creates a new XCAPClient::Document for this application with name _document_name_.
53
+ def add_document(document_name)
54
+ raise DocumentError, "document '#{document_name}' already exists" if @documents[document_name]
55
+ @documents[document_name] = Document.new(document_name)
56
+
57
+ return @documents[document_name]
58
+ end
59
+
60
+ end
61
+
62
+ end