File Coverage

blib/lib/Net/FTPServer/DBeg1/Server.pm
Criterion Covered Total %
statement 24 60 40.0
branch 0 12 0.0
condition 0 9 0.0
subroutine 8 15 53.3
pod 6 6 100.0
total 38 102 37.2


line stmt bran cond sub pod time code
1             # -*- perl -*-
2              
3             # Net::FTPServer A Perl FTP Server
4             # Copyright (C) 2000 Bibliotech Ltd., Unit 2-3, 50 Carnwath Road,
5             # London, SW6 3EG, United Kingdom.
6             #
7             # This program is free software; you can redistribute it and/or modify
8             # it under the terms of the GNU General Public License as published by
9             # the Free Software Foundation; either version 2 of the License, or
10             # (at your option) any later version.
11             #
12             # This program is distributed in the hope that it will be useful,
13             # but WITHOUT ANY WARRANTY; without even the implied warranty of
14             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15             # GNU General Public License for more details.
16             #
17             # You should have received a copy of the GNU General Public License
18             # along with this program; if not, write to the Free Software
19             # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20              
21             =pod
22              
23             =head1 NAME
24              
25             Net::FTPServer::DBeg1::Server - The DB example FTP server personality
26              
27             =head1 SYNOPSIS
28              
29             dbeg1-ftpd.pl [-d] [-v] [-p port] [-s] [-S] [-V] [-C conf_file]
30              
31             =head1 DESCRIPTION
32              
33             C is the example DB-based FTP server
34             personality. This personality implements a simple
35             FTP server with a PostgreSQL database back-end.
36              
37             =head1 METHODS
38              
39             =cut
40              
41             package Net::FTPServer::DBeg1::Server;
42              
43 1     1   858 use strict;
  1         2  
  1         26  
44              
45 1     1   4 use vars qw($VERSION);
  1         3  
  1         57  
46             ( $VERSION ) = '$Revision: 1.1 $ ' =~ /\$Revision:\s+([^\s]+)/;
47              
48 1     1   5 use DBI;
  1         2  
  1         28  
49              
50 1     1   4 use Net::FTPServer;
  1         3  
  1         20  
51 1     1   247 use Net::FTPServer::DBeg1::FileHandle;
  1         2  
  1         23  
52 1     1   5 use Net::FTPServer::DBeg1::DirHandle;
  1         2  
  1         17  
53              
54 1     1   3 use vars qw(@ISA);
  1         3  
  1         39  
55             @ISA = qw(Net::FTPServer);
56              
57             # Cached statement handles.
58 1     1   5 use vars qw($sth1 $sth2 $sth3);
  1         1  
  1         392  
59              
60             # This is called before configuration.
61              
62             sub pre_configuration_hook
63             {
64 0     0 1   my $self = shift;
65              
66 0           $self->{version_string} .= " Net::FTPServer::DBeg1/$VERSION";
67              
68             # Custom SITE commands.
69 0           $self->{site_command_table}{USAGE} = \&_SITE_USAGE_command;
70             }
71              
72             # This is called just after accepting a new connection. We connect
73             # to the database here.
74              
75             sub post_accept_hook
76             {
77 0     0 1   my $self = shift;
78              
79             # Connect to the database.
80 0 0         my $dbh = DBI->connect ("dbi:Pg(RaiseError=>1,AutoCommit=>0):dbname=ftp",
81             "", "")
82             or die "cannot connect to database: ftp: $!";
83              
84             # Store the database handle.
85 0           $self->{fs_dbh} = $dbh;
86             }
87              
88             # This is called after executing every command. It commits the transaction
89             # into the database.
90              
91             sub post_command_hook
92             {
93 0     0 1   my $self = shift;
94              
95 0           $self->{fs_dbh}->commit;
96             }
97              
98             # Perform login against the database.
99              
100             sub authentication_hook
101             {
102 0     0 1   my $self = shift;
103 0           my $user = shift;
104 0           my $pass = shift;
105 0           my $user_is_anon = shift;
106              
107             # Disallow anonymous access.
108 0 0         return -1 if $user_is_anon;
109              
110             # Verify access against the database.
111 0           my $sql = "select password from users where username = ?";
112 0   0       $sth1 ||= $self->{fs_dbh}->prepare ($sql);
113 0           $sth1->execute ($user);
114              
115 0 0         my $row = $sth1->fetch or return -1; # No such user.
116              
117             # Check password.
118 0           my $hashed_pass = $row->[0];
119 0 0         return -1 unless crypt ($pass, $hashed_pass) eq $hashed_pass;
120              
121             # Successful login.
122 0           return 0;
123             }
124              
125             # Called just after user C<$user> has successfully logged in.
126              
127             sub user_login_hook
128       0 1   {
129             # Do nothing for now, but in future it would be a good
130             # idea to change uid or chroot to a safe place.
131             }
132              
133             # Return an instance of Net::FTPServer::DBeg1::DirHandle
134             # corresponding to the root directory.
135              
136             sub root_directory_hook
137             {
138 0     0 1   my $self = shift;
139              
140 0           return new Net::FTPServer::DBeg1::DirHandle ($self);
141             }
142              
143             # The SITE USAGE command.
144              
145             sub _SITE_USAGE_command
146             {
147 0     0     my $self = shift;
148 0           my $cmd = shift;
149 0           my $rest = shift;
150              
151             # Count the number of files and directories used.
152 0           my $sql = "select count(id) from files";
153 0   0       $sth2 ||= $self->{fs_dbh}->prepare ($sql);
154 0           $sth2->execute;
155              
156 0 0         my $row = $sth2->fetch or die "no rows returned from count";
157              
158 0           my $nr_files = $row->[0];
159              
160 0           $sql = "select count(id) from directories";
161 0   0       $sth3 ||= $self->{fs_dbh}->prepare ($sql);
162 0           $sth3->execute;
163              
164 0 0         $row = $sth3->fetch or die "no rows returned from count";
165              
166 0           my $nr_dirs = $row->[0];
167              
168 0           $self->reply (200,
169             "There are $nr_files files and $nr_dirs directories.");
170             }
171              
172             1 # So that the require or use succeeds.
173              
174             __END__