File Coverage

blib/lib/DJabberd/Stanza.pm
Criterion Covered Total %
statement 12 83 14.4
branch 0 26 0.0
condition 0 9 0.0
subroutine 4 25 16.0
pod 0 18 0.0
total 16 161 9.9


line stmt bran cond sub pod time code
1             package DJabberd::Stanza;
2 1     1   27361 use strict;
  1         3  
  1         42  
3 1     1   5 use base qw(DJabberd::XMLElement);
  1         2  
  1         687  
4 1     1   10 use Carp qw(croak);
  1         2  
  1         95  
5             use fields (
6 1         11 'connection', # Store the connection the stanza came in on so we can respond.
7             # may be undef, as it's a weakref. if you want to mess with the
8             # structure, you can't do so unless you're the owner, so clone
9             # it first otherwise.
10             '_memo_tojid', # memoized to jid
11             '_memo_fromjid', # memoized from jid
12 1     1   5 );
  1         13  
13              
14             sub downbless {
15 0     0 0   my $class = shift;
16 0 0         if (ref $_[0]) {
17 0           my ($self, $conn) = @_;
18 0           my $new = fields::new($class);
19 0           %$new = %$self; # copy fields
20 0 0         if ($conn) {
21 0           $new->{connection} = $conn;
22 0           Scalar::Util::weaken($new->{connection});
23             }
24 0           return $new;
25             } else {
26 0           croak("Bogus use of downbless.");
27             }
28              
29             }
30              
31             sub as_summary {
32 0     0 0   my $self = shift;
33 0           return "[Stanza of type " . $self->element_name . " to " . $self->to_jid->as_string . "]";
34             }
35              
36             sub on_recv_from_server {
37 0     0 0   my ($self, $conn) = @_;
38 0           $self->deliver($conn->vhost);
39             }
40              
41             sub process {
42 0     0 0   my ($self, $conn) = @_;
43 0           die "$self ->process not implemented\n";
44             }
45              
46             sub connection {
47 0     0 0   my $self = shift;
48 0           return $self->{connection};
49             }
50              
51             sub set_connection {
52 0     0 0   my ($self, $conn) = @_;
53 0           $self->{connection} = $conn;
54             }
55              
56             # at this point, it's assumed the stanza has passed filtering checks,
57             # and should be delivered.
58             sub deliver {
59 0     0 0   my ($stanza, $arg) = @_;
60              
61             # arg can be a connection, vhost, or nothing. TODO: kinda ghetto. fix callers?
62 0           my $vhost;
63 0 0         if (UNIVERSAL::isa($arg, "DJabberd::VHost")) {
    0          
    0          
64 0           $vhost = $arg;
65             } elsif (UNIVERSAL::isa($arg, "DJabberd::Connection")) {
66 0           $vhost = $arg->vhost;
67             } elsif ($stanza->{connection}) {
68 0           $vhost = $stanza->{connection}->vhost;
69             }
70 0 0         Carp::croak("Can't determine vhost delivering: " . $stanza->as_xml) unless $vhost;
71              
72             $vhost->hook_chain_fast("deliver",
73             [ $stanza ],
74             {
75 0     0     delivered => sub { },
76             # FIXME: in future, this should note deliver was
77             # complete and the next message to this jid should be dequeued and
78             # subsequently delivered. (in order deliver)
79             error => sub {
80 0     0     my $reason = $_[1];
81 0           $stanza->delivery_failure($vhost, $reason);
82             },
83             },
84             sub {
85 0     0     $stanza->delivery_failure($vhost);
86 0           });
87             }
88              
89             # by default, stanzas need to and from coming from a server
90             sub acceptable_from_server {
91 0     0 0   my ($self, $conn) = @_; # where $conn is a serverin connection
92 0           my ($to, $from) = ($self->to_jid, $self->from_jid);
93 0 0 0       return 0 unless $to && $from;
94 0 0         return 0 unless $conn->peer_domain_is_verified($from->domain);
95             #return 0 unless $conn->vhost; FIXME? yes?
96 0           return 1;
97             }
98              
99             sub delivery_failure {
100 0     0 0   my ($self, $vh, $reason) = @_;
101             #warn "$self has no ->delivery_failure method implemented\n";
102             }
103              
104             sub to {
105 0     0 0   my DJabberd::Stanza $self = shift;
106 0           return $self->{attrs}{"{}to"};
107             }
108              
109             sub from {
110 0     0 0   my DJabberd::Stanza $self = shift;
111 0           return $self->{attrs}{"{}from"};
112             }
113              
114             sub to_jid {
115 0     0 0   my DJabberd::Stanza $self = shift;
116 0   0       return $self->{_memo_tojid} ||= DJabberd::JID->new($self->{attrs}{"{}to"});
117             }
118              
119             sub from_jid {
120 0     0 0   my DJabberd::Stanza $self = shift;
121 0   0       return $self->{_memo_fromjid} ||= DJabberd::JID->new($self->{attrs}{"{}from"});
122             }
123              
124             sub set_from {
125             #my ($self, $from) = @_;
126 0     0 0   my DJabberd::Stanza $self = $_[0];
127 0           $self->{_memo_fromjid} = undef;
128 0 0         $self->{attrs}{"{}from"} = ref $_[1] ? $_[1]->as_string : $_[1];
129             }
130              
131             sub set_to {
132             #my ($self, $to) = @_;
133 0     0 0   my DJabberd::Stanza $self = $_[0];
134 0           $self->{_memo_tojid} = undef;
135 0 0         $self->{attrs}{"{}to"} = ref $_[1] ? $_[1]->as_string : $_[1];
136             }
137              
138             sub deliver_when_unavailable {
139 0     0 0   0;
140             }
141              
142             sub make_response {
143 0     0 0   my ($self) = @_;
144              
145             # Common to all stanzas is a switching of the from/to addresses.
146 0           my $response = $self->clone;
147 0           my $from = $self->from;
148 0           my $to = $self->to;
149              
150 0           $response->set_to($from);
151 0 0         $to ? $response->set_from($to) : delete($response->attrs->{"{}from"});
152            
153 0           $response->set_raw("");
154              
155 0           return $response;
156             }
157              
158             sub make_error_response {
159 0     0 0   my ($self, $code, $type, $error) = @_;
160            
161 0           my $response = $self->clone;
162 0           my $from = $self->from;
163 0           my $to = $self->to;
164              
165 0           $response->set_to($from);
166 0 0         $to ? $response->set_from($to) : delete($response->attrs->{"{}from"});
167              
168 0 0         my $error_elem = new DJabberd::XMLElement(
169             "jabber:server",
170             "error",
171             {
172             "{}code" => $code,
173             "{}type" => $type,
174             },
175             [
176             ref $error ? $error : new DJabberd::XMLElement("urn:ietf:params:xml:ns:xmpp-stanzas", $error, {}, []),
177             ],
178             );
179              
180 0           $response->attrs->{"{}type"} = "error";
181 0           $response->push_child($error_elem);
182            
183 0           return $response;
184             }
185              
186             1;