new project
[Net-APP.git] / APP.pm
1 package Net::APP;
2
3 use strict;
4 use vars qw($VERSION $APP_VERSION @ISA $AUTOLOAD);
5 use Carp;
6 use IO::Socket;
7 use Net::Cmd;
8
9 $VERSION = '0.1'; # $Id: APP.pm,v 1.1 1999-06-21 10:11:11 ivan Exp $
10 $APP_VERSION = '2.1';
11
12 @ISA = qw(Net::Cmd IO::Socket::INET);
13
14 =head1 NAME
15
16 Net::APP - Critical Path Account Provisioning Protocol
17
18 =head1 SYNOPSIS
19
20   use Net::APP;
21
22   #constructor
23   $app = new Net::APP ( 'host:port',
24                         User     => $user,
25                         Domain   => $domain,
26                         Password => $password,
27                         Timeout  => 60,
28                         Debug    => 1,
29                       ) or die $@;
30
31   #commands
32   $app->ver( 'ver' => $Net::APP::APP_VERSION );
33   $app->login ( User     => $user,
34                 Domain   => $domain,
35                 Password => $password,
36               );
37
38   $app->create_domain ( Domain => $domain );
39   $app->delete_domain ( Domain => $domain );
40   #etc. (see the Account Provisioning Protocol Developer's Guide, section 3.3)
41
42   #command status
43   $message = $app->message;
44   $code = $app->code;
45   $bool = $app->ok();
46
47   #destructor
48   $app->close();
49
50 =head1 DESCRIPTION
51
52 This module implements a client interface to Critical Path's Account
53 Provisioning Protocol, enabling a perl application to talk to APP servers.
54 This documentation assumes that you are familiar with the APP protocol
55 documented in the Account Provisioning Protocol Developer's Guide.
56
57 A new Net::APP object must be created with the I<new> method.  Once this has
58 been done, all APP commands are accessed via method calls on the object.
59
60 =head1 METHODS
61
62 =over 4
63
64 =item new ( HOST:PORT [ , OPTIONS ] )
65
66 This is the constructor for a new Net::APP object.  C<HOST> and C<PORT>
67 specify the host and port to connect to in cleartext.  Typically this
68 connection is proxied via Safe Passage Secure Tunnel to Critical Path.
69
70 This method will connect to the APP server and execute the I<ver> method.
71
72 I<OPTIONS> are passed in a hash like fastion, using key and value pairs.
73 Possible options are:
74
75 I<Timeout> - Set a timeout value (defaults to 120)
76
77 I<Debug> - Enable debugging information (see the debug method in L<Net::Cmd>)
78
79 I<User>, I<Domain>, I<Password> - if these exist, the I<new> method will also
80 execute the I<login> method automatically.
81
82 If the constructor fails I<undef> will be returned and an error message will be
83 in $@.
84
85 =cut
86
87 sub new {
88   my $proto = shift;
89   my $class = ref($proto) || $proto;
90   my ($host, $port) = split(/:/, shift);
91   my %arg = @_;
92
93   my $self = $class->SUPER::new( PeerAddr => $host,
94                                 PeerPort => $port,
95                                 Proto    => 'tcp',
96                                 Timeout  => defined $arg{Timeout}
97                                                     ? $arg{Timeout}
98                                                     : 120
99                               ) or return undef;
100
101   $self->autoflush(1);
102
103   $self->debug(exists $arg{Debug} ? $arg{Debug} : undef);
104
105   my $response = $self->_app_response;
106   unless ( $self->message =~ /^HI APP/ ) {
107     $@ = $self->code. " ". $self->message;
108     $self->close();
109     return undef;
110   }
111
112   $self->ver( 'ver' => $APP_VERSION );
113   unless ( $self->ok ) {
114     $@ = $self->code. " ". $self->message;
115     $self->close();
116     return undef;
117   }
118
119   if ( exists $arg{User} && exists $arg{Domain} && exists $arg{Password} ) {
120     $self->login( User     => $arg{User},
121                   Domain   => $arg{Domain},
122                   Password => $arg{Password},
123                 );
124     unless ( $self->ok ) {
125       $@ = $self->code. " ". $self->message;
126       $self->close();
127       return undef;
128     }
129   }
130
131   $self;
132 }
133
134 =item ver
135
136 =item login
137
138 =item create_domain
139
140 =item delete_domain
141
142 =item etc.
143
144 See the Account Provisioning Protocol Developer's Guide for details.  Commands
145 need not be in upper case, and options are passed in a hash-like fashion, as
146 a list of key-value pairs.
147
148 All options return a reference to a list containing the lines of the reponse,
149 or I<undef> upon failure.  The first line is parsed for the status code and
150 message.  You can check the status code and message using the normal Net::Cmd
151 I<message>, I<code>, I<ok>, and I<status> methods.
152
153 Only the get_num_domain_mailboxes, get_mailbox_availability and
154 get_mailbox_status methods currently return any additional response
155 information.  No attempt is (yet) made to parse this data.
156
157 =item message 
158
159 Returns the text message returned from the last command.
160
161 =item code
162
163 Returns the response code from the last command (see the Account Provisioning
164 Protcol Developer's Guide, chapter 4).  The code `-1' is used to represent
165 unparsable output from the APP server, in which case the entire first line
166 of the response is returned by the I<messsage> method.
167
168 =item ok
169
170 Returns true if the last code was an acceptable response.
171
172 =cut
173
174 sub ok {
175   my $self = shift;
176   ! $self->code();
177 }
178
179 =item status
180
181 Since the APP protocol has no concept of a "most significant digit" (see
182 L<Net::Cmd/status>), this is a noisy synonym for I<code>.
183
184 =cut
185
186 sub status {
187   carp "status method called (use code instead)";
188   my $self = shift;
189   $self->code();
190 }
191
192 sub AUTOLOAD {
193   my $self = shift;
194   my $command = $AUTOLOAD;
195   $command =~ s/.*://;
196   $self->_app_command( $command, @_ );
197   $self->_app_response;
198 }
199
200 =back
201
202 =head1 INTERNAL METHODS
203
204 These methods are not intended to be called by the user.
205
206 =over 4
207
208 =item _app_command ( COMMAND [ , OPTIONS ] )
209
210 Sends I<COMMAND>, encoded as per the Account Provisioning Protocol Developer's
211 Guide, section 3.2.  I<OPTIONS> are passed in a hash like
212 fashion, using key and value pairs.
213
214 =cut
215
216 sub _app_command {
217   my $self = shift;
218   my $command = shift;
219   my %arg = @_;
220
221   $self->command ( uc($command),
222                    map "\U$_\E=\"". _quote($arg{$_}). '"', keys %arg
223                  );
224   $self->command( '.' );
225 }
226
227 =item _app_response
228
229 Gets a response from the server.  Returns a reference to a list containing
230 the lines, or I<undef> upon failure.  You can check the status code and message
231 using the normal Net::Cmd I<message>, I<code>, I<ok>, and I<status> methods.
232
233 =cut
234
235 sub _app_response {
236   my $self = shift;
237   my $lines = $self->read_until_dot;
238   if ( $self->debug ) {
239     foreach ( @{$lines}, ".\n" ) { $self->debug_print('', $_ ) }
240   }
241   if ( $lines->[0] =~ /^(OK|ER)\s+(\d+)\s+(.*)$/ ) {
242     warn 'OK response with non-zero status!' if $1 eq 'OK' && $2;
243     warn 'ER response with zero status!' if $1 eq 'ER' && ! $2;
244     $self->set_status ( $2, $3 );
245   } else {
246     $self->set_status ( -1, $lines->[0] );
247   }
248   $lines;
249 }
250
251 =back
252
253 =head1 INTERNAL SUBROUTINES
254
255 These subroutines are not intended to be called by the user.
256
257 =over 4
258
259 =item _quote
260
261 Doubles double quotes.
262
263 This is untested for strings containing consecutive double quotes.
264
265 =cut
266
267 sub _quote {
268   my $string = shift;
269   $string =~ s/\"/\"\"/g; #consecutive quotes?
270   $string;
271 }
272
273 =back
274
275 =head1 AUTHOR
276
277 Ivan Kohler <ivan-netapp@sisd.com>.
278
279 This module is not sponsored or endorsed by Critical Path.
280
281 =head1 COPYRIGHT
282
283 Copyright (c) 1999 Ivan Kohler.
284 Copyright (c) 1999 Silicon Interactive Software Design.
285 All rights reserved.
286 This program is free software; you can redistribute it and/or modify it under
287 the same terms as Perl itself.
288
289 =head1 VERSION
290
291 $Id: APP.pm,v 1.1 1999-06-21 10:11:11 ivan Exp $
292
293 This module currently implements APP v2.1, as documented in the Account
294 Provisioning Protocol Developers Guide v2.1.
295
296 =head1 BUGS
297
298 The Account Provisioning Protocol Developer's Guide is not publicly available.
299
300 It appears that Safe Passage Secure Tunnel establishes a standard SSL 
301 connection.  It should be possible to use Net::SSLeay and connect to the APP
302 server directly.
303
304 Sending values with consecutive double quote characters is untested.
305
306 The get_num_domain_mailboxes, get_mailbox_availability and get_mailbox_status
307 methods currently return response information.  No attempt is (yet) made to
308 parse this data.
309
310 =head1 SEE ALSO
311
312 Critical Path <http://www.cp.net/>,
313 Safe Passage Secure Tunnel <http://www.c2.net/products/spst>,
314 L<Net::SSLeay>, L<Net::Cmd>, perl(1).
315
316 =head1 HISTORY
317
318 $Log: APP.pm,v $
319 Revision 1.1  1999-06-21 10:11:11  ivan
320 Initial revision
321
322
323 =cut
324
325 1;
326