File Coverage

blib/lib/Net/FTPServer/DBeg1/FileHandle.pm
Criterion Covered Total %
statement 24 74 32.4
branch 0 8 0.0
condition 0 12 0.0
subroutine 8 14 57.1
pod 6 6 100.0
total 38 114 33.3


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::FileHandle - The full FTP server personality
26              
27             =head1 SYNOPSIS
28              
29             use Net::FTPServer::DBeg1::FileHandle;
30              
31             =head1 METHODS
32              
33             =cut
34              
35             package Net::FTPServer::DBeg1::FileHandle;
36              
37 1     1   5 use strict;
  1         2  
  1         25  
38              
39 1     1   4 use vars qw($VERSION);
  1         1  
  1         56  
40             ( $VERSION ) = '$Revision: 1.1 $ ' =~ /\$Revision:\s+([^\s]+)/;
41              
42 1     1   6 use Carp qw(croak confess);
  1         2  
  1         38  
43              
44 1     1   5 use Net::FTPServer::FileHandle;
  1         2  
  1         17  
45 1     1   284 use Net::FTPServer::DBeg1::DirHandle;
  1         5  
  1         38  
46 1     1   6 use Net::FTPServer::DBeg1::IOBlob;
  1         3  
  1         19  
47              
48 1     1   5 use vars qw(@ISA);
  1         2  
  1         42  
49             @ISA = qw(Net::FTPServer::FileHandle);
50              
51 1     1   5 use vars qw($sth1 $sth2 $sth3 $sth4);
  1         2  
  1         490  
52              
53             # Return a new file handle.
54              
55             sub new
56             {
57 0     0 1   my $class = shift;
58 0           my $ftps = shift;
59 0           my $pathname = shift;
60 0           my $dir_id = shift;
61 0           my $file_id = shift;
62 0           my $content = shift;
63              
64             # Create object.
65 0           my $self = Net::FTPServer::FileHandle->new ($ftps, $pathname);
66              
67 0           $self->{fs_dir_id} = $dir_id;
68 0           $self->{fs_file_id} = $file_id;
69 0           $self->{fs_content} = $content;
70              
71 0           return bless $self, $class;
72             }
73              
74             # Return the directory handle for this file.
75              
76             sub dir
77             {
78 0     0 1   my $self = shift;
79              
80             return Net::FTPServer::DBeg1::DirHandle->new ($self->{ftps},
81             $self->dirname,
82 0           $self->{fs_dir_id});
83             }
84              
85             # Open the file handle.
86              
87             sub open
88             {
89 0     0 1   my $self = shift;
90 0           my $mode = shift;
91              
92 0 0         if ($mode eq "r") # Open file for reading.
    0          
    0          
93             {
94 0           return new Net::FTPServer::DBeg1::IOBlob ('r', $self->{ftps}{fs_dbh}, $self->{fs_content});
95             }
96             elsif ($mode eq "w") # Create/overwrite the file.
97             {
98             # Remove the existing large object and create a new one.
99 0           my $dbh = $self->{ftps}{fs_dbh};
100             my $blob_id = $dbh->func ($dbh->{pg_INV_WRITE}|$dbh->{pg_INV_READ},
101 0           'lo_creat');
102              
103 0           my $sql = "update files set content = ? where id = ?";
104 0   0       $sth4 ||= $dbh->prepare ($sql);
105 0           $sth4->execute ($blob_id, int ($self->{fs_file_id}));
106              
107 0           $dbh->func ($self->{fs_content}, 'lo_unlink');
108 0           $self->{fs_content} = $blob_id;
109              
110 0           return new Net::FTPServer::DBeg1::IOBlob ('w', $self->{ftps}{fs_dbh}, $self->{fs_content});
111             }
112             elsif ($mode eq "a") # Append to the file.
113             {
114 0           return new Net::FTPServer::DBeg1::IOBlob ('w', $self->{ftps}{fs_dbh}, $self->{fs_content});
115             }
116             else
117             {
118 0           croak "unknown file mode: $mode; use 'r', 'w' or 'a' instead";
119             }
120             }
121              
122             sub status
123             {
124 0     0 1   my $self = shift;
125 0           my $dbh = $self->{ftps}{fs_dbh};
126 0           my $username = substr $self->{ftps}{user}, 0, 8;
127              
128             # Tricky: pull out the size information for this blob.
129              
130             # XXX For some reason PostgreSQL (6.4) fails when you call lo_open
131             # the first time. But if you retry a second time it succeeds. Therefore
132             # there is this hack. [RWMJ]
133              
134 0           my $blob_fd;
135              
136 0   0       for (my $retries = 0; !$blob_fd && $retries < 3; ++$retries)
137             {
138             $blob_fd = $dbh->func ($self->{fs_content}, $dbh->{pg_INV_READ},
139 0           'lo_open');
140             }
141              
142 0 0         die "failed to open blob $self->{fs_content}: ", $dbh->errstr
143             unless $blob_fd;
144              
145 0           my $size = $dbh->func ($blob_fd, 0, 2, 'lo_lseek');
146              
147 0           $dbh->func ($blob_fd, 'lo_close');
148              
149 0           return ( 'f', 0644, 1, $username, "users", $size, 0 );
150             }
151              
152             # Move a file to elsewhere.
153              
154             sub move
155             {
156 0     0 1   my $self = shift;
157 0           my $dirh = shift;
158 0           my $filename = shift;
159              
160 0           my $sql = "update files set dir_id = ?, name = ? where id = ?";
161 0   0       $sth2 ||= $self->{ftps}{fs_dbh}->prepare ($sql);
162             $sth2->execute (int ($dirh->{fs_dir_id}), $filename,
163 0           int ($self->{fs_file_id}));
164              
165 0           return 0;
166             }
167              
168             # Delete a file.
169              
170             sub delete
171             {
172 0     0 1   my $self = shift;
173              
174 0           my $sql = "delete from files where id = ?";
175 0   0       $sth1 ||= $self->{ftps}{fs_dbh}->prepare ($sql);
176 0           $sth1->execute (int ($self->{fs_file_id}));
177              
178             # Delete the large object.
179 0           $self->{ftps}{fs_dbh}->func ($self->{fs_content}, 'lo_unlink');
180              
181 0           return 0;
182             }
183              
184             1 # So that the require or use succeeds.
185              
186             __END__