File Coverage

blib/lib/SOAP/Transport/JABBER.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             # ======================================================================
2             #
3             # Copyright (C) 2000-2001 Paul Kulchenko (paulclinger@yahoo.com)
4             # SOAP::Lite is free software; you can redistribute it
5             # and/or modify it under the same terms as Perl itself.
6             #
7             # $Id: JABBER.pm 353 2010-03-17 21:08:34Z kutterma $
8             #
9             # ======================================================================
10              
11             package SOAP::Transport::JABBER;
12              
13 1     1   862 use strict;
  1         2  
  1         40  
14 1     1   5 use warnings;
  1         2  
  1         56  
15              
16             our $VERSION = 0.713;
17              
18 1     1   482 use Net::Jabber 1.0021 qw(Client);
  0            
  0            
19             use URI::Escape;
20             use URI;
21              
22             my $NAMESPACE = "http://namespaces.soaplite.com/transport/jabber";
23              
24             {
25             no warnings qw(redefine);
26             # fix problem with printData in 1.0021
27             *Net::Jabber::printData = sub { 'nothing' }
28             if Net::Jabber->VERSION == 1.0021;
29              
30             # fix problem with Unicode encoding in EscapeXML.
31             # Jabber ALWAYS converts latin to utf8
32             *Net::Jabber::EscapeXML = *Net::Jabber::EscapeXML = # that's Jabber 1.0021
33             *XML::Stream::EscapeXML =
34             *XML::Stream::EscapeXML = # that's Jabber 1.0022
35             \&SOAP::Utils::encode_data;
36              
37             # There is also an error in XML::Stream::UnescapeXML 1.12, but
38             # we can't do anything there, except hack it also :(
39             }
40              
41             # ======================================================================
42              
43             package URI::jabber; # ok, lets do 'jabber://' scheme
44             require URI::_server;
45             require URI::_userpass;
46             @URI::jabber::ISA = qw(URI::_server URI::_userpass);
47              
48             # jabber://soaplite_client:soapliteclient@jabber.org:5222/soaplite_server@jabber.org/Home
49             # ^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^
50              
51             # ======================================================================
52              
53             package SOAP::Transport::JABBER::Query;
54             our $VERSION = 0.713;
55             sub new {
56             my $proto = shift;
57             bless {} => ref($proto) || $proto;
58             }
59              
60             sub SetPayload {
61             shift;
62             Net::Jabber::SetXMLData( "single", shift->{QUERY}, "payload", shift, {} );
63             }
64              
65             sub GetPayload {
66             shift;
67             Net::Jabber::GetXMLData( "value", shift->{QUERY}, "payload", "" );
68             }
69              
70             # ======================================================================
71              
72             package SOAP::Transport::JABBER::Client;
73             our $VERSION = 0.713;
74             use vars qw(@ISA);
75             @ISA = qw(SOAP::Client Net::Jabber::Client);
76              
77             sub DESTROY { SOAP::Trace::objects('()') }
78              
79             sub new {
80             my $self = shift;
81              
82             unless ( ref $self ) {
83             my $class = ref($self) || $self;
84             my ( @params, @methods );
85             while (@_) {
86             $class->can( $_[0] )
87             ? push( @methods, shift() => shift )
88             : push( @params, shift );
89             }
90             $self = $class->SUPER::new(@params);
91             while (@methods) {
92             my ( $method, $params ) = splice( @methods, 0, 2 );
93             $self->$method( ref $params eq 'ARRAY' ? @$params : $params );
94             }
95             SOAP::Trace::objects('()');
96             }
97             return $self;
98             }
99              
100             sub endpoint {
101             my $self = shift;
102              
103             return $self->SUPER::endpoint unless @_;
104              
105             my $endpoint = shift;
106              
107             # nothing to do if new endpoint is the same as current one
108             return $self
109             if $self->SUPER::endpoint && $self->SUPER::endpoint eq $endpoint;
110              
111             my $uri = URI->new($endpoint);
112             my ( $undef, $to, $resource ) = split m!/!, $uri->path, 3;
113             $self->Connect(
114             hostname => $uri->host,
115             port => $uri->port,
116             ) or Carp::croak "Can't connect to @{[$uri->host_port]}: $!";
117              
118             my @result = $self->AuthSend(
119             username => $uri->user,
120             password => $uri->password,
121             resource => 'soapliteClient',
122             );
123             $result[0] eq "ok"
124             or Carp::croak "Can't authenticate to @{[$uri->host_port]}: @result";
125              
126             $self->AddDelegate(
127             namespace => $NAMESPACE,
128             parent => 'Net::Jabber::Query',
129             parenttype => 'query',
130             delegate => 'SOAP::Transport::JABBER::Query',
131             );
132              
133             # Get roster and announce presence
134             $self->RosterGet();
135             $self->PresenceSend();
136              
137             $self->SUPER::endpoint($endpoint);
138             }
139              
140             sub send_receive {
141             my ( $self, %parameters ) = @_;
142             my ( $envelope, $endpoint, $encoding ) =
143             @parameters{qw(envelope endpoint encoding)};
144              
145             $self->endpoint( $endpoint ||= $self->endpoint );
146              
147             my ( $undef, $to, $resource ) = split m!/!, URI->new($endpoint)->path, 3;
148              
149             # Create a Jabber info/query message
150             my $iq = new Net::Jabber::IQ();
151             $iq->SetIQ(
152             type => 'set',
153             to => join '/',
154             $to => $resource || 'soapliteServer',
155             );
156             my $query = $iq->NewQuery($NAMESPACE);
157             $query->SetPayload($envelope);
158              
159             SOAP::Trace::debug($envelope);
160              
161             my $iq_rcvd = $self->SendAndReceiveWithID($iq);
162             my ($query_rcvd) = $iq_rcvd->GetQuery($NAMESPACE)
163             if $iq_rcvd; # expect only one
164             my $msg = $query_rcvd->GetPayload() if $query_rcvd;
165              
166             SOAP::Trace::debug($msg);
167              
168             my $code = $self->GetErrorCode();
169              
170             $self->code($code);
171             $self->message($code);
172             $self->is_success( !defined $code || $code eq '' );
173             $self->status($code);
174              
175             return $msg;
176             }
177              
178             # ======================================================================
179              
180             package SOAP::Transport::JABBER::Server;
181             our $VERSION = 0.713;
182             use Carp ();
183             use vars qw(@ISA $AUTOLOAD);
184             @ISA = qw(SOAP::Server);
185              
186             sub new {
187             my $self = shift;
188              
189             unless ( ref $self ) {
190             my $class = ref($self) || $self;
191             my $uri = URI->new(shift);
192             $self = $class->SUPER::new(@_);
193              
194             $self->{_jabberserver} = Net::Jabber::Client->new;
195             $self->{_jabberserver}->Connect(
196             hostname => $uri->host,
197             port => $uri->port,
198             ) or Carp::croak "Can't connect to @{[$uri->host_port]}: $!";
199              
200             my ( $undef, $resource ) = split m!/!, $uri->path, 2;
201             my @result = $self->AuthSend(
202             username => $uri->user,
203             password => $uri->password,
204             resource => $resource || 'soapliteServer',
205             );
206             $result[0] eq "ok"
207             or Carp::croak
208             "Can't authenticate to @{[$uri->host_port]}: @result";
209              
210             $self->{_jabberserver}->SetCallBacks(
211             iq => sub {
212             shift;
213             my $iq = new Net::Jabber::IQ(@_);
214              
215             my ($query) = $iq->GetQuery($NAMESPACE); # expect only one
216             my $request = $query->GetPayload();
217              
218             SOAP::Trace::debug($request);
219              
220             # Set up response
221             my $reply = $iq->Reply;
222             my $x = $reply->NewQuery($NAMESPACE);
223              
224             my $response = $self->SUPER::handle($request);
225             $x->SetPayload($response);
226              
227             # Send response
228             $self->{_jabberserver}->Send($reply);
229             } );
230              
231             $self->AddDelegate(
232             namespace => $NAMESPACE,
233             parent => 'Net::Jabber::Query',
234             parenttype => 'query',
235             delegate => 'SOAP::Transport::JABBER::Query',
236             );
237              
238             $self->RosterGet();
239             $self->PresenceSend();
240             }
241             return $self;
242             }
243              
244             sub AUTOLOAD {
245             my $method = substr( $AUTOLOAD, rindex( $AUTOLOAD, '::' ) + 2 );
246             return if $method eq 'DESTROY';
247              
248             no strict 'refs';
249             *$AUTOLOAD = sub { shift->{_jabberserver}->$method(@_) };
250             goto &$AUTOLOAD;
251             }
252              
253             sub handle {
254             shift->Process();
255             }
256              
257             # ======================================================================
258              
259             1;
260              
261             __END__