Bug 7394 : Fixing scoping issue with XSLT processing. Also bailing out early for...
[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
18 # with Koha; if not, write to the Free Software Foundation, Inc.,
19 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21 use strict;
22 #use warnings; FIXME - Bug 2505
23 use C4::Context;
24 use C4::Auth qw/get_session/;
25 use IO::File;
26
27 use vars qw($VERSION);
28
29 BEGIN {
30         # set the version for version checking
31         $VERSION = 3.00;
32 }
33
34 =head1 NAME
35
36 C4::UploadedFile - manage files uploaded by the user
37 for later processing.
38
39 =head1 SYNOPSIS
40
41  # create and store data
42  my $uploaded_file = C4::UploadedFile->new($sessionID);
43  my $fileID = $uploaded_file->id();
44  $uploaded_file->name('c:\temp\file.mrc');
45  $uploaded_file->max_size(1024);
46  while ($have_more_data) {
47     $uploaded_file->stash($data, $bytes_read);
48  }
49  $uploaded_file->done();
50
51  # check status of current file upload
52  my $progress = C4::UploadedFile->upload_progress($sessionID);
53
54  # get file handle for reading uploaded file
55  my $uploaded_file = C4::UploadedFile->fetch($fileID);
56  my $fh = $uploaded_file->fh();
57
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   my $uploaded_file = C4::UploadedFile->new($sessionID);
77
78 Creates a new object to represent the uploaded file.  Requires
79 the current session ID.
80
81 =cut
82
83 sub new {
84     my $class = shift;
85     my $sessionID = shift;
86
87     my $self = {};
88
89     $self->{'sessionID'} = $sessionID;
90     $self->{'fileID'} = Digest::MD5::md5_hex(Digest::MD5::md5_hex(time().{}.rand().{}.$$));
91     # FIXME - make staging area configurable
92     my $TEMPROOT = "/tmp";
93     my $OUTPUTDIR = "$TEMPROOT/$sessionID";
94     mkdir $OUTPUTDIR;
95     my $tmp_file_name = "$OUTPUTDIR/$self->{'fileID'}";
96     my $fh = new IO::File $tmp_file_name, "w";
97     unless (defined $fh) {
98         return undef;
99     }
100     $fh->binmode(); # Windows compatibility
101     $self->{'fh'} = $fh;
102     $self->{'tmp_file_name'} = $tmp_file_name;
103     $self->{'max_size'} = 0;
104     $self->{'progress'} = 0;
105     $self->{'name'} = '';
106
107     bless $self, $class;
108     $self->_serialize();
109
110     my $session = get_session($sessionID);
111     $session->param('current_upload', $self->{'fileID'});
112     $session->flush();
113
114     return $self;
115
116 }
117
118 sub _serialize {
119     my $self = shift;
120
121     my $prefix = "upload_" . $self->{'fileID'};
122     my $session = get_session($self->{'sessionID'});
123
124     # temporarily take file handle out of structure
125     my $fh = $self->{'fh'};
126     delete $self->{'fh'};
127     $session->param($prefix, $self);
128     $session->flush();
129     $self->{'fh'} =$fh;
130 }
131
132 =head2 id
133
134   my $fileID = $uploaded_file->id();
135
136 =cut
137
138 sub id {
139     my $self = shift;
140     return $self->{'fileID'};
141 }
142
143 =head2 name
144
145   my $name = $uploaded_file->name();
146   $uploaded_file->name($name);
147
148 Accessor method for the name by which the file is to be known.
149
150 =cut
151
152 sub name {
153     my $self = shift;
154     if (@_) {
155         $self->{'name'} = shift;
156         $self->_serialize();
157     } else {
158         return $self->{'name'};
159     }
160 }
161
162 =head2 max_size
163
164   my $max_size = $uploaded_file->max_size();
165   $uploaded_file->max_size($max_size);
166
167 Accessor method for the maximum size of the uploaded file.
168
169 =cut
170
171 sub max_size {
172     my $self = shift;
173     @_ ? $self->{'max_size'} = shift : $self->{'max_size'};
174 }
175
176 =head2 stash
177
178   $uploaded_file->stash($dataref, $bytes_read);
179
180 Write C<$dataref> to the temporary file.  C<$bytes_read> represents
181 the number of bytes (out of C<$max_size>) transmitted so far.
182
183 =cut
184
185 sub stash {
186     my $self = shift;
187     my $dataref = shift;
188     my $bytes_read = shift;
189
190     my $fh = $self->{'fh'};
191     print $fh $$dataref;
192
193     my $percentage = int(($bytes_read / $self->{'max_size'}) * 100);
194     if ($percentage > $self->{'progress'}) {
195         $self->{'progress'} = $percentage;
196         $self->_serialize();
197     }
198 }
199
200 =head2 done
201
202   $uploaded_file->done();
203
204 Indicates that all of the bytes have been uploaded.
205
206 =cut
207
208 sub done {
209     my $self = shift;
210     $self->{'progress'} = 'done';
211     $self->{'fh'}->close();
212     $self->_serialize();
213 }
214
215 =head2 upload_progress
216
217   my $upload_progress = C4::UploadFile->upload_progress($sessionID);
218
219 Returns (as an integer from 0 to 100) the percentage
220 progress of the current file upload.
221
222 =cut
223
224 sub upload_progress {
225     my ($class, $sessionID) = shift;
226
227     my $session = get_session($sessionID);
228
229     my $fileID = $session->param('current_upload');
230
231     my $reported_progress = 0;
232     if (defined $fileID and $fileID ne "") {
233         my $file = C4::UploadedFile->fetch($sessionID, $fileID);
234         my $progress = $file->{'progress'};
235         if (defined $progress) {
236             if ($progress eq "done") {
237                 $reported_progress = 100;
238             } else {
239                 $reported_progress = $progress;
240             }
241         }
242     }
243     return $reported_progress;
244 }
245
246 =head2 fetch
247
248   my $uploaded_file = C4::UploadedFile->fetch($sessionID, $fileID);
249
250 Retrieves an uploaded file object from the current session.
251
252 =cut
253
254 sub fetch {
255     my $class = shift;
256     my $sessionID = shift;
257     my $fileID = shift;
258
259     my $session = get_session($sessionID);
260     my $prefix = "upload_$fileID";
261     my $self = $session->param($prefix);
262     my $fh = new IO::File $self->{'tmp_file_name'}, "r";
263     $self->{'fh'} = $fh;
264
265     bless $self, $class;
266     return $self;
267 }
268
269 =head2 fh
270
271   my $fh = $uploaded_file->fh();
272
273 Returns an IO::File handle to read the uploaded file.
274
275 =cut
276
277 sub fh {
278     my $self = shift;
279     return $self->{'fh'};
280 }
281
282 1;
283 __END__
284
285 =head1 AUTHOR
286
287 Koha Development Team <http://koha-community.org/>
288
289 Galen Charlton <galen.charlton@liblime.com>
290
291 =cut