View | Details | Raw Unified | Return to bug 14321
Collapse All | Expand All

(-)a/Koha/Upload.pm (+272 lines)
Line 0 Link Here
1
package Koha::Upload;
2
3
# Copyright 2015 Rijksmuseum
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
=head1 NAME
21
22
Koha::Upload - Facilitate file upload
23
24
=head1 SYNOPSIS
25
26
    use Koha::Upload;
27
28
=head1 DESCRIPTION
29
30
    This class
31
32
=head1 METHODS
33
34
=head2 new
35
36
    Create object (via Class::Accessor).
37
38
=head1 PROPERTIES
39
40
=head2 ???
41
42
    ???
43
44
=head1 ADDITIONAL COMMENTS
45
46
=cut
47
48
use constant KOHA_UPLOAD => 'koha_upload';
49
use constant BYTES_DIGEST => 2048;
50
51
use Modern::Perl;
52
use CGI; # no utf8 flag, since it may interfere with binary uploads
53
use Digest::MD5;
54
use File::Spec;
55
use IO::File;
56
use Time::HiRes;
57
58
use base qw(Class::Accessor);
59
60
use C4::Context;
61
62
__PACKAGE__->mk_ro_accessors( qw| name
63
|);
64
65
=head2 new
66
67
    Returns new object based on Class::Accessor.
68
69
=cut
70
71
sub new {
72
    my ( $class, $params ) = @_;
73
    my $self = $class->SUPER::new();
74
    $self->_init( $params );
75
    return $self;
76
}
77
78
=head2 cgi
79
80
    Returns new object based on Class::Accessor.
81
82
=cut
83
84
sub cgi {
85
    my ( $self ) = @_;
86
87
    # Next call handles the actual upload via CGI hook.
88
    # The third parameter (0) below means: no CGI temporary storage.
89
    # Cancelling an upload will make CGI abort the script; no problem,
90
    # the file(s) without db entry will be removed later.
91
    my $query = CGI::->new( sub { $self->_hook(@_); }, {}, 0 );
92
    if( $query ) {
93
        $self->_done;
94
        return $query;
95
    }
96
}
97
98
=head2 result
99
100
    Returns new object based on Class::Accessor.
101
102
=cut
103
104
sub result {
105
    my ( $self ) = @_;
106
    my @a = map { $self->{files}->{$_}->{id} } keys $self->{files};
107
    return join ',', @a;
108
}
109
110
=head2 get
111
112
    Returns array
113
    optional parameter: filehandle => 1 (name, path only by default)
114
115
=cut
116
117
sub get {
118
    my ( $self, $params ) = @_;
119
    my $temp= $self->_lookup( $params );
120
    my ( @rv, $res );
121
    foreach my $r ( @$temp ) {
122
        $res->{name} = $r->{filename};
123
        $res->{path}= $self->_full_fname($r);
124
        $res->{fh} = IO::File->new( $res->{path}, "r" )
125
            if $params->{filehandle};
126
        push @rv, $res;
127
        last if !wantarray;
128
    }
129
    return wantarray? @rv: $res;
130
}
131
132
sub DESTROY {
133
}
134
135
# **************  INTERNAL ROUTINES ********************************************
136
137
sub _init {
138
    my ( $self, $params ) = @_;
139
140
    $self->{rootdir} = C4::Context->config('upload_path');
141
    $self->{tmpdir} = File::Spec->tmpdir;
142
    if( exists $params->{tmp} || exists $params->{temp} ||
143
      !$params->{category} ) {
144
        $self->{temporary} = 1;
145
        $self->{category} = undef;
146
    } else {
147
        $self->{category} = $params->{category};
148
    }
149
150
    $self->{errors} = [];
151
    $self->{files} = {};
152
    $self->{uid} = C4::Context->userenv->{number} if C4::Context->userenv;
153
}
154
155
sub _fh {
156
    my ( $self, $filename ) = @_;
157
    if( $self->{files}->{$filename} ) {
158
        return $self->{files}->{$filename}->{fh};
159
    }
160
}
161
162
sub _create_file {
163
    my ( $self, $filename ) = @_;
164
    my $fh;
165
    if( $self->{files}->{$filename} &&
166
            $self->{files}->{$filename}->{errcode} ) {
167
        #skip
168
    } elsif( $self->{temporary} && !$self->{tmpdir} ) {
169
        $self->{files}->{$filename}->{errcode} = 2;
170
    } else {
171
        my $dir = $self->_dir;
172
        my $fn = $self->{files}->{$filename}->{hash}. '_'. $filename;
173
        $fh = IO::File->new( "$dir/$fn", "w");
174
        if( $fh ) {
175
            $fh->binmode;
176
            $self->{files}->{$filename}->{fh}= $fh;
177
        } else {
178
            $self->{files}->{$filename}->{errcode} = 1;
179
            # push @{$self->{errors}}, [ 1, $filename ];
180
        }
181
    }
182
    return $fh;
183
}
184
185
sub _dir {
186
    my ( $self ) = @_;
187
    my $dir = $self->{temporary}? $self->{tmpdir}: $self->{rootdir};
188
    $dir.= '/'. ( $self->{category}? $self->{category}: KOHA_UPLOAD );
189
    mkdir $dir if !-d $dir;
190
    return $dir;
191
}
192
193
sub _full_fname {
194
    my ( $self, $rec ) = @_;
195
    if( ref $rec ) {
196
        return ( $rec->{category}? $self->{rootdir}: $self->{tmpdir} ).
197
            '/'. $rec->{dir}. '/'. $rec->{hashvalue}. '_'. $rec->{filename};
198
    }
199
}
200
201
sub _hook {
202
    my ( $self, $filename, $buffer, $bytes_read, $data ) = @_;
203
    $self->_compute( $filename, $buffer );
204
    my $fh = $self->_fh( $filename ) // $self->_create_file( $filename );
205
    print $fh $buffer if $fh;
206
}
207
208
sub _done {
209
    my ( $self ) = @_;
210
    $self->{done} = 1;
211
    foreach my $f ( keys $self->{files} ) {
212
        my $fh = $self->_fh($f);
213
        $self->_register( $f, $fh? tell( $fh ): undef )
214
            if !$self->{files}->{$f}->{errcode};
215
        $fh->close if $fh;
216
    }
217
}
218
219
sub _register {
220
    my ( $self, $filename, $size ) = @_;
221
    my $dbh= C4::Context->dbh;
222
    my $sql= "INSERT INTO uploaded_files (hashvalue, filename, dir, filesize,
223
        owner, categorycode) VALUES (?,?,?,?,?,?)";
