line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/bin/perl |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package XCAP::Client; |
4
|
|
|
|
|
|
|
|
5
|
1
|
|
|
1
|
|
2535
|
use Moose; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
use Moose::Util::TypeConstraints; |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
use Data::Validate::URI qw(is_uri); |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
use XCAP::Client::Connection; |
11
|
|
|
|
|
|
|
use XCAP::Client::Document; |
12
|
|
|
|
|
|
|
use XCAP::Client::Element; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
our $VERSION = "0.07"; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
has 'connection' => ( |
17
|
|
|
|
|
|
|
is => 'ro', |
18
|
|
|
|
|
|
|
isa => 'Object', |
19
|
|
|
|
|
|
|
lazy => 1, |
20
|
|
|
|
|
|
|
default => sub { |
21
|
|
|
|
|
|
|
my $self = shift; |
22
|
|
|
|
|
|
|
XCAP::Client::Connection->new( |
23
|
|
|
|
|
|
|
uri => $self->uri, |
24
|
|
|
|
|
|
|
auth_realm => $self->auth_realm, |
25
|
|
|
|
|
|
|
auth_username => $self->auth_username, |
26
|
|
|
|
|
|
|
auth_password => $self->auth_password |
27
|
|
|
|
|
|
|
) |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
); |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
has 'uri' => ( |
32
|
|
|
|
|
|
|
is => 'rw', |
33
|
|
|
|
|
|
|
isa => 'Str', |
34
|
|
|
|
|
|
|
lazy => 1, |
35
|
|
|
|
|
|
|
default => sub { |
36
|
|
|
|
|
|
|
my $self = shift; |
37
|
|
|
|
|
|
|
join ('/', $self->xcap_root, $self->application, $self->tree, |
38
|
|
|
|
|
|
|
$self->user, $self->filename); |
39
|
|
|
|
|
|
|
}, |
40
|
|
|
|
|
|
|
); |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=head1 NAME |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
XCAP::Client - XCAP client protocol (RFC 4825). |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=head1 SYNOPSIS |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
use XCAP::Client; |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
my $xcap_client = new XCAP::Client( |
51
|
|
|
|
|
|
|
xcap_root => "https://my.xcapserver.org/xcap-root", |
52
|
|
|
|
|
|
|
user => "sip:foo@domain.org", |
53
|
|
|
|
|
|
|
auth_username => "foo", |
54
|
|
|
|
|
|
|
auth_password => "bar", |
55
|
|
|
|
|
|
|
); |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
# Set the document. |
58
|
|
|
|
|
|
|
$xcap_client->application('pres-rules'); |
59
|
|
|
|
|
|
|
$xcap_client->filename('index'); |
60
|
|
|
|
|
|
|
$xcap_client->tree('user'); |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# Delete |
63
|
|
|
|
|
|
|
$xcap_client->document->delete; |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# Fetch pres-rules document. |
66
|
|
|
|
|
|
|
$xcap_client->document->fetch(); |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
# If you want to create or replace. |
69
|
|
|
|
|
|
|
$xcap_client->document->content($xml_content); |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
# Create a new document. |
72
|
|
|
|
|
|
|
$xcap_client->document->create; |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
# Replace. |
75
|
|
|
|
|
|
|
$xcap_client->document->replace; |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=head1 DESCRIPTION |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
XCAP (RFC 4825) 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. |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
XCAPClient library implements the XCAP protocol in client side, allowing the applications to get, store, modify and delete XML documents in the server. |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
The module implements the following features: |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
* Fetch, create/replace and delete a document. |
87
|
|
|
|
|
|
|
* Parameters allowing customized fields for each XCAP application. |
88
|
|
|
|
|
|
|
* Manage of multiple documents per XCAP application. |
89
|
|
|
|
|
|
|
* SSL support. |
90
|
|
|
|
|
|
|
* Exception for each HTTP error response. |
91
|
|
|
|
|
|
|
* Digest and Basic HTTP authentication. |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
Todo: |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
* Fetch, create/replace and delete a document element (XML node) |
96
|
|
|
|
|
|
|
* Fetch, create/replace and delete an element attribute. |
97
|
|
|
|
|
|
|
* Fetch the XCAP server auids, extensions and namespaces. |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=head2 xcap_root |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
It's a context that contains all the documents across all application usages and users that are managed by the server. |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
The root of the XCAP hierarchy is called the XCAP root. It defines the context in which all other resources exist. The XCAP root is represented with an HTTP URI, called the XCAP Root URI. This URI is a valid HTTP URI; however, it doesn't point to any resource that actually exists on the server. Its purpose is to identify the root of the tree within the domain where all XCAP documents are stored. |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=cut |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
subtype 'IsURI' |
110
|
|
|
|
|
|
|
=> as 'Str' |
111
|
|
|
|
|
|
|
=> where { is_uri($_) } |
112
|
|
|
|
|
|
|
=> message { "This xcap_root ($_) is not an uri!" }; |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
has 'xcap_root' => ( |
115
|
|
|
|
|
|
|
is => 'rw', |
116
|
|
|
|
|
|
|
isa => 'IsURI' |
117
|
|
|
|
|
|
|
); |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=head2 user |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
user - User that represents the parent for all documents for a particular user for a particular application usage within a particular XCAP root. |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=cut |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
subtype 'IsUserID' |
126
|
|
|
|
|
|
|
=> as 'Str' |
127
|
|
|
|
|
|
|
=> where { $_ =~ /^sip(s)?:.*@.*/ } |
128
|
|
|
|
|
|
|
=> message { 'User entry needs to be sip:foo@domain.org.' }; |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
has 'user' => ( |
131
|
|
|
|
|
|
|
is => 'rw', |
132
|
|
|
|
|
|
|
isa => 'IsUserID' |
133
|
|
|
|
|
|
|
); |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=head2 auth_realm |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
auth_realm - The HTTP authentication realm or name. |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=head2 auth_username |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
auth_username - The HTTP authentication username. |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=head2 auth_password |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
auth_password - The HTTP authentcation password. |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=cut |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
has ['auth_realm', 'auth_username', 'auth_password'] => ( |
151
|
|
|
|
|
|
|
is => 'rw', |
152
|
|
|
|
|
|
|
isa => 'Str' |
153
|
|
|
|
|
|
|
); |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=head2 application |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Application can be resource-lists, rls-services, pres-rules, pdif-manipulations or xcap-caps. (Default: pres-rules) |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=cut |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
has 'application' => ( |
162
|
|
|
|
|
|
|
is => 'rw', |
163
|
|
|
|
|
|
|
isa => enum([qw[resource-lists rls-services pres-rules pdif-manipulation watchers xcap-caps ]]), |
164
|
|
|
|
|
|
|
default => 'pres-rules' |
165
|
|
|
|
|
|
|
); |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=head2 tree |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
Tree can be users or global. (Default: users) |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=cut |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
has 'tree' => ( |
174
|
|
|
|
|
|
|
is => 'rw', |
175
|
|
|
|
|
|
|
isa => enum([qw[users global]]), |
176
|
|
|
|
|
|
|
default => 'users' |
177
|
|
|
|
|
|
|
); |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head2 filename |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
Filename. (Default: index) |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=cut |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
has 'filename' => ( |
186
|
|
|
|
|
|
|
is => 'rw', |
187
|
|
|
|
|
|
|
isa => 'Str', |
188
|
|
|
|
|
|
|
default => 'index' |
189
|
|
|
|
|
|
|
); |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=head1 METHODS |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=head2 document->[create,fetch,replace,delete] |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
You can create, fetch, replace or delete a document with this methods. To use create or delete you need to say the content of the "document->content". |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
=cut |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
has 'document' => ( |
200
|
|
|
|
|
|
|
is => 'ro', |
201
|
|
|
|
|
|
|
isa => 'Object', |
202
|
|
|
|
|
|
|
lazy => 1, |
203
|
|
|
|
|
|
|
default => sub { |
204
|
|
|
|
|
|
|
my $self = shift; |
205
|
|
|
|
|
|
|
XCAP::Client::Document->new(connection => $self->connection) } |
206
|
|
|
|
|
|
|
); |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=head2 element->[add,fetch] |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
=cut |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
has 'element' => ( |
213
|
|
|
|
|
|
|
is => 'ro', |
214
|
|
|
|
|
|
|
isa => 'Object', |
215
|
|
|
|
|
|
|
lazy => 1, |
216
|
|
|
|
|
|
|
default => sub { |
217
|
|
|
|
|
|
|
my $self = shift; |
218
|
|
|
|
|
|
|
XCAP::Client::Element->new(connection => $self->connection) } |
219
|
|
|
|
|
|
|
); |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
=head1 AUTHOR |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
Thiago Rondon <thiago@aware.com.br> |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
http://www.aware.com.br/ |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
This software is copyright (c) 2009 by Aware. |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
=cut |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
1; |
236
|
|
|
|
|
|
|
|