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

(-)a/Koha/Upload.pm (-11 / +109 lines)
Lines 51-56 use constant BYTES_DIGEST => 2048; Link Here
51
use Modern::Perl;
51
use Modern::Perl;
52
use CGI; # no utf8 flag, since it may interfere with binary uploads
52
use CGI; # no utf8 flag, since it may interfere with binary uploads
53
use Digest::MD5;
53
use Digest::MD5;
54
use Encode;
54
use File::Spec;
55
use File::Spec;
55
use IO::File;
56
use IO::File;
56
use Time::HiRes;
57
use Time::HiRes;
Lines 94-99 sub cgi { Link Here
94
    }
95
    }
95
}
96
}
96
97
98
=head2 count
99
100
    Returns number of uploaded files without errors
101
102
=cut
103
104
sub count {
105
    my ( $self ) = @_;
106
    return scalar grep { !exists $self->{files}->{$_}->{errcode} } keys $self->{files};
107
}
108
97
=head2 result
109
=head2 result
98
110
99
    Returns new object based on Class::Accessor.
111
    Returns new object based on Class::Accessor.
Lines 102-109 sub cgi { Link Here
102
114
103
sub result {
115
sub result {
104
    my ( $self ) = @_;
116
    my ( $self ) = @_;
105
    my @a = map { $self->{files}->{$_}->{id} } keys $self->{files};
117
    my @a = map { $self->{files}->{$_}->{id} }
106
    return join ',', @a;
118
        grep { !exists $self->{files}->{$_}->{errcode} }
119
        keys $self->{files};
120
    return @a? ( join ',', @a ): undef;
107
}
121
}
108
122
109
=head2 err
123
=head2 err
Lines 136-146 sub get { Link Here
136
    my ( @rv, $res);
150
    my ( @rv, $res);
137
    foreach my $r ( @$temp ) {
151
    foreach my $r ( @$temp ) {
138
        undef $res;
152
        undef $res;
153
        foreach( qw[id hashvalue filesize categorycode public] ) {
154
            $res->{$_} = $r->{$_};
155
        }
139
        $res->{name} = $r->{filename};
156
        $res->{name} = $r->{filename};
140
        $res->{path}= $self->_full_fname($r);
157
        $res->{path} = $self->_full_fname($r);
141
        if( $res->{path} && -r $res->{path} ) {
158
        if( $res->{path} && -r $res->{path} ) {
142
            $res->{fh} = IO::File->new( $res->{path}, "r" )
159
            if( $params->{filehandle} ) {
143
                if $params->{filehandle};
160
                my $fh = IO::File->new( $res->{path}, "r" );
161
                $fh->binmode if $fh;
162
                $res->{fh} = $fh;
163
            }
144
            push @rv, $res;
164
            push @rv, $res;
145
        } else {
165
        } else {
146
            $self->{files}->{ $r->{filename} }->{errcode}=5; #not readable
166
            $self->{files}->{ $r->{filename} }->{errcode}=5; #not readable
Lines 150-158 sub get { Link Here
150
    return wantarray? @rv: $res;
170
    return wantarray? @rv: $res;
151
}
171
}
152
172
173
=head2 delete
174
175
    Returns array of deleted filenames or undef.
176
    Since it now only accepts id as parameter, you should not expect more
177
    than one filename.
178
179
=cut
180
181
sub delete {
182
    my ( $self, $params ) = @_;
183
    return if !$params->{id};
184
    my @res;
185
    my $temp = $self->_lookup({ id => $params->{id} });
186
    foreach( @$temp ) {
187
        my $d = $self->_delete( $_ );
188
        push @res, $d if $d;
189
    }
190
    return if !@res;
191
    return @res;
192
}
193
153
sub DESTROY {
194
sub DESTROY {
154
}
195
}
155
196
197
# **************  HELPER ROUTINES / CLASS METHODS ******************************
198
199
=head2 getCategories
200
201
    getCategories returns a list of upload category codes and names
202
203
=cut
204
205
sub getCategories {
206
    my ( $class ) = @_;
207
    my $cats = C4::Koha::GetAuthorisedValues('UPLOAD');
208
    [ map {{ code => $_->{authorised_value}, name => $_->{lib} }} @$cats ];
209
}
210
211
=head2 httpheaders
212
213
    httpheaders returns http headers for a retrievable upload
214
    Will be extended by report 14282
215
216
=cut
217
218
sub httpheaders {
219
    my ( $class, $name ) = @_;
220
    return (
221
        '-type'       => 'application/octet-stream',
222
        '-attachment' => $name,
223
    );
224
}
225
156
# **************  INTERNAL ROUTINES ********************************************
226
# **************  INTERNAL ROUTINES ********************************************
157
227
158
sub _init {
228
sub _init {
Lines 192-198 sub _create_file { Link Here
192
    } else {
262
    } else {
193
        my $dir = $self->_dir;
263
        my $dir = $self->_dir;
194
        my $fn = $self->{files}->{$filename}->{hash}. '_'. $filename;
264
        my $fn = $self->{files}->{$filename}->{hash}. '_'. $filename;
195
        if( -e "$dir/$fn" ) {
265
        if( -e "$dir/$fn" && @{ $self->_lookup({
266
          hashvalue => $self->{files}->{$filename}->{hash} }) } ) {
267
        # if the file exists and it is registered, then set error
196
            $self->{files}->{$filename}->{errcode} = 1; #already exists
268
            $self->{files}->{$filename}->{errcode} = 1; #already exists
197
            return;
269
            return;
198
        }
270
        }
Lines 232-237 sub _full_fname { Link Here
232
304
233
sub _hook {
305
sub _hook {
234
    my ( $self, $filename, $buffer, $bytes_read, $data ) = @_;
306
    my ( $self, $filename, $buffer, $bytes_read, $data ) = @_;
307
    $filename= Encode::decode_utf8( $filename ); # UTF8 chars in filename
235
    $self->_compute( $filename, $buffer );
308
    $self->_compute( $filename, $buffer );
236
    my $fh = $self->_fh( $filename ) // $self->_create_file( $filename );
309
    my $fh = $self->_fh( $filename ) // $self->_create_file( $filename );
237
    print $fh $buffer if $fh;
310
    print $fh $buffer if $fh;
Lines 269-287 sub _register { Link Here
269
sub _lookup {
342
sub _lookup {
270
    my ( $self, $params ) = @_;
343
    my ( $self, $params ) = @_;
271
    my $dbh = C4::Context->dbh;
344
    my $dbh = C4::Context->dbh;
272
    my $sql = 'SELECT id,hashvalue,filename,dir,categorycode '.
345
    my $sql = 'SELECT id,hashvalue,filename,dir,filesize,categorycode,public '.
273
        'FROM uploaded_files ';
346
        'FROM uploaded_files ';
347
    my @pars;
274
    if( $params->{id} ) {
348
    if( $params->{id} ) {
275
        $sql.= "WHERE id=?";
349
        return [] if $params->{id} !~ /^\d+(,\d+)*$/;
276
    } else {
350
        $sql.= "WHERE id IN ($params->{id})";
351
        @pars = ();
352
    } elsif( $params->{hashvalue} ) {
277
        $sql.= "WHERE hashvalue=?";
353
        $sql.= "WHERE hashvalue=?";
354
        @pars = ( $params->{hashvalue} );
355
    } else {
356
        $sql.= "WHERE filename LIKE ? OR hashvalue LIKE ?";
357
        @pars = ( '%'.$params->{term}.'%', '%'.$params->{term}.'%' );
278
    }
358
    }
279
    $sql.= $self->{public}? " AND public=1": '';
359
    $sql.= $self->{public}? " AND public=1": '';
280
    my $temp= $dbh->selectall_arrayref( $sql, { Slice => {} },
360
    $sql.= ' ORDER BY id';
281
        ( $params->{id} // $params->{hashvalue} // 0 ) );
361
    my $temp= $dbh->selectall_arrayref( $sql, { Slice => {} }, @pars );
282
    return $temp;
362
    return $temp;
283
}
363
}
284
364
365
sub _delete {
366
    my ( $self, $rec ) = @_;
367
    my $dbh = C4::Context->dbh;
368
    my $sql = 'DELETE FROM uploaded_files WHERE id=?';
369
    my $file = $self->_full_fname($rec);
370
    if( !-e $file ) { # we will just delete the record
371
        # TODO Should we add a trace here for the missing file?
372
        $dbh->do( $sql, undef, ( $rec->{id} ) );
373
        return $rec->{filename};
374
    } elsif( unlink($file) ) {
375
        $dbh->do( $sql, undef, ( $rec->{id} ) );
376
        return $rec->{filename};
377
    }
378
    $self->{files}->{ $rec->{filename} }->{errcode} = 7;
379
    #NOTE: errcode=6 is used to report successful delete (see template)
380
    return;
381
}
382
285
sub _compute {
383
sub _compute {
286
# Computes hash value when sub hook feeds the first block
384
# Computes hash value when sub hook feeds the first block
287
# For temporary files, the id is made unique with time
385
# For temporary files, the id is made unique with time
(-)a/cataloguing/value_builder/upload.pl (-132 / +21 lines)
Lines 4-9 Link Here
4
4
5
# This file is part of Koha.
5
# This file is part of Koha.
6
#
6
#
7
# Copyright (C) 2015 Rijksmuseum
7
# Copyright (C) 2011-2012 BibLibre
8
# Copyright (C) 2011-2012 BibLibre
8
#
9
#
9
# Koha is free software; you can redistribute it and/or modify it
10
# Koha is free software; you can redistribute it and/or modify it
Lines 20-164 Link Here
20
# along with Koha; if not, see <http://www.gnu.org/licenses>.
21
# along with Koha; if not, see <http://www.gnu.org/licenses>.
21
22
22
use Modern::Perl;
23
use Modern::Perl;
23
use CGI qw/-utf8/;
24
24
25
use C4::Auth;
25
# This plugin does not use the plugin launcher. It refers to tools/upload.pl.
26
use C4::Context;
26
# That script and template support using it as a plugin.
27
use C4::Output;
27
28
use C4::UploadedFiles;
28
# If the plugin is called with the pattern [id=some_hashvalue] in the
29
# corresponding field, it starts the upload script as a search, providing
30
# the possibility to delete the uploaded file. If the field is empty, you
31
# can upload a new file.
29
32
30
my $builder = sub {
33
my $builder = sub {
31
    my ( $params ) = @_;
34
    my ( $params ) = @_;
32
    my $function_name = $params->{id};
35
    return <<"SCRIPT";
33
    my $res           = "
36
<script type=\"text/javascript\">
34
    <script type=\"text/javascript\">
37
        function Click$params->{id}(event) {
35
        function Click$function_name(event) {
36
            var index = event.data.id;
38
            var index = event.data.id;
37
            var id = document.getElementById(index).value;
39
            var str = document.getElementById(index).value;
38
            var IsFileUploadUrl=0;
40
            var myurl, term;
39
            if (id.match(/opac-retrieve-file/)) {
41
            if( str && str.match(/id=([0-9a-f]+)/) ) {
40
                IsFileUploadUrl=1;
42
                term = RegExp.\$1;
41
            }
43
                myurl = '../tools/upload.pl?op=search&index='+index+'&term='+term+'&plugin=1';
42
            if(id.match(/id=([0-9a-f]+)/)){
43
                id = RegExp.\$1;
44
            }
45
            var newin=window.open(\"../cataloguing/plugin_launcher.pl?plugin_name=upload.pl&index=\"+index+\"&id=\"+id+\"&from_popup=0\"+\"&IsFileUploadUrl=\"+IsFileUploadUrl, 'upload', 'width=600,height=400,toolbar=false,scrollbars=no');
46
            newin.focus();
47
        }
48
    </script>
49
";
50
    return $res;
51
};
52
53
my $launcher = sub {
54
    my ( $params ) = @_;
55
    my $input = $params->{cgi};
56
    my $index = $input->param('index');
57
    my $id = $input->param('id');
58
    my $delete = $input->param('delete');
59
    my $uploaded_file = $input->param('uploaded_file');
60
    my $from_popup = $input->param('from_popup');
61
    my $isfileuploadurl = $input->param('IsFileUploadUrl');
62
    my $dangling = C4::UploadedFiles::DanglingEntry($id,$isfileuploadurl);
63
    my $template_name;
64
    if ($delete || ($id && ($dangling==0 || $dangling==1))) {
65
        $template_name = "upload_delete_file.tt";
66
    }
67
    else {
68
        $template_name = "upload.tt";
69
    }
70
71
    my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
72
        {   template_name   => "cataloguing/value_builder/$template_name",
73
            query           => $input,
74
            type            => "intranet",
75
            authnotrequired => 0,
76
            flagsrequired   => { editcatalogue => '*' },
77
            debug           => 1,
78
        }
79
    );
80
81
    if ($dangling==2) {
82
        $template->param( dangling => 1 );
83
    }
84
85
    # Dealing with the uploaded file
86
    my $dir = $input->param('uploadcategory');
87
    if ($uploaded_file and $dir) {
88
        my $fh = $input->upload('uploaded_file');
89
90
        $id = C4::UploadedFiles::UploadFile($uploaded_file, $dir, $fh->handle);
91
        my $OPACBaseURL = C4::Context->preference('OPACBaseURL') // '';
92
        $OPACBaseURL =~ s#/$##;
93
        if (!$OPACBaseURL) {
94
            $template->param(MissingURL => 1);
95
        }
96
        if($id && $OPACBaseURL) {
97
            my $return = "$OPACBaseURL/cgi-bin/koha/opac-retrieve-file.pl?id=$id";
98
            $template->param(
99
                success => 1,
100
                return => $return,
101
                uploaded_file => $uploaded_file,
102
            );
103
        } else {
104
            $template->param(error => 1);
105
        }
106
    } elsif ($delete || ($id && ($dangling==0 || $dangling==1))) {
107
        # If there's already a file uploaded for this field,
108
        # We handle its deletion
109
        if ($delete) {
110
            if(C4::UploadedFiles::DelUploadedFile($id)==0) {;
111
                $template->param(error => 1);
112
            } else {
44
            } else {
113
                $template->param(success => 1);
45
                myurl = '../tools/upload.pl?op=new&index='+index+'&plugin=1';
114
            }
46
            }
47
            window.open( myurl, 'tag_editor', 'width=800,height=400,toolbar=false,scrollbars=yes' );
115
        }
48
        }
116
    } else {
49
</script>
117
        my $upload_path = C4::Context->config('upload_path');
50
SCRIPT
118
        if ($upload_path) {
119
            my $filefield = CGI::filefield(
120
                -name => 'uploaded_file',
121
                -size => 50,
122
            );
123
            $template->param(
124
                filefield => $filefield,
125
                uploadcategories => C4::UploadedFiles::getCategories(),
126
            );
127
        } else {
128
            $template->param( error_upload_path_not_configured => 1 );
129
        }
130
131
        if (!$uploaded_file && !$dir && $from_popup) {
132
            $template->param(error_nothing_selected => 1);
133
        }
134
        elsif (!$uploaded_file && $dir) {
135
            $template->param(error_no_file_selected => 1);
136
        }
137
        if ($uploaded_file and not $dir) {
138
            $template->param(error_no_dir_selected => 1);
139
        }
140
141
    }
142
143
    $template->param(
144
        index => $index,
145
        id => $id,
146
    );
147
148
    output_html_with_http_headers $input, $cookie, $template->output;
149
};
51
};
150
52
151
return { builder => $builder, launcher => $launcher };
53
return { builder => $builder };
152
153
1;
154
155
__END__
156
157
=head1 upload.pl
158
159
This plugin allows to upload files on the server and reference it in a marc
160
field.
161
162
It uses config variable upload_path and pref OPACBaseURL.
163
164
=cut
(-)a/koha-tmpl/intranet-tmpl/prog/en/js/file-upload.js (-3 / +3 lines)
Lines 1-4 Link Here
1
function AjaxUpload ( input, progressbar, callback ) {
1
function AjaxUpload ( input, progressbar, xtra, callback ) {
2
    // input and progressbar are jQuery objects
2
    // input and progressbar are jQuery objects
3
    // callback is the callback function for completion
3
    // callback is the callback function for completion
4
    var formData= new FormData();
4
    var formData= new FormData();
Lines 6-12 function AjaxUpload ( input, progressbar, callback ) { Link Here
6
        formData.append( "uploadfile", file );
6
        formData.append( "uploadfile", file );
7
    });
7
    });
8
    var xhr= new XMLHttpRequest();
8
    var xhr= new XMLHttpRequest();
9
    var url= '/cgi-bin/koha/tools/upload-file.pl';
9
    var url= '/cgi-bin/koha/tools/upload-file.pl?' + xtra;
10
    progressbar.val( 0 );
10
    progressbar.val( 0 );
11
    progressbar.next('.fileuploadpercent').text( '0' );
11
    progressbar.next('.fileuploadpercent').text( '0' );
12
    xhr.open('POST', url, true);
12
    xhr.open('POST', url, true);
Lines 21-27 function AjaxUpload ( input, progressbar, callback ) { Link Here
21
            progressbar.val( 100 );
21
            progressbar.val( 100 );
22
            progressbar.next('.fileuploadpercent').text( '100' );
22
            progressbar.next('.fileuploadpercent').text( '100' );
23
        }
23
        }
24
        callback( data.status, data.fileid );
24
        callback( data.status, data.fileid, data.errors );
25
    }
25
    }
26
    xhr.onerror = function (e) {
26
    xhr.onerror = function (e) {
27
        // Probably only fires for network failure
27
        // Probably only fires for network failure
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/offline_circ/process_koc.tt (-1 / +1 lines)
Lines 20-26 function StartUpload() { Link Here
20
    $("#fileuploadstatus").show();
20
    $("#fileuploadstatus").show();
21
    $("form#processfile #uploadedfileid").val('');
21
    $("form#processfile #uploadedfileid").val('');
22
    $("form#enqueuefile #uploadedfileid").val('');
22
    $("form#enqueuefile #uploadedfileid").val('');
23
    xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), cbUpload );
23
    xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), '', cbUpload );
24
}
24
}
25
25
26
function cbUpload( status, fileid ) {
26
function cbUpload( status, fileid ) {
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/stage-marc-import.tt (-1 / +1 lines)
Lines 39-45 function StartUpload() { Link Here
39
    $("#processfile").hide();
39
    $("#processfile").hide();
40
    $("#fileuploadstatus").show();
40
    $("#fileuploadstatus").show();
41
    $("#uploadedfileid").val('');
41
    $("#uploadedfileid").val('');
42
    xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), cbUpload );
42
    xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), '', cbUpload );
43
    $("#fileuploadcancel").show();
43
    $("#fileuploadcancel").show();
44
}
44
}
45
function CancelUpload() {
45
function CancelUpload() {
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-images.tt (-1 / +1 lines)
Lines 18-24 function StartUpload() { Link Here
18
    $('#uploadform button.submit').prop('disabled',true);
18
    $('#uploadform button.submit').prop('disabled',true);
19
    $("#fileuploadstatus").show();
19
    $("#fileuploadstatus").show();
20
    $("#uploadedfileid").val('');
20
    $("#uploadedfileid").val('');
21
    xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), cbUpload );
21
    xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), '', cbUpload );
22
}
22
}
23
function cbUpload( status, fileid ) {
23
function cbUpload( status, fileid ) {
24
    if( status=='done' ) {
24
    if( status=='done' ) {
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload.tt (+306 lines)
Line 0 Link Here
1
[% INCLUDE 'doc-head-open.inc' %]
2
[% USE Koha %]
3
[% IF plugin %]
4
    <title>Upload plugin</title>
5
[% ELSE %]
6
    <title>Koha &rsaquo; Tools &rsaquo; Upload</title>
7
[% END %]
8
[% INCLUDE 'doc-head-close.inc' %]
9
10
[% BLOCK plugin_pars %]
11
    [% IF plugin %]
12
        <input type="hidden" name="plugin" value="1" />
13
        <input type="hidden" name="index" value="[% index %]" />
14
    [% END %]
15
[% END %]
16
17
[% BLOCK breadcrumbs %]
18
    <div id="breadcrumbs">
19
        <a href="/cgi-bin/koha/mainpage.pl">Home</a>
20
        &rsaquo;
21
        <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a>
22
        &rsaquo;
23
        <a href="/cgi-bin/koha/tools/upload.pl">Upload</a>
24
        &rsaquo;
25
        <span id="lastbreadcrumb">
26
        [% IF mode=='new' || mode =='deleted'%]
27
            Add new upload or search
28
        [% ELSE %]
29
            Results
30
        [% END %]
31
        </span>
32
    </div>
33
[% END %]
34
35
[% BLOCK form_new %]
36
    <form method="post" action="[% SCRIPT_NAME %]" id="uploadfile" enctype="multipart/form-data">
37
        [% PROCESS plugin_pars %]
38
        <fieldset class="rows" id="uploadform">
39
        <legend>Upload new files</legend>
40
        <ol>
41
        <li>
42
        <div id="fileuploadform">
43
            <label for="fileToUpload">Select files: </label>
44
            <input type="file" id="fileToUpload" name="fileToUpload" multiple/>
45
        </div>
46
        </li>
47
        <li>
48
            <label for="uploadcategory">Category: </label>
49
                      <select id="uploadcategory" name="uploadcategory">
50
                      [% IF !plugin %]
51
                          <option value="" disabled hidden selected></option>
52
                      [% END %]
53
                      [% FOREACH cat IN uploadcategories %]
54
                          <option value="[% cat.code %]">[% cat.name %]</option>
55
                      [% END %]
56
                      </select>
57
        </li>
58
        [% IF !plugin %]
59
            <li>
60
                <div class="hint">Note: For temporary uploads do not select a category. The file will not be made available for public downloading.</div>
61
            </li>
62
        [% END %]
63
        <li>
64
            [% IF plugin %]
65
                <input type="hidden" id="public" name="public" value="1"/>
66
            [% ELSE %]
67
                <label>&nbsp;</label>
68
                <input type="checkbox" id="public" name="public">
69
                    Allow public downloads
70
                </input>
71
            [% END %]
72
        </li>
73
        </ol>
74
        <fieldset class="action">
75
            <button id="fileuploadbutton" onclick="StartUpload(); return false;">Upload</button>
76
            <button id="fileuploadcancel" onclick="CancelUpload(); return false;">Cancel</button>
77
        </fieldset>
78
        </fieldset>
79
        <div id="fileuploadpanel">
80
            <div id="fileuploadstatus">Upload progress:
81
            <progress id="fileuploadprogress" min="0" max="100" value="0">
82
            </progress>
83
            <span class="fileuploadpercent">0</span>%
84
            </div>
85
            <div id="fileuploadfailed"></div>
86
        </div>
87
    </form>
88
[% END %]
89
90
[% BLOCK form_search %]
91
    <form method="post" id="searchfile" action="[% SCRIPT_NAME %]" enctype="multipart/form-data">
92
        [% PROCESS plugin_pars %]
93
        <input type="hidden" name="op" value="search"/>
94
        <fieldset class="rows">
95
        <legend>Search uploads by name or hashvalue</legend>
96
        <ol>
97
        <li>
98
            <label for="searchupload">Search term: </label>
99
            <input type="text" id="term" name="term" value=""/>
100
        </li>
101
        <li>
102
            <fieldset class="action">
103
                <button id="searchbutton" class="submit">Search</button>
104
            </fieldset>
105
        </li>
106
        </ol>
107
        </fieldset>
108
    </form>
109
[% END %]
110
111
[% BLOCK submitter %]
112
    <form id="submitter" style="display:none;" method="post">
113
        [% PROCESS plugin_pars %]
114
        <input type="hidden" name="op" id="op" value=""/>
115
        <input type="hidden" name="id" id="id" value="" />
116
        <input type="hidden" name="msg" id="msg" value="" />
117
    </form>
118
[% END %]
119
120
[% BLOCK closer %]
121
    [% IF plugin %]
122
        <form id="closer">
123
            <fieldset class="action">
124
                <button onclick="window.close();return false;">Close</button>
125
            </fieldset>
126
        </form>
127
    [% END %]
128
[% END %]
129
130
[% BLOCK table_results %]
131
    <table>
132
    <thead>
133
    <tr>
134
        <th>Filename</td>
135
        <th>Size</td>
136
        <th>Hashvalue</td>
137
        <th>Category</td>
138
        <th>Public</td>
139
        <th>Actions</td>
140
    </tr>
141
    </thead>
142
    <tbody>
143
    [% FOREACH record IN uploads %]
144
    <tr>
145
        <td>[% record.name %]</td>
146
        <td>[% record.filesize %]</td>
147
        <td>[% record.hashvalue %]</td>
148
        <td>[% record.categorycode %]</td>
149
        <td>[% IF record.public %]Yes[% ELSE %]No[% END %]</td>
150
        <td>
151
            [% IF plugin %]
152
                <a href="" onclick="Choose('[% record.hashvalue %]'); return false;">Choose</a>&nbsp;
153
            [% END %]
154
            <a href="" onclick="SubmitMe( 'download', [% record.id %] ); return false;">Download</a>&nbsp;
155
            <a href="" onclick="ClearField(); SubmitMe( 'delete', [% record.id %] ); return false;">Delete</a>
156
        </td>
157
   </tr>
158
   [% END %]
159
   </tbody>
160
   </table>
161
[% END %]
162
163
<style type="text/css">
164
    #fileuploadstatus,#fileuploadfailed { display : none; }
165
    #fileuploadstatus { margin:.4em; }
166
    #fileuploadprogress { width:150px;height:10px;border:1px solid #666;background:url('[% interface %]/[% theme %]/img/progress.png') -300px 0px no-repeat; }
167
</style>
168
169
<script type="text/javascript">
170
//<![CDATA[
171
    var errMESSAGES = [
172
        "Error 0: Not in use",
173
        _("This file already exists (in this category)."),
174
        _("File could not be created. Check permissions."),
175
        _("Your koha-conf.xml does not contain a valid upload_path."),
176
        _("No temporary directory found."),
177
        _("File could not be read."),
178
        _("File has been deleted."),
179
        _("File could not be deleted."),
180
    ];
181
//]]>
182
</script>
183
<script type="text/javascript" src="[% themelang %]/js/file-upload.js"></script>
184
<script type="text/javascript">
185
//<![CDATA[
186
function StartUpload() {
187
    if( $('#fileToUpload').prop('files').length == 0 ) return;
188
    $('#fileToUpload').prop('disabled',true);
189
    $('#fileuploadbutton').hide();
190
    $("#fileuploadcancel").show();
191
    $("#fileuploadfailed").html('');
192
    $("#myalerts").hide('');
193
    $("#myalerts").html('');
194
    $("#fileuploadstatus").show();
195
    $("#uploadedfileid").val('');
196
    $("#searchfile").hide();
197
    $("#lastbreadcrumb").text( _("Add a new upload") );
198
199
    var xtra='';
200
    if( $("#uploadcategory").val() )
201
        xtra= xtra + 'category=' + $("#uploadcategory").val();
202
    if( $('#public').prop('checked') || $('#public').val() )
203
        // the second condition refers to the plugin environment
204
        xtra = xtra + '&public=1';
205
    xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), xtra, cbUpload );
206
}
207
function CancelUpload() {
208
    if( xhr ) xhr.abort();
209
    $("#fileuploadstatus").hide();
210
    $('#fileToUpload').prop('disabled', false);
211
    $('#fileuploadbutton').show();
212
    $("#fileuploadcancel").hide();
213
    $("#fileuploadfailed").show();
214
    $("#fileuploadfailed").text( _("Upload status: Cancelled ") );
215
}
216
function cbUpload( status, fileid, err ) {
217
    if( status=='done' ) {
218
        var e = err? JSON.stringify(err): '';
219
        SubmitMe( 'search', fileid, e );
220
    } else {
221
        $('#fileToUpload').prop('disabled', false);
222
        $('#fileuploadbutton').show();
223
        $("#fileuploadcancel").hide();
224
        $("#fileuploadstatus").hide();
225
        $("#fileuploadfailed").show();
226
        $("#fileuploadfailed").html( _("Upload status: ") +
227
            ( status=='failed'? _("Failed"):
228
            ( status=='denied'? _("Denied"): status ))
229
        );
230
        ShowAlerts( err );
231
    }
232
}
233
function ShowAlerts(err) {
234
    var str = '';
235
    for( var file in err ) {
236
        str= str + '<p>' + file + ': ' +
237
            errMESSAGES[ err[file] ] + '</p>';
238
    }
239
    $('#myalerts').html(str);
240
    $('#myalerts').show();
241
}
242
function SubmitMe(op, id, msg ) {
243
    $("#submitter #op").val( op );
244
    $("#submitter #id").val( id );
245
    $("#submitter #msg").val( msg );
246
    $("#submitter").submit();
247
}
248
function ClearField() {
249
    [% IF plugin %]
250
        $(window.opener.document).find('#[% index %]').val( '' );
251
    [% END %]
252
}
253
function Choose(hashval) {
254
    var res = '[% Koha.Preference('OPACBaseURL') %]';
255
    res = res.replace( /\/$/, '');
256
    res = res + '/cgi-bin/koha/opac-retrieve-file.pl?id=' + hashval;
257
    [% IF index %]
258
        $(window.opener.document).find('#[% index %]').val( res );
259
    [% END %]
260
    window.close();
261
}
262
$(document).ready(function() {
263
    [% IF msg %]
264
        ShowAlerts( [% msg %] );
265
    [% END %]
266
    $("#fileuploadcancel").hide();
267
});
268
//]]>
269
</script>
270
</head>
271
272
<body id="tools_upload" class="tools">
273
[% IF !plugin %]
274
    [% INCLUDE 'header.inc' %]
275
    [% INCLUDE 'cat-search.inc' %]
276
    [% PROCESS breadcrumbs %]
277
[% END %]
278
279
<div id="doc3" class="yui-t2">
280
   <div id="bd">
281
    <div id="yui-main">
282
    <div class="yui-b">
283
284
<h1>Upload</h1>
285
286
<div class="dialog alert" id="myalerts" style="display:none;"></div>
287
288
[% PROCESS submitter %]
289
[% IF mode == 'new' || mode == 'deleted' %]
290
    [% PROCESS form_new %]
291
    [% PROCESS form_search %]
292
[% ELSIF mode == 'report' %]
293
    [% IF uploads %]
294
        <h3>Your request gave the following results:</h3>
295
        [% PROCESS table_results %]
296
    [% ELSE %]
297
        <h4>Sorry, your request had no results.</h4>
298
    [% END %]
299
[% END %]
300
[% PROCESS closer %]
301
302
</div>
303
</div>
304
</div>
305
306
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/tools/upload-file.pl (-10 / +27 lines)
Lines 18-27 Link Here
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 Modern::Perl;
20
use Modern::Perl;
21
use CGI::Cookie;
22
21
23
use CGI qw ( -utf8 );
22
use CGI qw ( -utf8 );
24
#use CGI::Session;
23
use CGI::Cookie;
24
use JSON;
25
25
use C4::Context;
26
use C4::Context;
26
use C4::Auth qw/check_cookie_auth haspermission/;
27
use C4::Auth qw/check_cookie_auth haspermission/;
27
use Koha::Upload;
28
use Koha::Upload;
Lines 57-74 if ($auth_failure) { Link Here
57
    exit 0;
58
    exit 0;
58
}
59
}
59
60
60
my $upload = Koha::Upload->new({ });
61
my $upload = Koha::Upload->new( extr_pars($ENV{QUERY_STRING}) );
61
if( !$upload || !$upload->cgi || $upload->err ) {
62
if( !$upload || !$upload->cgi || !$upload->count ) {
62
    send_reply( 'failed' );
63
    # not one upload succeeded
64
    send_reply( 'failed', undef, $upload? $upload->err: undef );
63
} else {
65
} else {
64
    send_reply( 'done', $upload->result );
66
    # in case of multiple uploads, at least one got through
67
    send_reply( 'done', $upload->result, $upload->err );
65
}
68
}
66
exit 0;
69
exit 0;
67
70
68
sub send_reply {    # response will be sent back as JSON
71
sub send_reply {    # response will be sent back as JSON
69
    my ( $upload_status, $data ) = @_;
72
    my ( $upload_status, $data, $error ) = @_;
70
    my $reply = CGI->new("");
73
    my $reply = CGI->new("");
71
    print $reply->header(-type => 'text/html');
74
    print $reply->header( -type => 'text/html', -charset => 'UTF-8' );
72
    print '{"status":"' . $upload_status .
75
    print JSON::encode_json({
73
        ( $data? '","fileid":"' . $data: '' ) . '"}';
76
        status => $upload_status,
77
        fileid => $data,
78
        errors => $error,
79
   });
80
}
81
82
sub extr_pars {
83
    my ( $qstr ) = @_;
84
    my $rv = {};
85
    foreach my $p ( qw[public category] ) {
86
        if( $qstr =~ /(^|&)$p=(\w+)(&|$)/ ) {
87
            $rv->{$p} = $2;
88
        }
89
    }
90
    return $rv;
74
}
91
}
(-)a/tools/upload.pl (-1 / +96 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# This file is part of Koha.
4
#
5
# Copyright (C) 2015 Rijksmuseum
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# 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 Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use CGI qw/-utf8/;
22
use JSON;
23
24
use C4::Auth;
25
use C4::Output;
26
use Koha::Upload;
27
28
my $input = CGI::->new;
29
my $op = $input->param('op') // 'new';
30
my $plugin = $input->param('plugin');
31
my $index = $input->param('index'); # MARC editor input field id
32
my $term = $input->param('term');
33
my $id = $input->param('id');
34
my $msg = $input->param('msg');
35
36
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
37
    {   template_name   => "tools/upload.tt",
38
        query           => $input,
39
        type            => "intranet",
40
        authnotrequired => 0,
41
        flagsrequired   => { editcatalogue => '*' },
42
    }
43
);
44
45
$template->param(
46
    plugin => $plugin,
47
    index  => $index,
48
);
49
if( $op eq 'new' ) {
50
    $template->param(
51
        mode => 'new',
52
        uploadcategories => Koha::Upload->getCategories,
53
    );
54
    output_html_with_http_headers $input, $cookie, $template->output;
55
} elsif( $op eq 'search' ) {
56
    my $h = $id? { id => $id }: { term => $term };
57
    my @uploads = Koha::Upload->new->get( $h );
58
    $template->param(
59
        mode => 'report',
60
        msg => $msg,
61
        uploads => \@uploads,
62
    );
63
    output_html_with_http_headers $input, $cookie, $template->output;
64
} elsif( $op eq 'delete' ) {
65
    # delete only takes the id parameter
66
    my $upl = Koha::Upload->new;
67
    my ( $fn ) = $upl->delete({ id => $id });
68
    my $e = $upl->err;
69
    my $msg = $fn? JSON::to_json({ $fn => 6 }):
70
        $e? JSON::to_json( $e ): undef;
71
    $template->param(
72
        mode => 'deleted',
73
        msg => $msg,
74
        uploadcategories => $upl->getCategories,
75
    );
76
    output_html_with_http_headers $input, $cookie, $template->output;
77
} elsif( $op eq 'download' ) {
78
    my $upl = Koha::Upload->new;
79
    my $rec = $upl->get({ id => $id, filehandle => 1 });
80
    my $fh = $rec->{fh};
81
    if( !$rec || !$fh ) {
82
        $template->param(
83
            mode => 'new',
84
            msg => JSON::to_json({ $id => 5 }),
85
            uploadcategories => $upl->getCategories,
86
        );
87
        output_html_with_http_headers $input, $cookie, $template->output;
88
    } else {
89
        my @hdr = $upl->httpheaders( $rec->{name} );
90
        print $input->header( @hdr );
91
        while( <$fh> ) {
92
            print $_;
93
        }
94
        $fh->close;
95
    }
96
}

Return to bug 14321