224
    my @pars= ( $self->{files}->{$filename}->{hash},
225
        $filename,
226
        $self->{temporary}? KOHA_UPLOAD: $self->{category},
227
        $size,
228
        $self->{uid},
229
        $self->{category},
230
    );
231
    $dbh->do( $sql, undef, @pars );
232
    my $i = $dbh->last_insert_id(undef, undef, 'uploaded_files', undef);
233
    $self->{files}->{$filename}->{id} = $i if $i;
234
}
235
236
sub _lookup {
237
    my ( $self, $params ) = @_;
238
    my $dbh = C4::Context->dbh;
239
    my $sql = 'SELECT id,hashvalue,filename,dir,categorycode '.
240
        'FROM uploaded_files ';
241
    if( $params->{id} ) {
242
        $sql.= "WHERE id=?";
243
    } else {
244
        $sql.= "WHERE hashvalue=?";
245
    }
246
    my $temp= $dbh->selectall_arrayref( $sql, { Slice => {} },
247
        ( $params->{id} // $params->{hashvalue} // 0 ) );
248
    return $temp;
249
}
250
251
sub _compute {
252
# Computes hash value when sub hook feeds the first block
253
# For temporary files, the id is made unique with time
254
    my ( $self, $name, $block ) = @_;
255
    if( !$self->{files}->{$name}->{hash} ) {
256
        my $str = $name. ( $self->{uid} // '0' ).
257
            ( $self->{temporary}? Time::HiRes::time(): '' ).
258
            ( $self->{category} // 'tmp' ). substr( $block, 0, BYTES_DIGEST );
259
        # since Digest cannot handle wide chars, we need to encode here
260
        # there could be a wide char in the filename or the category
261
        my $h = Digest::MD5::md5_hex( Encode::encode_utf8( $str ) );
262
        $self->{files}->{$name}->{hash} = $h;
263
    }
264
}
265
266
=head1 AUTHOR
267
268
    Marcel de Rooy, Rijksmuseum Amsterdam, The Netherlands
269
270
=cut
271
272
1;
(-)a/koha-tmpl/intranet-tmpl/prog/en/js/file-upload.js (+32 lines)
Line 0 Link Here
1
function AjaxUpload ( input, progressbar, callback ) {
2
    // input and progressbar are jQuery objects
3
    // callback is the callback function for completion
4
    var formData= new FormData();
5
    $.each( input.prop('files'), function( dx, file ) {
6
        formData.append( "uploadfile", file );
7
    });
8
    var xhr= new XMLHttpRequest();
9
    var url= '/cgi-bin/koha/tools/upload-file.pl';
10
    progressbar.val( 0 );
11
    progressbar.next('.fileuploadpercent').text( '0' );
12
    xhr.open('POST', url, true);
13
    xhr.upload.onprogress = function (e) {
14
        var p = Math.round( (e.loaded/e.total) * 100 );
15
        progressbar.val( p );
16
        progressbar.next('.fileuploadpercent').text( p );
17
    }
18
    xhr.onload = function (e) {
19
        var data = JSON.parse( xhr.responseText );
20
        if( data.status == 'done' ) {
21
            progressbar.val( 100 );
22
            progressbar.next('.fileuploadpercent').text( '100' );
23
        }
24
        callback( data.status, data.fileid );
25
    }
26
    xhr.onerror = function (e) {
27
        // Probably only fires for network failure
28
        alert('An error occurred while uploading.');
29
    }
30
    xhr.send( formData );
31
    return xhr;
32
}
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/offline_circ/process_koc.tt (-8 / +31 lines)
Lines 1-22 Link Here
1
[% INCLUDE 'doc-head-open.inc' %]
1
[% INCLUDE 'doc-head-open.inc' %]
2
<title>Koha &rsaquo; Circulation &rsaquo; Offline circulation file upload</title>
2
<title>Koha &rsaquo; Circulation &rsaquo; Offline circulation file upload</title>
3
[% INCLUDE 'doc-head-close.inc' %]
3
[% INCLUDE 'doc-head-close.inc' %]
4
[% INCLUDE 'file-upload.inc' %]
4
5
<script type="text/javascript" src="[% themelang %]/js/background-job-progressbar.js"></script>
5
<script type="text/javascript" src="[% themelang %]/js/background-job-progressbar.js"></script>
6
<script type="text/javascript" src="[% themelang %]/js/file-upload.js"></script>
6
<script type="text/javascript">
7
<script type="text/javascript">
7
//<![CDATA[
8
//<![CDATA[
9
var xhr;
8
$(document).ready(function(){
10
$(document).ready(function(){
9
    $("#enqueuefile").hide();
11
    $("#enqueuefile").hide();
10
    $("#processfile").hide();
12
    $("#processfile").hide();
11
});
13
});
12
14
13
function CheckUpload(f){
15
function StartUpload() {
14
    if (f.fileToUpload.value == ""){
16
    if( $('#fileToUpload').prop('files').length == 0 ) return;
15
        alert(_("Please choose a file to upload"));
17
    $('#fileuploadform input.submit').prop('disabled',true);
18
    $("#fileuploadfailed").hide();
19
    $("#processfile").hide();
20
    $("#fileuploadstatus").show();
21
    $("form#processfile #uploadedfileid").val('');
22
    $("form#enqueuefile #uploadedfileid").val('');
23
    xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), cbUpload );
24
}
25
26
function cbUpload( status, fileid ) {
27
    if( status=='done' ) {
28
        $("form#processfile #uploadedfileid").val( fileid );
29
        $("form#enqueuefile #uploadedfileid").val( fileid );
30
        $('#fileToUpload').prop('disabled',true);
31
        $("#processfile").show();
32
        $("#enqueuefile").show();
16
    } else {
33
    } else {
17
        return ajaxFileUpload()
34
        $("#fileuploadstatus").hide();
35
        $("#fileuploadfailed").show();
36
        $("#fileuploadfailed").text( _("Upload status: ") +
37
            ( status=='failed'? _("Failed"):
38
            ( status=='denied'? _("Denied"): status ))
39
        );
18
    }
40
    }
19
    return false;
20
}
41
}
21
42
22
function CheckForm(f) {
43
function CheckForm(f) {
Lines 25-30 function CheckForm(f) { Link Here
25
    } else {
46
    } else {
26
        $("#fileuploadstatus").hide();
47
        $("#fileuploadstatus").hide();
27
        $("#fileuploadform").slideUp();
48
        $("#fileuploadform").slideUp();
49
        $("#mainformsubmit").prop('disabled',true);
50
        $("#queueformsubmit").prop('disabled',true);
28
        return submitBackgroundJob(f);
51
        return submitBackgroundJob(f);
29
    }
52
    }
30
    return false;
53
    return false;
Lines 70-79 function CheckForm(f) { Link Here
70
		<fieldset class="brief">
93
		<fieldset class="brief">
71
       <ol><li><label for="fileToUpload">Choose .koc file: </label>
94
       <ol><li><label for="fileToUpload">Choose .koc file: </label>
72
       <input type="file" id="fileToUpload" size="50" name="fileToUpload" /></li></ol>
95
       <input type="file" id="fileToUpload" size="50" name="fileToUpload" /></li></ol>
73
	   <fieldset class="action"><input type="button" class="submit" value="Upload file" onclick="CheckUpload(this.form);" /></fieldset>
96
       <fieldset class="action"><input type="button" class="submit" value="Upload file" onclick="StartUpload();return false;" /></fieldset>
74
	   </fieldset>
97
	   </fieldset>
75
     </form>
98
     </form>
76
     <div id="fileuploadstatus" style="display:none">Upload progress: <div id="fileuploadprogress"></div> <span id="fileuploadpercent">0</span>%</div>
99
     <div id="fileuploadstatus" style="display:none">Upload progress: <progress id="fileuploadprogress" min="0" max="100" value="0"></progress> <span class="fileuploadpercent">0</span>%</div>
77
     <div id="fileuploadfailed" style="display:none"></div>
100
     <div id="fileuploadfailed" style="display:none"></div>
78
   </div>
101
   </div>
79
102
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/stage-marc-import.tt (-7 / +57 lines)
Lines 1-14 Link Here
1
[% INCLUDE 'doc-head-open.inc' %]
1
[% INCLUDE 'doc-head-open.inc' %]
2
<title>Koha &rsaquo; Tools &rsaquo; Stage MARC records for import</title>
2
<title>Koha &rsaquo; Tools &rsaquo; Stage MARC records for import</title>
3
[% INCLUDE 'doc-head-close.inc' %]
3
[% INCLUDE 'doc-head-close.inc' %]
4
[% INCLUDE 'file-upload.inc' %]
4
5
<script type="text/javascript" src="[% themelang %]/js/background-job-progressbar.js"></script>
5
<script type="text/javascript" src="[% themelang %]/js/background-job-progressbar.js"></script>
6
<script type="text/javascript" src="[% themelang %]/js/file-upload.js"></script>
7
6
<style type="text/css">
8
<style type="text/css">
7
	#uploadpanel,#fileuploadstatus,#fileuploadfailed,#jobpanel,#jobstatus,#jobfailed { display : none; }
9
    #fileuploadstatus,#fileuploadfailed,#fileuploadcancel,#jobpanel,#jobstatus,#jobfailed { display : none; }
8
	#fileuploadstatus,#jobstatus { margin:.4em; }
10
	#fileuploadstatus,#jobstatus { margin:.4em; }
9
    #fileuploadprogress,#jobprogress{ width:150px;height:10px;border:1px solid #666;background:url('[% interface %]/[% theme %]/img/progress.png') -300px 0px no-repeat; }</style>
11
    #fileuploadprogress,#jobprogress { width:150px;height:10px;border:1px solid #666;background:url('[% interface %]/[% theme %]/img/progress.png') -300px 0px no-repeat; }
12
</style>
13
10
<script type="text/javascript">
14
<script type="text/javascript">
11
//<![CDATA[
15
//<![CDATA[
16
var xhr;
12
$(document).ready(function(){
17
$(document).ready(function(){
13
	$("#processfile").hide();
18
	$("#processfile").hide();
14
    $("#record_type").change(function() {
19
    $("#record_type").change(function() {
Lines 27-33 function CheckForm(f) { Link Here
27
    }
32
    }
28
    return false;
33
    return false;
29
}
34
}
30
35
function StartUpload() {
36
    if( $('#fileToUpload').prop('files').length == 0 ) return;
37
    $('#fileuploadbutton').hide();
38
    $("#fileuploadfailed").hide();
39
    $("#processfile").hide();
40
    $("#fileuploadstatus").show();
41
    $("#uploadedfileid").val('');
42
    xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), cbUpload );
43
    $("#fileuploadcancel").show();
44
}
45
function CancelUpload() {
46
    if( xhr ) xhr.abort();
47
    $("#fileuploadstatus").hide();
48
    $('#fileuploadbutton').show();
49
    $("#fileuploadcancel").hide();
50
    $("#fileuploadfailed").show();
51
    $("#fileuploadfailed").text( _("Upload status: Cancelled ") );
52
}
53
function cbUpload( status, fileid ) {
54
    if( status=='done' ) {
55
        $("#uploadedfileid").val( fileid );
56
        $('#fileToUpload').prop('disabled',true);
57
        $('#fileuploadbutton').prop('disabled',true);
58
        $('#fileuploadbutton').show();
59
        $("#fileuploadcancel").hide();
60
        $("#processfile").show();
61
    } else {
62
        $('#fileuploadbutton').show();
63
        $("#fileuploadcancel").hide();
64
        $("#fileuploadstatus").hide();
65
        $("#fileuploadfailed").show();
66
        $("#fileuploadfailed").text( _("Upload status: ") +
67
            ( status=='failed'? _("Failed"):
68
            ( status=='denied'? _("Denied"): status ))
69
        );
70
    }
71
}
31
//]]>
72
//]]>
32
</script>
73
</script>
33
</head>
74
</head>
Lines 90-100 function CheckForm(f) { Link Here
90
		<input type="file" id="fileToUpload" name="fileToUpload" />
131
		<input type="file" id="fileToUpload" name="fileToUpload" />
91
        </div>	</li>
132
        </div>	</li>
92
</ol>
133
</ol>
93
        <fieldset class="action"><button class="submit" onclick="return ajaxFileUpload();">Upload file</button></fieldset>
134
    <fieldset class="action">
135
        <button id="fileuploadbutton" onclick="StartUpload(); return false;">Upload file</button>
136
        <button id="fileuploadcancel" onclick="CancelUpload(); return false;">Cancel</button>
137
    </fieldset>
94
</fieldset>
138
</fieldset>
95
		
139
		
96
        <div id="uploadpanel"><div id="fileuploadstatus">Upload progress: <div id="fileuploadprogress"></div> <span id="fileuploadpercent">0</span>%</div>
140
    <div id="fileuploadpanel">
97
        <div id="fileuploadfailed"></div></div>
141
        <div id="fileuploadstatus">Upload progress:
142
            <progress id="fileuploadprogress" min="0" max="100" value="0">
143
            </progress>
144
            <span class="fileuploadpercent">0</span>%
145
        </div>
146
        <div id="fileuploadfailed"></div>
147
    </div>
98
</form>
148
</form>
99
149
100
    <form method="post" id="processfile" action="[% SCRIPT_NAME %]" enctype="multipart/form-data">
150
    <form method="post" id="processfile" action="[% SCRIPT_NAME %]" enctype="multipart/form-data">
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-images.tt (-6 / +39 lines)
Lines 1-14 Link Here
1
[% INCLUDE 'doc-head-open.inc' %]
1
[% INCLUDE 'doc-head-open.inc' %]
2
<title>Koha &rsaquo; Tools &rsaquo; Upload images</title>
2
<title>Koha &rsaquo; Tools &rsaquo; Upload images</title>
3
[% INCLUDE 'doc-head-close.inc' %]
3
[% INCLUDE 'doc-head-close.inc' %]
4
[% INCLUDE 'file-upload.inc' %]
4
5
<script type="text/javascript" src="[% themelang %]/js/background-job-progressbar.js"></script>
5
<script type="text/javascript" src="[% themelang %]/js/background-job-progressbar.js"></script>
6
<script type="text/javascript" src="[% themelang %]/js/file-upload.js"></script>
7
6
<style type="text/css">
8
<style type="text/css">
7
	#uploadpanel,#fileuploadstatus,#fileuploadfailed,#jobpanel,#jobstatus,#jobfailed { display : none; }
9
    #fileuploadstatus,#fileuploadfailed,#jobpanel,#jobstatus,#jobfailed { display : none; }
8
	#fileuploadstatus,#jobstatus { margin:.4em; }
10
	#fileuploadstatus,#jobstatus { margin:.4em; }
9
    #fileuploadprogress,#jobprogress{ width:150px;height:10px;border:1px solid #666;background:url('[% interface %]/[% theme %]/img/progress.png') -300px 0px no-repeat; }</style>
11
    #fileuploadprogress,#jobprogress { width:150px;height:10px;border:1px solid #666;background:url('[% interface %]/[% theme %]/img/progress.png') -300px 0px no-repeat; }
12
</style>
13
10
<script type="text/javascript">
14
<script type="text/javascript">
11
//<![CDATA[
15
//<![CDATA[
16
function StartUpload() {
17
    if( $('#fileToUpload').prop('files').length == 0 ) return;
18
    $('#uploadform button.submit').prop('disabled',true);
19
    $("#fileuploadstatus").show();
20
    $("#uploadedfileid").val('');
21
    xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), cbUpload );
22
}
23
function cbUpload( status, fileid ) {
24
    if( status=='done' ) {
25
        $("#uploadedfileid").val( fileid );
26
        $('#fileToUpload').prop('disabled',true);
27
        $("#processfile").show();
28
    } else {
29
        $("#fileuploadstatus").hide();
30
        $("#fileuploadfailed").show();
31
        $("#fileuploadfailed").text( _("Upload status: ") +
32
            ( status=='failed'? _("Failed"):
33
            ( status=='denied'? _("Denied"): status ))
34
        );
35
        $("#processfile").hide();
36
    }
37
}
12
$(document).ready(function(){
38
$(document).ready(function(){
13
	$("#processfile").hide();
39
	$("#processfile").hide();
14
	$("#zipfile").click(function(){
40
	$("#zipfile").click(function(){
Lines 19-25 $(document).ready(function(){ Link Here
19
	});
45
	});
20
    $("#uploadfile").validate({
46
    $("#uploadfile").validate({
21
        submitHandler: function(form) {
47
        submitHandler: function(form) {
22
            ajaxFileUpload();
48
            StartUpload();
49
            return false;
23
        }
50
        }
24
    });
51
    });
25
});
52
});
Lines 76-83 $(document).ready(function(){ Link Here
76
    <fieldset class="action"><button class="submit">Upload file</button></fieldset>
103
    <fieldset class="action"><button class="submit">Upload file</button></fieldset>
77
</fieldset>
104
</fieldset>
78
105
79
        <div id="uploadpanel"><div id="fileuploadstatus">Upload progress: <div id="fileuploadprogress"></div> <span id="fileuploadpercent">0</span>%</div>
106
    <div id="uploadpanel">
80
        <div id="fileuploadfailed"></div></div>
107
        <div id="fileuploadstatus">Upload progress:
108
            <progress min="0" max="100" value="0" id="fileuploadprogress">
109
            </progress>
110
            <span class="fileuploadpercent">0</span>%
111
        </div>
112
        <div id="fileuploadfailed"></div>
113
    </div>
81
</form>
114
</form>
82
115
83
    <form method="post" id="processfile" action="[% SCRIPT_NAME %]" enctype="multipart/form-data">
116
    <form method="post" id="processfile" action="[% SCRIPT_NAME %]" enctype="multipart/form-data">
(-)a/offline_circ/enqueue_koc.pl (-3 / +3 lines)
Lines 32-38 use C4::Circulation; Link Here
32
use C4::Items;
32
use C4::Items;
33
use C4::Members;
33
use C4::Members;
34
use C4::Stats;
34
use C4::Stats;
35
use C4::UploadedFile;
35
use Koha::Upload;
36
36
37
use Date::Calc qw( Add_Delta_Days Date_to_Days );
37
use Date::Calc qw( Add_Delta_Days Date_to_Days );
38
38
Lines 60-67 my $sessionID = $cookies{'CGISESSID'}->value; Link Here
60
our $dbh = C4::Context->dbh();
60
our $dbh = C4::Context->dbh();
61
61
62
if ($fileID) {
62
if ($fileID) {
63
    my $uploaded_file = C4::UploadedFile->fetch($sessionID, $fileID);
63
    my $upload = Koha::Upload->new->get({ id => $fileID, filehandle => 1 });
64
    my $fh = $uploaded_file->fh();
64
    my $fh = $upload->{fh};
65
    my @input_lines = <$fh>;
65
    my @input_lines = <$fh>;
66
66
67
    my $header_line = shift @input_lines;
67
    my $header_line = shift @input_lines;
(-)a/offline_circ/process_koc.pl (-4 / +4 lines)
Lines 32-38 use C4::Circulation; Link Here
32
use C4::Items;
32
use C4::Items;
33
use C4::Members;
33
use C4::Members;
34
use C4::Stats;
34
use C4::Stats;
35
use C4::UploadedFile;
35
use Koha::Upload;
36
use C4::BackgroundJob;
36
use C4::BackgroundJob;
37
37
38
use Date::Calc qw( Add_Delta_Days Date_to_Days );
38
use Date::Calc qw( Add_Delta_Days Date_to_Days );
Lines 69-79 if ($completedJobID) { Link Here
69
    $template->param(transactions_loaded => 1);
69
    $template->param(transactions_loaded => 1);
70
    $template->param(messages => $results->{results});
70
    $template->param(messages => $results->{results});
71
} elsif ($fileID) {
71
} elsif ($fileID) {
72
    my $uploaded_file = C4::UploadedFile->fetch($sessionID, $fileID);
72
    my $upload = Koha::Upload->new->get({ id => $fileID, filehandle => 1 });
73
    my $fh = $uploaded_file->fh();
73
    my $fh = $upload->{fh};
74
    my $filename = $upload->{name};
74
    my @input_lines = <$fh>;
75
    my @input_lines = <$fh>;
75
76
76
    my $filename = $uploaded_file->name();
77
    my $job = undef;
77
    my $job = undef;
78
78
79
    if ($runinbackground) {
79
    if ($runinbackground) {
(-)a/tools/stage-marc-import.pl (-4 / +5 lines)
Lines 39-45 use C4::Output; Link Here
39
use C4::Biblio;
39
use C4::Biblio;
40
use C4::ImportBatch;
40
use C4::ImportBatch;
41
use C4::Matcher;
41
use C4::Matcher;
42
use C4::UploadedFile;
42
use Koha::Upload;
43
use C4::BackgroundJob;
43
use C4::BackgroundJob;
44
use C4::MarcModificationTemplates;
44
use C4::MarcModificationTemplates;
45
use Koha::Plugins;
45
use Koha::Plugins;
Lines 84-91 if ($completedJobID) { Link Here
84
    my $results = $job->results();
84
    my $results = $job->results();
85
    $template->param(map { $_ => $results->{$_} } keys %{ $results });
85
    $template->param(map { $_ => $results->{$_} } keys %{ $results });
86
} elsif ($fileID) {
86
} elsif ($fileID) {
87
    my $uploaded_file = C4::UploadedFile->fetch($sessionID, $fileID);
87
    my $upload = Koha::Upload->new->get({ id => $fileID, filehandle => 1 });
88
    my $fh = $uploaded_file->fh();
88
    my $fh = $upload->{fh};
89
    my $filename = $upload->{name}; # filename only, no path
89
	my $marcrecord='';
90
	my $marcrecord='';
90
    $/ = "\035";
91
    $/ = "\035";
91
	while (<$fh>) {
92
	while (<$fh>) {
Lines 93-100 if ($completedJobID) { Link Here
93
        s/\s+$//;
94
        s/\s+$//;
94
		$marcrecord.=$_;
95
		$marcrecord.=$_;
95
	}
96
	}
97
    $fh->close;
96
98
97
    my $filename = $uploaded_file->name();
98
    my $job = undef;
99
    my $job = undef;
99
    my $dbh;
100
    my $dbh;
100
    if ($runinbackground) {
101
    if ($runinbackground) {
(-)a/tools/upload-cover-image.pl (-4 / +4 lines)
Lines 47-53 use C4::Context; Link Here
47
use C4::Auth;
47
use C4::Auth;
48
use C4::Output;
48
use C4::Output;
49
use C4::Images;
49
use C4::Images;
50
use C4::UploadedFile;
50
use Koha::Upload;
51
use C4::Log;
51
use C4::Log;
52
52
53
my $debug = 1;
53
my $debug = 1;
Lines 83-91 $template->{VARS}->{'biblionumber'} = $biblionumber; Link Here
83
my $total = 0;
83
my $total = 0;
84
84
85
if ($fileID) {
85
if ($fileID) {
86
    my $uploaded_file = C4::UploadedFile->fetch( $sessionID, $fileID );
86
    my $upload = Koha::Upload->new->get({ id => $fileID, filehandle => 1 });
87
    if ( $filetype eq 'image' ) {
87
    if ( $filetype eq 'image' ) {
88
        my $fh       = $uploaded_file->fh();
88
        my $fh       = $upload->{fh};
89
        my $srcimage = GD::Image->new($fh);
89
        my $srcimage = GD::Image->new($fh);
90
        if ( defined $srcimage ) {
90
        if ( defined $srcimage ) {
91
            my $dberror = PutImage( $biblionumber, $srcimage, $replace );
91
            my $dberror = PutImage( $biblionumber, $srcimage, $replace );
Lines 102-108 if ($fileID) { Link Here
102
        undef $srcimage;
102
        undef $srcimage;
103
    }
103
    }
104
    else {
104
    else {
105
        my $filename = $uploaded_file->filename();
105
        my $filename = $upload->{path};
106
        my $dirname = File::Temp::tempdir( CLEANUP => 1 );
106
        my $dirname = File::Temp::tempdir( CLEANUP => 1 );
107
        unless ( system( "unzip", $filename, '-d', $dirname ) == 0 ) {
107
        unless ( system( "unzip", $filename, '-d', $dirname ) == 0 ) {
108
            $error = 'UZIPFAIL';
108
            $error = 'UZIPFAIL';
(-)a/tools/upload-file-progress.pl (-3 / +2 lines)
Lines 36-42 my $flags_required = [ Link Here
36
     {tools     => 'upload_local_cover_images'},
36
     {tools     => 'upload_local_cover_images'},
37
];
37
];
38
38
39
my %cookies = fetch CGI::Cookie;
39
my %cookies = CGI::Cookie->fetch;
40
40
41
my ($auth_status, $sessionID) = check_cookie_auth($cookies{'CGISESSID'}->value);
41
my ($auth_status, $sessionID) = check_cookie_auth($cookies{'CGISESSID'}->value);
42
42
Lines 47-54 foreach my $flag_required ( @{$flags_required} ) { Link Here
47
    }
47
    }
48
}
48
}
49
49
50
my $reply = CGI->new;
50
if ($auth_failure) {
51
if ($auth_failure) {
51
    my $reply = CGI->new("");
52
    print $reply->header(-type => 'text/html');
52
    print $reply->header(-type => 'text/html');
53
    print '{"progress":"0"}';
53
    print '{"progress":"0"}';
54
    exit 0;
54
    exit 0;
Lines 56-62 if ($auth_failure) { Link Here
56
56
57
my $reported_progress = C4::UploadedFile->upload_progress($sessionID);
57
my $reported_progress = C4::UploadedFile->upload_progress($sessionID);
58
58
59
my $reply = CGI->new("");
60
print $reply->header(-type => 'text/html');
59
print $reply->header(-type => 'text/html');
61
# response will be sent back as JSON
60
# response will be sent back as JSON
62
print '{"progress":"' . $reported_progress . '"}';
61
print '{"progress":"' . $reported_progress . '"}';
(-)a/tools/upload-file.pl (-40 / +18 lines)
Lines 17-34 Link Here
17
# You should have received a copy of the GNU General Public License
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
19
20
use strict;
20
use Modern::Perl;
21
#use warnings; FIXME - Bug 2505
21
use CGI::Cookie;
22
22
23
# standard or CPAN modules used
24
use IO::File;
25
use CGI qw ( -utf8 );
23
use CGI qw ( -utf8 );
26
use CGI::Session;
24
#use CGI::Session;
27
use C4::Context;
25
use C4::Context;
28
use C4::Auth qw/check_cookie_auth haspermission/;
26
use C4::Auth qw/check_cookie_auth haspermission/;
29
use CGI::Cookie; # need to check cookies before
27
use Koha::Upload;
30
                 # having CGI parse the POST request
31
use C4::UploadedFile;
32
28
33
# upload-file.pl must authenticate the user
29
# upload-file.pl must authenticate the user
34
# before processing the POST request,
30
# before processing the POST request,
Lines 36-42 use C4::UploadedFile; Link Here
36
# not authorized.  Consequently, unlike
32
# not authorized.  Consequently, unlike
37
# most of the other CGI scripts, upload-file.pl
33
# most of the other CGI scripts, upload-file.pl
38
# requires that the session cookie already
34
# requires that the session cookie already
39
# have been created.
35
# has been created.
40
36
41
my $flags_required = [
37
my $flags_required = [
42
    {circulate  => 'circulate_remaining_permissions'},
38
    {circulate  => 'circulate_remaining_permissions'},
Lines 44-53 my $flags_required = [ Link Here
44
    {tools      => 'upload_local_cover_images'}
40
    {tools      => 'upload_local_cover_images'}
45
];
41
];
46
42
47
my %cookies = fetch CGI::Cookie;
43
my %cookies = CGI::Cookie->fetch;
44
my $sid = $cookies{'CGISESSID'}->value;
48
45
49
my $auth_failure = 1;
46
my $auth_failure = 1;
50
my ( $auth_status, $sessionID ) = check_cookie_auth( $cookies{'CGISESSID'}->value );
47
my ( $auth_status, $sessionID ) = check_cookie_auth( $sid );
51
foreach my $flag_required ( @{$flags_required} ) {
48
foreach my $flag_required ( @{$flags_required} ) {
52
    if ( my $flags = haspermission( C4::Context->config('user'), $flag_required ) ) {
49
    if ( my $flags = haspermission( C4::Context->config('user'), $flag_required ) ) {
53
        $auth_failure = 0 if $auth_status eq 'ok';
50
        $auth_failure = 0 if $auth_status eq 'ok';
Lines 56-95 foreach my $flag_required ( @{$flags_required} ) { Link Here
56
53
57
if ($auth_failure) {
54
if ($auth_failure) {
58
    $auth_status = 'denied' if $auth_status eq 'failed';
55
    $auth_status = 'denied' if $auth_status eq 'failed';
59
    send_reply($auth_status, "");
56
    send_reply( $auth_status );
60
    exit 0;
57
    exit 0;
61
}
58
}
62
59
63
our $uploaded_file = C4::UploadedFile->new($sessionID);
60
my $upload = Koha::Upload->new({ });
64
unless (defined $uploaded_file) {
61
if( !$upload || ! $upload->cgi ) {
65
    # FIXME - failed to create file for some reason
62
    send_reply( 'failed' );
66
    send_reply('failed', '');
63
} else {
67
    exit 0;
64
    send_reply( 'done', $upload->result );
68
}
65
}
69
$uploaded_file->max_size($ENV{'CONTENT_LENGTH'}); # may not be the file size, exactly
70
71
my $query;
72
$query = new CGI \&upload_hook;
73
$uploaded_file->done();
74
send_reply('done', $uploaded_file->id());
75
76
# FIXME - if possible, trap signal caused by user cancelling upload
77
# FIXME - something is wrong during cleanup: \t(in cleanup) Can't call method "commit" on unblessed reference at /usr/local/share/perl/5.8.8/CGI/Session/Driver/DBI.pm line 130 during global destruction.
78
exit 0;
66
exit 0;
79
67
80
sub upload_hook {
68
sub send_reply {    # response will be sent back as JSON
81
    my ($file_name, $buffer, $bytes_read, $session) = @_;
69
    my ( $upload_status, $data ) = @_;
82
    $uploaded_file->stash(\$buffer, $bytes_read);
83
    if ( ! $uploaded_file->name && $file_name ) { # save name on first chunk
84
        $uploaded_file->name($file_name);
85
    }
86
}
87
88
sub send_reply {
89
    my ($upload_status, $fileid) = @_;
90
91
    my $reply = CGI->new("");
70
    my $reply = CGI->new("");
92
    print $reply->header(-type => 'text/html');
71
    print $reply->header(-type => 'text/html');
93
    # response will be sent back as JSON
72
    print '{"status":"' . $upload_status .
94
    print '{"status":"' . $upload_status . '","fileid":"' . $fileid . '"}';
73
        ( $data? '","fileid":"' . $data: '' ) . '"}';
95
}
74
}
96
- 

Return to bug 14321