rename internal function
[koha.git] / C4 / UploadedFile.pm
1 package C4::UploadedFile;
2
3 # Copyright (C) 2007 LibLime
4 # Galen Charlton <galen.charlton@liblime.com>
5 #
6 # This file is part of Koha.
7 #
8 # Koha is free software; you can redistribute it and/or modify it under the
9 # terms of the GNU General Public License as published by the Free Software
10 # Foundation; either version 2 of the License, or (at your option) any later
11 # version.
12 #
13 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
14 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License along with
18 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
19 # Suite 330, Boston, MA  02111-1307 USA
20
21 use strict;
22 use C4::Context;
23 use C4::Auth qw/get_session/;
24 use IO::File;
25
26 use vars qw($VERSION);
27
28 # set the version for version checking
29 $VERSION = 3.00;
30
31 =head1 NAME
32
33 C4::UploadedFile - manage files uploaded by the user
34 for later processing.
35
36 =head1 SYNOPSIS
37
38 =over 4
39
40 # create and store data
41 my $uploaded_file = C4::UploadedFile->new($sessionID);
42 my $fileID = $uploaded_file->id();
43 $uploaded_file->name('c:\temp\file.mrc');
44 $uploaded_file->max_size(1024);
45 while ($have_more_data) {
46     $uploaded_file->stash($data, $bytes_read);
47 }
48 $uploaded_file->done();
49
50 # check status of current file upload
51 my $progress = C4::UploadedFile->upload_progress($sessionID);
52
53 # get file handle for reading uploaded file
54 my $uploaded_file = C4::UploadedFile->fetch($fileID);
55 my $fh = $uploaded_file->fh();
56
57 =back
58
59 Stores files uploaded by the user from their web browser.  The
60 uploaded files are temporary and at present are not guaranteed
61 to survive beyond the life of the user's session.
62
63 This module allows for tracking the progress of the file
64 currently being uploaded.
65
66 TODO: implement secure persistant storage of uploaded files.
67
68 =cut
69
70 =head1 METHODS
71
72 =cut
73
74 =head2 new
75
76 =over 4
77
78 my $uploaded_file = C4::UploadedFile->new($sessionID);
79
80 =back
81
82 Creates a new object to represent the uploaded file.  Requires
83 the current session ID.
84
85 =cut
86
87 sub new {
88     my $class = shift;
89     my $sessionID = shift;
90
91     my $self = {};
92
93     $self->{'sessionID'} = $sessionID;
94     $self->{'fileID'} = Digest::MD5::md5_hex(Digest::MD5::md5_hex(time().{}.rand().{}.$$));
95     # FIXME - make staging area configurable
96     my $TEMPROOT = "/tmp";
97     my $OUTPUTDIR = "$TEMPROOT/$sessionID";
98     mkdir $OUTPUTDIR;
99     my $tmp_file_name = "$OUTPUTDIR/$self->{'fileID'}";
100     my $fh = new IO::File $tmp_file_name, "w";
101     unless (defined $fh) {
102         return undef;
103     }
104     $fh->binmode(); # Windows compatibility
105     $self->{'fh'} = $fh;
106     $self->{'tmp_file_name'} = $tmp_file_name;
107     $self->{'max_size'} = 0;
108     $self->{'progress'} = 0;
109     $self->{'name'} = '';
110
111     bless $self, $class;
112     $self->_serialize();
113
114     my $session = get_session($sessionID);
115     $session->param('current_upload', $self->{'fileID'});
116     $session->flush();
117
118     return $self;
119
120 }
121
122 sub _serialize {
123     my $self = shift;
124
125     my $prefix = "upload_" . $self->{'fileID'};
126     my $session = get_session($self->{'sessionID'});
127
128     # temporarily take file handle out of structure
129     my $fh = $self->{'fh'};
130     delete $self->{'fh'};
131     $session->param($prefix, $self);
132     $session->flush();
133     $self->{'fh'} =$fh;
134 }
135
136 =head2 id
137
138 =over 4
139
140 my $fileID = $uploaded_file->id();
141
142 =back
143
144 =cut
145
146 sub id {
147     my $self = shift;
148     return $self->{'fileID'};
149 }
150
151 =head2 name
152
153 =over 4
154
155 my $name = $uploaded_file->name();
156 $uploaded_file->name($name);
157
158 =back
159
160 Accessor method for the name by which the file is to be known.
161
162 =cut
163
164 sub name {
165     my $self = shift;
166     if (@_) {
167         $self->{'name'} = shift;
168         $self->_serialize();
169     } else {
170         return $self->{'name'};
171     }
172 }
173
174 =head2 max_size
175
176 =over 4
177
178 my $max_size = $uploaded_file->max_size();
179 $uploaded_file->max_size($max_size);
180
181 =back
182
183 Accessor method for the maximum size of the uploaded file.
184
185 =cut
186
187 sub max_size {
188     my $self = shift;
189     @_ ? $self->{'max_size'} = shift : $self->{'max_size'};
190 }
191
192 =head2 stash
193
194 =over 4
195
196 $uploaded_file->stash($dataref, $bytes_read);
197
198 =back
199
200 Write C<$dataref> to the temporary file.  C<$bytes_read> represents
201 the number of bytes (out of C<$max_size>) transmitted so far.
202
203 =cut
204
205 sub stash {
206     my $self = shift;
207     my $dataref = shift;
208     my $bytes_read = shift;
209
210     my $fh = $self->{'fh'};
211     print $fh $$dataref;
212
213     my $percentage = int(($bytes_read / $self->{'max_size'}) * 100);
214     if ($percentage > $self->{'progress'}) {
215         $self->{'progress'} = $percentage;
216         $self->_serialize();
217     }
218 }
219
220 =head2 done
221
222 =over 4
223
224 $uploaded_file->done();
225
226 =back
227
228 Indicates that all of the bytes have been uploaded.
229
230 =cut
231
232 sub done {
233     my $self = shift;
234     $self->{'progress'} = 'done';
235     $self->{'fh'}->close();
236     $self->_serialize();
237 }
238
239 =head2 upload_progress
240
241 =over 4
242
243 my $upload_progress = C4::UploadFile->upload_progress($sessionID);
244
245 =back
246
247 Returns (as an integer from 0 to 100) the percentage
248 progress of the current file upload.
249
250 =cut
251
252 sub upload_progress {
253     my ($class, $sessionID) = shift;
254
255     my $session = get_session($sessionID);
256
257     my $fileID = $session->param('current_upload');
258
259     my $reported_progress = 0;
260     if (defined $fileID and $fileID ne "") {
261         my $file = C4::UploadedFile->fetch($sessionID, $fileID);
262         my $progress = $file->{'progress'};
263         if (defined $progress) {
264             if ($progress eq "done") {
265                 $reported_progress = 100;
266             } else {
267                 $reported_progress = $progress;
268             }
269         }
270     }
271     return $reported_progress;
272 }
273
274 =head2 fetch
275
276 =over 4
277
278     my $uploaded_file = C4::UploadedFile->fetch($sessionID, $fileID);
279
280 =back
281
282 Retrieves an uploaded file object from the current session.
283
284 =cut
285
286 sub fetch {
287     my $class = shift;
288     my $sessionID = shift;
289     my $fileID = shift;
290
291     my $session = get_session($sessionID);
292     my $prefix = "upload_$fileID";
293     my $self = $session->param($prefix);
294     my $fh = new IO::File $self->{'tmp_file_name'}, "r";
295     $self->{'fh'} = $fh;
296
297     bless $self, $class;
298     return $self;
299 }
300
301 =head2 fh
302
303 =over
304
305 my $fh = $uploaded_file->fh();
306
307 =back
308
309 Returns an IO::File handle to read the uploaded file.
310
311 =cut
312
313 sub fh {
314     my $self = shift;
315     return $self->{'fh'};
316 }
317
318 =head1 AUTHOR
319
320 Koha Development Team <info@koha.org>
321
322 Galen Charlton <galen.charlton@liblime.com>
323
324 =cut