506dce1de208fd669914e5bdfd64e3631959932c
[freeside.git] / fs_selfservice / FS-SelfService / SelfService / XMLRPC.pm
1 package FS::SelfService::XMLRPC;
2
3 =head1 NAME
4
5 FS::SelfService::XMLRPC - Freeside XMLRPC accessible self-service API
6
7 =head1 SYNOPSIS
8
9 =head1 DESCRIPTION
10
11 Use this API to implement your own client "self-service" module vi XMLRPC.
12
13 Each routine described in L<FS::SelfService> is available vi XMLRPC as the
14 method FS.SelfService.XMLRPC.B<method>.  All values are passed to the
15 selfservice-server in a struct of strings.  The return values are in a
16 struct as strings, arrays, or structs as appropriate for the values
17 described in L<FS::SelfService>.
18
19 =head1 BUGS
20
21 =head1 SEE ALSO
22
23 L<freeside-selfservice-clientd>, L<freeside-selfservice-server>,L<FS::SelfService>
24
25 =cut
26
27 use strict;
28 use vars qw($DEBUG $AUTOLOAD);
29 use XMLRPC::Lite; # for XMLRPC::Data
30 use FS::SelfService;
31
32 $DEBUG = 0;
33 $FS::SelfService::DEBUG = $DEBUG;
34
35 #false laziness w/FS::ClientAPI_XMLRPC.pm
36 our %typefix_skin_info = (
37   'logo'              => 'base64',
38   'title_left_image'  => 'base64',
39   'title_right_image' => 'base64',
40   'menu_top_image'    => 'base64',
41   'menu_body_image'   => 'base64',
42   'menu_bottom_image' => 'base64',
43 );
44 our %typefix = (
45   'invoice_pdf'          => { 'invoice_pdf' => 'base64', },
46   'legacy_invoice_pdf'   => { 'invoice_pdf' => 'base64', },
47   'skin_info'            => \%typefix_skin_info,
48   'login_info'           => \%typefix_skin_info,
49   'logout'               => \%typefix_skin_info,
50   'access_info'          => \%typefix_skin_info,
51   'reset_passwd'         => \%typefix_skin_info,
52   'check_reset_passwd'   => \%typefix_skin_info,
53   'process_reset_passwd' => \%typefix_skin_info,
54   'invoice_logo'         => { 'logo'  => 'base64', },
55   'login_banner_image'   => { 'image' => 'base64', },
56   'quotation_print'      => { 'document' => 'base64' },
57 );
58
59 sub AUTOLOAD {
60   my $call = $AUTOLOAD;
61   $call =~ s/^FS::SelfService::XMLRPC:://;
62
63   if (exists($FS::SelfService::autoload{$call})) {
64
65     shift; #discard package name;
66
67     $call = "FS::SelfService::$call";
68
69     no strict 'refs';
70
71     my $return = &{$call}(@_);
72
73     if ( exists($typefix{$call}) ) {
74       my $typefix = $typefix{$call};
75       foreach my $field ( grep exists($return->{$_}), keys %$typefix ) {
76         my $type = $typefix->{$field};
77         $return->{$field} = XMLRPC::Data->value($return->{$field})
78                                         ->type($type);
79       }
80     }
81
82     $return;
83
84   }else{
85     die "No such procedure: $call";
86   }
87 }
88
89 package SOAP::Transport::HTTP::Daemon;  # yuck
90
91 use POSIX qw(:sys_wait_h);
92
93 no warnings 'redefine';
94
95 sub handle {
96   my $self = shift->new;
97
98   local $SIG{CHLD} = 'IGNORE';
99
100 ACCEPT:
101   while (my $c = $self->accept) {
102     
103     my $kid = 0;
104     do {
105       $kid = waitpid(-1, WNOHANG);
106       warn "found kid $kid";
107     } while $kid > 0;
108
109     my $pid = fork;
110     next ACCEPT if $pid;
111
112     if ( not defined $pid ) {
113       warn "fork() failed: $!";
114       $c = undef;
115     } else {
116       while (my $r = $c->get_request) {
117         $self->request($r);
118         $self->SUPER::handle;
119         $c->send_response($self->response);
120       }
121       # replaced ->close, thanks to Sean Meisner <Sean.Meisner@VerizonWireless.com>
122       # shutdown() doesn't work on AIX. close() is used in this case. Thanks to Jos Clijmans <jos.clijmans@recyfin.be>
123       UNIVERSAL::isa($c, 'shutdown') ? $c->shutdown(2) : $c->close(); 
124       $c->close;
125     }
126     exit;
127   }
128 }
129
130 1;