/[cvs]/nfo/perl/libs/RPC/XML/SessionServer.pm
ViewVC logotype

Annotation of /nfo/perl/libs/RPC/XML/SessionServer.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Fri Apr 4 17:19:05 2003 UTC (21 years, 3 months ago) by joko
Branch: MAIN
initial commit

1 joko 1.1 package RPC::XML::SessionServer;
2    
3     use strict;
4     use warnings;
5    
6     use base qw( RPC::XML::Server );
7    
8    
9     use Data::Dumper;
10     use shortcuts qw( make_guid );
11    
12     sub dispatch
13     {
14     my ($self, $xml) = @_;
15    
16     my ($reqobj, @data, $response, $name, $meth);
17    
18     if (ref($xml) eq 'SCALAR')
19     {
20     $reqobj = $self->{__parser}->parse($$xml);
21     return RPC::XML::response
22     ->new(RPC::XML::fault->new(200, "XML parse failure: $reqobj"))
23     unless (ref $reqobj);
24     }
25     elsif (ref($xml) eq 'ARRAY')
26     {
27     # This is sort of a cheat, to make the system.multicall API call a
28     # lot easier. The syntax isn't documented in the manual page, for good
29     # reason.
30     $reqobj = RPC::XML::request->new(shift(@$xml), @$xml);
31     }
32     elsif (UNIVERSAL::isa($xml, 'RPC::XML::request'))
33     {
34     $reqobj = $xml;
35     }
36     else
37     {
38     $reqobj = $self->{__parser}->parse($xml);
39     return RPC::XML::response
40     ->new(RPC::XML::fault->new(200, "XML parse failure: $reqobj"))
41     unless (ref $reqobj);
42     }
43    
44     $self->{__request_object} = $reqobj;
45    
46     @data = @{$reqobj->args};
47     $name = $reqobj->name;
48    
49     #print "request: ", Dumper($reqobj);
50    
51     #$self->{session_id} ||= '';
52    
53     my $session_id = $self->_server_read_request();
54    
55     my $err_code = 0;
56     my $err_msg = '';
57    
58     # check session-id here: do we already know it?
59     if (!$session_id) {
60     $err_code = 510;
61     $err_msg = "Internal error: Unique session identifier could not be created.";
62     } elsif (!$self->{__sessions}->{$session_id}) {
63     $err_code = 511;
64     $err_msg = "Internal error: Unknown session identifier '$session_id'.";
65     }
66    
67     if ($err_code) {
68     return $self->_get_fault_response($err_code, $err_msg);
69     }
70    
71     # increase access-counter (per-session)
72     #$self->{__sessions}->{$session_id}++;
73    
74    
75     # Get the method, call it, and bump the internal requests counter. Create
76     # a fault object if there is problem with the method object itself.
77     if (ref($meth = $self->get_method($name)))
78     {
79     if (!$self->_method_check_permissions($meth)) {
80     return $self->_get_fault_response(401, "Authorization required for method \"" . $meth->name() . "\". Please login first.");
81     }
82    
83     # manipulate sigtable, if required (session initialized)
84     #if ($session_id) {
85     # my $signature = $meth->{sig_table};
86     #}
87    
88     #print Dumper(@data);
89    
90     # manipulate args, if required (session initialized)
91     =pod
92     if ($session_id && $#data >= 1) {
93     my $last = pop @data;
94     #print Dumper($last);
95     if ($last && ref $last eq 'RPC::XML::struct') {
96     my $last_value = $last->value();
97     print Dumper($last_value);
98     if (!$last_value->{RPCSESSID}) {
99     push @data, $last;
100     }
101     }
102     }
103     =cut
104    
105     $response = $meth->call($self, @data);
106     $self->{__requests}++;
107     }
108     else
109     {
110     $response = RPC::XML::fault->new(300, $meth);
111     }
112    
113     #my $session_id_obj = new RPC::XML::string($session_id);
114     #$response = new RPC::XML::array($response, $session_id_obj);
115    
116     #print "response: ", Dumper($response);
117    
118     # All the eval'ing and error-trapping happened within the method class
119     RPC::XML::response->new($response);
120     }
121    
122     sub _get_fault_response {
123     my $self = shift;
124     my $code = shift;
125     my $message = shift;
126     my $response = RPC::XML::fault->new($code, $message);
127     print __PACKAGE__ . ": [" . $self->get_session_id() . "] - $message", "\n";
128     return RPC::XML::response->new($response);
129     }
130    
131     sub _method_check_permissions {
132     my $self = shift;
133     my $method = shift;
134    
135     # if method is not declared as 'protected' - just signal good
136     return 1 if !$method->{protected};
137    
138     # check if already authenticated - also signal good
139     my $id = $self->get_session_id();
140     return 1 if $self->{__auth}->{$id};
141    
142     }
143    
144     sub authenticate {
145     my $self = shift;
146    
147     my $user = shift;
148     my $pass = shift;
149    
150     # signal bad if no authentication information is supplied
151     if (!$self->{authentication}) { return; }
152    
153     #my $method = shift;
154    
155     #my $prot = $method->{protection};
156     #$prot->{type} ||= '';
157    
158     my $request_auth_type = 'plain';
159     my $server_auth_type = $self->{authentication}->{type};
160    
161     # check if auth-type from request matches declaration
162     if ($request_auth_type ne $server_auth_type) {
163     $self->debug( "Issued authentication-type '$request_auth_type' does not match server-requirement '$server_auth_type'." );
164     return;
165     }
166    
167     if (!$request_auth_type) {
168     $self->debug( "Authentication type was empty." );
169     return;
170    
171     } elsif ($request_auth_type eq 'plain') {
172     $self->debug( "User '$user' attempts to authenticate with type '$request_auth_type'." );
173     #print Dumper($self);
174     if ($self->{authentication}->{user} eq $user && $self->{authentication}->{pass} eq $pass) {
175     my $id = $self->get_session_id();
176     $self->{__auth}->{$id}++;
177     $self->debug( "Authentication successful [user=$self->{authentication}->{user}]." );
178     return 1;
179    
180     } else {
181     $self->debug( "Authentication failed [user=$self->{authentication}->{user}]." );
182     }
183    
184     } elsif ($request_auth_type eq 'md5') {
185     $self->debug( "FIXME: Protection type '$request_auth_type' not supported." );
186    
187     } else {
188     $self->debug( "Protection type '$request_auth_type' not supported." );
189     }
190    
191     }
192    
193     sub _server_read_request() {
194    
195     my $self = shift;
196     my $reqobj = $self->{__request_object};
197    
198     my $isNew = 0;
199     my $session_id;
200    
201     # check if session-id is already present in request (we don't have cookies here) ...
202     if ($session_id = $reqobj->{session_id}) {
203     #print "session_id_r: ", $session_id, "\n";
204     delete $reqobj->{session_id};
205     } else {
206     # ... issue new one
207     #print Dumper($self);
208     $session_id = make_guid();
209     $isNew = 1;
210     }
211    
212     # set current session id to server scope
213     # FIXME: is this transfer still valid if multi-threading and/or -processing gets used?
214     # FIXME: this is a hairy place for doing stuff like this! review twice!
215     $self->{__session_id} = $session_id;
216    
217     if ($isNew) {
218     $self->debug("Initializing new client session with identifier '$session_id'.");
219     $self->_server_init_session();
220     }
221    
222     return $session_id;
223    
224     }
225    
226     sub _server_init_session {
227     my $self = shift;
228     my $session_id = $self->{__session_id};
229     # increase access-counter (per-session)
230     $self->{__sessions}->{$session_id}++;
231     }
232    
233     sub get_session_id {
234     my $self = shift;
235     return $self->{__session_id};
236     }
237    
238     sub debug {
239     my $self = shift;
240     print __PACKAGE__, "[$self->{__host}:$self->{__port}]", ": ", @_, "\n" if @_;
241     }
242    
243    
244    
245    
246     package RPC::XML::request;
247    
248     use strict;
249     use warnings;
250     #use vars qw(@ISA);
251     use base qw( RPC::XML::request );
252    
253     use Data::Dumper;
254    
255    
256     sub new
257     {
258     my $class = shift;
259     my @argz = @_;
260    
261     my ($self, $name);
262    
263     $class = ref($class) || $class;
264     $RPC::XML::ERROR = '';
265    
266     unless (@argz)
267     {
268     $RPC::XML::ERROR = 'RPC::XML::request::new: At least a method name ' .
269     'must be specified';
270     return undef;
271     }
272    
273     if (UNIVERSAL::isa($argz[0], 'RPC::XML::request'))
274     {
275     # Maybe this will be a clone operation
276     }
277     else
278     {
279     # This is the method name to be called
280     $name = shift(@argz);
281    
282     # check for session-id in request's args
283     my $session_id = _request_get_RPCSESSID(\@argz);
284    
285     # All the remaining args must be data.
286     @argz = RPC::XML::smart_encode(@argz);
287     #print Dumper(@argz);
288     $self = { args => [ @argz ], name => $name, session_id => $session_id };
289     bless $self, $class;
290    
291     #print Dumper($self);
292     }
293    
294     $self;
295     }
296    
297     # Accessor methods
298     sub name { shift->{name} }
299     sub args { shift->{args} || [] }
300     sub session_id { shift->{session_id} }
301    
302    
303     sub _request_get_RPCSESSID {
304    
305     my $haystack = shift;
306    
307     # check each element in $haystack for being a hash (struct),
308     # if so, check if key 'RPCSESSID' exists in there
309     # propagate this as session-id!
310    
311     foreach (@$haystack) {
312    
313     # check lists (arrays) recursively
314     if (ref $_ eq 'RPC::XML::array') {
315     return _request_get_RPCSESSID($_);
316    
317     } elsif (ref $_ eq 'RPC::XML::struct') {
318     if (exists $_->{RPCSESSID}) {
319     my $id_obj = $_->{RPCSESSID};
320     my $id = $id_obj->value();
321     delete $_->{RPCSESSID};
322     #last;
323     return $id;
324     }
325    
326     }
327     }
328    
329     }
330    
331     1;
332     __END__

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed