Bugzilla – Attachment 41501 Details for
Bug 14321
Merge UploadedFile and UploadedFiles into Koha::Upload
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 14321: Redirect upload plugin to general upload script
Bug-14321-Redirect-upload-plugin-to-general-upload.patch (text/plain), 32.54 KB, created by
Marcel de Rooy
on 2015-08-14 12:33:19 UTC
(
hide
)
Description:
Bug 14321: Redirect upload plugin to general upload script
Filename:
MIME Type:
Creator:
Marcel de Rooy
Created:
2015-08-14 12:33:19 UTC
Size:
32.54 KB
patch
obsolete
>From 9936ac15412f0ac95b65a298749c3167580a17a9 Mon Sep 17 00:00:00 2001 >From: Marcel de Rooy <m.de.rooy@rijksmuseum.nl> >Date: Sat, 8 Aug 2015 17:28:25 +0200 >Subject: [PATCH] Bug 14321: Redirect upload plugin to general upload script >Content-Type: text/plain; charset=utf-8 > >This patch makes the following changes to achieve that: >[1] Adds a tools/upload script and template. It allows to upload multiple > files at once. >[2] Adds additional parameter to js function AjaxUpload (for category > and public column). >[3] Adds methods to Upload: count, delete, getCategories, httpheaders. >[4] Makes upload-file return error messages in JSON. For a multiple upload, > we could have some files with errors and others without errors. > The upload is now marked as Failed only if there was no upload at all. >[5] Adds decode_utf8 statement for UTF-8 chars in filenames (in the CGI > hook). Note that we do not want the -utf8 flag here for binary uploads. >[6] The upload plugin is converted to use tools/upload with plugin param. > Deleting an upload is now presented via the search results form. > >NOTE: A unit test is supplied in a follow-up patch. > >Test plan: >[1] Upload three files via tools/upload.pl with a category and marked as > public. Check the results in the table. >[2] Pick one new file and one of the files of step 1. Upload them in the > same category. One upload should succeed. Check for reported error. >[3] Upload a file via stage-marc-import. Stage it. >[4] Go to Cataloguing editor. Connect upload.pl to field 856$u. > In an empty 856$u, click the tag editor. Upload a file and click Choose. > Save the record. Open the record in the OPAC and click the link. > Copy this link to your clipboard for step 5. >[5] Go back to editor. Click the tag editor on the same 856 field. > Choose for Delete. > Open the link in your clipboard again. >[6] Check the process of upload, search, download and delete of an upload > with some diacritical characters in the filename. >--- > Koha/Upload.pm | 120 +++++++- > cataloguing/value_builder/upload.pl | 153 ++-------- > koha-tmpl/intranet-tmpl/prog/en/js/file-upload.js | 6 +- > .../prog/en/modules/offline_circ/process_koc.tt | 2 +- > .../prog/en/modules/tools/stage-marc-import.tt | 2 +- > .../prog/en/modules/tools/upload-images.tt | 2 +- > .../intranet-tmpl/prog/en/modules/tools/upload.tt | 306 ++++++++++++++++++++ > tools/upload-file.pl | 37 ++- > tools/upload.pl | 96 ++++++ > 9 files changed, 565 insertions(+), 159 deletions(-) > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload.tt > create mode 100755 tools/upload.pl > >diff --git a/Koha/Upload.pm b/Koha/Upload.pm >index 8501218..08cd125 100644 >--- a/Koha/Upload.pm >+++ b/Koha/Upload.pm >@@ -51,6 +51,7 @@ use constant BYTES_DIGEST => 2048; > use Modern::Perl; > use CGI; # no utf8 flag, since it may interfere with binary uploads > use Digest::MD5; >+use Encode; > use File::Spec; > use IO::File; > use Time::HiRes; >@@ -94,6 +95,17 @@ sub cgi { > } > } > >+=head2 count >+ >+ Returns number of uploaded files without errors >+ >+=cut >+ >+sub count { >+ my ( $self ) = @_; >+ return scalar grep { !exists $self->{files}->{$_}->{errcode} } keys $self->{files}; >+} >+ > =head2 result > > Returns new object based on Class::Accessor. >@@ -102,8 +114,10 @@ sub cgi { > > sub result { > my ( $self ) = @_; >- my @a = map { $self->{files}->{$_}->{id} } keys $self->{files}; >- return join ',', @a; >+ my @a = map { $self->{files}->{$_}->{id} } >+ grep { !exists $self->{files}->{$_}->{errcode} } >+ keys $self->{files}; >+ return @a? ( join ',', @a ): undef; > } > > =head2 err >@@ -136,11 +150,17 @@ sub get { > my ( @rv, $res); > foreach my $r ( @$temp ) { > undef $res; >+ foreach( qw[id hashvalue filesize categorycode public] ) { >+ $res->{$_} = $r->{$_}; >+ } > $res->{name} = $r->{filename}; >- $res->{path}= $self->_full_fname($r); >+ $res->{path} = $self->_full_fname($r); > if( $res->{path} && -r $res->{path} ) { >- $res->{fh} = IO::File->new( $res->{path}, "r" ) >- if $params->{filehandle}; >+ if( $params->{filehandle} ) { >+ my $fh = IO::File->new( $res->{path}, "r" ); >+ $fh->binmode if $fh; >+ $res->{fh} = $fh; >+ } > push @rv, $res; > } else { > $self->{files}->{ $r->{filename} }->{errcode}=5; #not readable >@@ -150,9 +170,59 @@ sub get { > return wantarray? @rv: $res; > } > >+=head2 delete >+ >+ Returns array of deleted filenames or undef. >+ Since it now only accepts id as parameter, you should not expect more >+ than one filename. >+ >+=cut >+ >+sub delete { >+ my ( $self, $params ) = @_; >+ return if !$params->{id}; >+ my @res; >+ my $temp = $self->_lookup({ id => $params->{id} }); >+ foreach( @$temp ) { >+ my $d = $self->_delete( $_ ); >+ push @res, $d if $d; >+ } >+ return if !@res; >+ return @res; >+} >+ > sub DESTROY { > } > >+# ************** HELPER ROUTINES / CLASS METHODS ****************************** >+ >+=head2 getCategories >+ >+ getCategories returns a list of upload category codes and names >+ >+=cut >+ >+sub getCategories { >+ my ( $class ) = @_; >+ my $cats = C4::Koha::GetAuthorisedValues('UPLOAD'); >+ [ map {{ code => $_->{authorised_value}, name => $_->{lib} }} @$cats ]; >+} >+ >+=head2 httpheaders >+ >+ httpheaders returns http headers for a retrievable upload >+ Will be extended by report 14282 >+ >+=cut >+ >+sub httpheaders { >+ my ( $class, $name ) = @_; >+ return ( >+ '-type' => 'application/octet-stream', >+ '-attachment' => $name, >+ ); >+} >+ > # ************** INTERNAL ROUTINES ******************************************** > > sub _init { >@@ -192,7 +262,9 @@ sub _create_file { > } else { > my $dir = $self->_dir; > my $fn = $self->{files}->{$filename}->{hash}. '_'. $filename; >- if( -e "$dir/$fn" ) { >+ if( -e "$dir/$fn" && @{ $self->_lookup({ >+ hashvalue => $self->{files}->{$filename}->{hash} }) } ) { >+ # if the file exists and it is registered, then set error > $self->{files}->{$filename}->{errcode} = 1; #already exists > return; > } >@@ -232,6 +304,7 @@ sub _full_fname { > > sub _hook { > my ( $self, $filename, $buffer, $bytes_read, $data ) = @_; >+ $filename= Encode::decode_utf8( $filename ); # UTF8 chars in filename > $self->_compute( $filename, $buffer ); > my $fh = $self->_fh( $filename ) // $self->_create_file( $filename ); > print $fh $buffer if $fh; >@@ -269,19 +342,44 @@ sub _register { > sub _lookup { > my ( $self, $params ) = @_; > my $dbh = C4::Context->dbh; >- my $sql = 'SELECT id,hashvalue,filename,dir,categorycode '. >+ my $sql = 'SELECT id,hashvalue,filename,dir,filesize,categorycode,public '. > 'FROM uploaded_files '; >+ my @pars; > if( $params->{id} ) { >- $sql.= "WHERE id=?"; >- } else { >+ return [] if $params->{id} !~ /^\d+(,\d+)*$/; >+ $sql.= "WHERE id IN ($params->{id})"; >+ @pars = (); >+ } elsif( $params->{hashvalue} ) { > $sql.= "WHERE hashvalue=?"; >+ @pars = ( $params->{hashvalue} ); >+ } else { >+ $sql.= "WHERE filename LIKE ? OR hashvalue LIKE ?"; >+ @pars = ( '%'.$params->{term}.'%', '%'.$params->{term}.'%' ); > } > $sql.= $self->{public}? " AND public=1": ''; >- my $temp= $dbh->selectall_arrayref( $sql, { Slice => {} }, >- ( $params->{id} // $params->{hashvalue} // 0 ) ); >+ $sql.= ' ORDER BY id'; >+ my $temp= $dbh->selectall_arrayref( $sql, { Slice => {} }, @pars ); > return $temp; > } > >+sub _delete { >+ my ( $self, $rec ) = @_; >+ my $dbh = C4::Context->dbh; >+ my $sql = 'DELETE FROM uploaded_files WHERE id=?'; >+ my $file = $self->_full_fname($rec); >+ if( !-e $file ) { # we will just delete the record >+ # TODO Should we add a trace here for the missing file? >+ $dbh->do( $sql, undef, ( $rec->{id} ) ); >+ return $rec->{filename}; >+ } elsif( unlink($file) ) { >+ $dbh->do( $sql, undef, ( $rec->{id} ) ); >+ return $rec->{filename}; >+ } >+ $self->{files}->{ $rec->{filename} }->{errcode} = 7; >+ #NOTE: errcode=6 is used to report successful delete (see template) >+ return; >+} >+ > sub _compute { > # Computes hash value when sub hook feeds the first block > # For temporary files, the id is made unique with time >diff --git a/cataloguing/value_builder/upload.pl b/cataloguing/value_builder/upload.pl >index 72bed79..e26bca7 100755 >--- a/cataloguing/value_builder/upload.pl >+++ b/cataloguing/value_builder/upload.pl >@@ -4,6 +4,7 @@ > > # This file is part of Koha. > # >+# Copyright (C) 2015 Rijksmuseum > # Copyright (C) 2011-2012 BibLibre > # > # Koha is free software; you can redistribute it and/or modify it >@@ -20,145 +21,33 @@ > # along with Koha; if not, see <http://www.gnu.org/licenses>. > > use Modern::Perl; >-use CGI qw/-utf8/; > >-use C4::Auth; >-use C4::Context; >-use C4::Output; >-use C4::UploadedFiles; >+# This plugin does not use the plugin launcher. It refers to tools/upload.pl. >+# That script and template support using it as a plugin. >+ >+# If the plugin is called with the pattern [id=some_hashvalue] in the >+# corresponding field, it starts the upload script as a search, providing >+# the possibility to delete the uploaded file. If the field is empty, you >+# can upload a new file. > > my $builder = sub { > my ( $params ) = @_; >- my $function_name = $params->{id}; >- my $res = " >- <script type=\"text/javascript\"> >- function Click$function_name(event) { >+ return <<"SCRIPT"; >+<script type=\"text/javascript\"> >+ function Click$params->{id}(event) { > var index = event.data.id; >- var id = document.getElementById(index).value; >- var IsFileUploadUrl=0; >- if (id.match(/opac-retrieve-file/)) { >- IsFileUploadUrl=1; >- } >- if(id.match(/id=([0-9a-f]+)/)){ >- id = RegExp.\$1; >- } >- 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'); >- newin.focus(); >- } >- </script> >-"; >- return $res; >-}; >- >-my $launcher = sub { >- my ( $params ) = @_; >- my $input = $params->{cgi}; >- my $index = $input->param('index'); >- my $id = $input->param('id'); >- my $delete = $input->param('delete'); >- my $uploaded_file = $input->param('uploaded_file'); >- my $from_popup = $input->param('from_popup'); >- my $isfileuploadurl = $input->param('IsFileUploadUrl'); >- my $dangling = C4::UploadedFiles::DanglingEntry($id,$isfileuploadurl); >- my $template_name; >- if ($delete || ($id && ($dangling==0 || $dangling==1))) { >- $template_name = "upload_delete_file.tt"; >- } >- else { >- $template_name = "upload.tt"; >- } >- >- my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >- { template_name => "cataloguing/value_builder/$template_name", >- query => $input, >- type => "intranet", >- authnotrequired => 0, >- flagsrequired => { editcatalogue => '*' }, >- debug => 1, >- } >- ); >- >- if ($dangling==2) { >- $template->param( dangling => 1 ); >- } >- >- # Dealing with the uploaded file >- my $dir = $input->param('uploadcategory'); >- if ($uploaded_file and $dir) { >- my $fh = $input->upload('uploaded_file'); >- >- $id = C4::UploadedFiles::UploadFile($uploaded_file, $dir, $fh->handle); >- my $OPACBaseURL = C4::Context->preference('OPACBaseURL') // ''; >- $OPACBaseURL =~ s#/$##; >- if (!$OPACBaseURL) { >- $template->param(MissingURL => 1); >- } >- if($id && $OPACBaseURL) { >- my $return = "$OPACBaseURL/cgi-bin/koha/opac-retrieve-file.pl?id=$id"; >- $template->param( >- success => 1, >- return => $return, >- uploaded_file => $uploaded_file, >- ); >- } else { >- $template->param(error => 1); >- } >- } elsif ($delete || ($id && ($dangling==0 || $dangling==1))) { >- # If there's already a file uploaded for this field, >- # We handle its deletion >- if ($delete) { >- if(C4::UploadedFiles::DelUploadedFile($id)==0) {; >- $template->param(error => 1); >+ var str = document.getElementById(index).value; >+ var myurl, term; >+ if( str && str.match(/id=([0-9a-f]+)/) ) { >+ term = RegExp.\$1; >+ myurl = '../tools/upload.pl?op=search&index='+index+'&term='+term+'&plugin=1'; > } else { >- $template->param(success => 1); >+ myurl = '../tools/upload.pl?op=new&index='+index+'&plugin=1'; > } >+ window.open( myurl, 'tag_editor', 'width=800,height=400,toolbar=false,scrollbars=yes' ); > } >- } else { >- my $upload_path = C4::Context->config('upload_path'); >- if ($upload_path) { >- my $filefield = CGI::filefield( >- -name => 'uploaded_file', >- -size => 50, >- ); >- $template->param( >- filefield => $filefield, >- uploadcategories => C4::UploadedFiles::getCategories(), >- ); >- } else { >- $template->param( error_upload_path_not_configured => 1 ); >- } >- >- if (!$uploaded_file && !$dir && $from_popup) { >- $template->param(error_nothing_selected => 1); >- } >- elsif (!$uploaded_file && $dir) { >- $template->param(error_no_file_selected => 1); >- } >- if ($uploaded_file and not $dir) { >- $template->param(error_no_dir_selected => 1); >- } >- >- } >- >- $template->param( >- index => $index, >- id => $id, >- ); >- >- output_html_with_http_headers $input, $cookie, $template->output; >+</script> >+SCRIPT > }; > >-return { builder => $builder, launcher => $launcher }; >- >-1; >- >-__END__ >- >-=head1 upload.pl >- >-This plugin allows to upload files on the server and reference it in a marc >-field. >- >-It uses config variable upload_path and pref OPACBaseURL. >- >-=cut >+return { builder => $builder }; >diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/file-upload.js b/koha-tmpl/intranet-tmpl/prog/en/js/file-upload.js >index 789f11d..f6817cb 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/js/file-upload.js >+++ b/koha-tmpl/intranet-tmpl/prog/en/js/file-upload.js >@@ -1,4 +1,4 @@ >-function AjaxUpload ( input, progressbar, callback ) { >+function AjaxUpload ( input, progressbar, xtra, callback ) { > // input and progressbar are jQuery objects > // callback is the callback function for completion > var formData= new FormData(); >@@ -6,7 +6,7 @@ function AjaxUpload ( input, progressbar, callback ) { > formData.append( "uploadfile", file ); > }); > var xhr= new XMLHttpRequest(); >- var url= '/cgi-bin/koha/tools/upload-file.pl'; >+ var url= '/cgi-bin/koha/tools/upload-file.pl?' + xtra; > progressbar.val( 0 ); > progressbar.next('.fileuploadpercent').text( '0' ); > xhr.open('POST', url, true); >@@ -21,7 +21,7 @@ function AjaxUpload ( input, progressbar, callback ) { > progressbar.val( 100 ); > progressbar.next('.fileuploadpercent').text( '100' ); > } >- callback( data.status, data.fileid ); >+ callback( data.status, data.fileid, data.errors ); > } > xhr.onerror = function (e) { > // Probably only fires for network failure >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/offline_circ/process_koc.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/offline_circ/process_koc.tt >index 2a44d82..0f9e578 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/offline_circ/process_koc.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/offline_circ/process_koc.tt >@@ -20,7 +20,7 @@ function StartUpload() { > $("#fileuploadstatus").show(); > $("form#processfile #uploadedfileid").val(''); > $("form#enqueuefile #uploadedfileid").val(''); >- xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), cbUpload ); >+ xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), '', cbUpload ); > } > > function cbUpload( status, fileid ) { >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/stage-marc-import.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/stage-marc-import.tt >index fed3104..0dff7d8 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/stage-marc-import.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/stage-marc-import.tt >@@ -39,7 +39,7 @@ function StartUpload() { > $("#processfile").hide(); > $("#fileuploadstatus").show(); > $("#uploadedfileid").val(''); >- xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), cbUpload ); >+ xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), '', cbUpload ); > $("#fileuploadcancel").show(); > } > function CancelUpload() { >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-images.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-images.tt >index 812df23..bf9535b 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-images.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-images.tt >@@ -18,7 +18,7 @@ function StartUpload() { > $('#uploadform button.submit').prop('disabled',true); > $("#fileuploadstatus").show(); > $("#uploadedfileid").val(''); >- xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), cbUpload ); >+ xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), '', cbUpload ); > } > function cbUpload( status, fileid ) { > if( status=='done' ) { >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload.tt >new file mode 100644 >index 0000000..0103bac >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload.tt >@@ -0,0 +1,306 @@ >+[% INCLUDE 'doc-head-open.inc' %] >+[% USE Koha %] >+[% IF plugin %] >+ <title>Upload plugin</title> >+[% ELSE %] >+ <title>Koha › Tools › Upload</title> >+[% END %] >+[% INCLUDE 'doc-head-close.inc' %] >+ >+[% BLOCK plugin_pars %] >+ [% IF plugin %] >+ <input type="hidden" name="plugin" value="1" /> >+ <input type="hidden" name="index" value="[% index %]" /> >+ [% END %] >+[% END %] >+ >+[% BLOCK breadcrumbs %] >+ <div id="breadcrumbs"> >+ <a href="/cgi-bin/koha/mainpage.pl">Home</a> >+ › >+ <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> >+ › >+ <a href="/cgi-bin/koha/tools/upload.pl">Upload</a> >+ › >+ <span id="lastbreadcrumb"> >+ [% IF mode=='new' || mode =='deleted'%] >+ Add new upload or search >+ [% ELSE %] >+ Results >+ [% END %] >+ </span> >+ </div> >+[% END %] >+ >+[% BLOCK form_new %] >+ <form method="post" action="[% SCRIPT_NAME %]" id="uploadfile" enctype="multipart/form-data"> >+ [% PROCESS plugin_pars %] >+ <fieldset class="rows" id="uploadform"> >+ <legend>Upload new files</legend> >+ <ol> >+ <li> >+ <div id="fileuploadform"> >+ <label for="fileToUpload">Select files: </label> >+ <input type="file" id="fileToUpload" name="fileToUpload" multiple/> >+ </div> >+ </li> >+ <li> >+ <label for="uploadcategory">Category: </label> >+ <select id="uploadcategory" name="uploadcategory"> >+ [% IF !plugin %] >+ <option value="" disabled hidden selected></option> >+ [% END %] >+ [% FOREACH cat IN uploadcategories %] >+ <option value="[% cat.code %]">[% cat.name %]</option> >+ [% END %] >+ </select> >+ </li> >+ [% IF !plugin %] >+ <li> >+ <div class="hint">Note: For temporary uploads do not select a category. The file will not be made available for public downloading.</div> >+ </li> >+ [% END %] >+ <li> >+ [% IF plugin %] >+ <input type="hidden" id="public" name="public" value="1"/> >+ [% ELSE %] >+ <label> </label> >+ <input type="checkbox" id="public" name="public"> >+ Allow public downloads >+ </input> >+ [% END %] >+ </li> >+ </ol> >+ <fieldset class="action"> >+ <button id="fileuploadbutton" onclick="StartUpload(); return false;">Upload</button> >+ <button id="fileuploadcancel" onclick="CancelUpload(); return false;">Cancel</button> >+ </fieldset> >+ </fieldset> >+ <div id="fileuploadpanel"> >+ <div id="fileuploadstatus">Upload progress: >+ <progress id="fileuploadprogress" min="0" max="100" value="0"> >+ </progress> >+ <span class="fileuploadpercent">0</span>% >+ </div> >+ <div id="fileuploadfailed"></div> >+ </div> >+ </form> >+[% END %] >+ >+[% BLOCK form_search %] >+ <form method="post" id="searchfile" action="[% SCRIPT_NAME %]" enctype="multipart/form-data"> >+ [% PROCESS plugin_pars %] >+ <input type="hidden" name="op" value="search"/> >+ <fieldset class="rows"> >+ <legend>Search uploads by name or hashvalue</legend> >+ <ol> >+ <li> >+ <label for="searchupload">Search term: </label> >+ <input type="text" id="term" name="term" value=""/> >+ </li> >+ <li> >+ <fieldset class="action"> >+ <button id="searchbutton" class="submit">Search</button> >+ </fieldset> >+ </li> >+ </ol> >+ </fieldset> >+ </form> >+[% END %] >+ >+[% BLOCK submitter %] >+ <form id="submitter" style="display:none;" method="post"> >+ [% PROCESS plugin_pars %] >+ <input type="hidden" name="op" id="op" value=""/> >+ <input type="hidden" name="id" id="id" value="" /> >+ <input type="hidden" name="msg" id="msg" value="" /> >+ </form> >+[% END %] >+ >+[% BLOCK closer %] >+ [% IF plugin %] >+ <form id="closer"> >+ <fieldset class="action"> >+ <button onclick="window.close();return false;">Close</button> >+ </fieldset> >+ </form> >+ [% END %] >+[% END %] >+ >+[% BLOCK table_results %] >+ <table> >+ <thead> >+ <tr> >+ <th>Filename</td> >+ <th>Size</td> >+ <th>Hashvalue</td> >+ <th>Category</td> >+ <th>Public</td> >+ <th>Actions</td> >+ </tr> >+ </thead> >+ <tbody> >+ [% FOREACH record IN uploads %] >+ <tr> >+ <td>[% record.name %]</td> >+ <td>[% record.filesize %]</td> >+ <td>[% record.hashvalue %]</td> >+ <td>[% record.categorycode %]</td> >+ <td>[% IF record.public %]Yes[% ELSE %]No[% END %]</td> >+ <td> >+ [% IF plugin %] >+ <a href="" onclick="Choose('[% record.hashvalue %]'); return false;">Choose</a> >+ [% END %] >+ <a href="" onclick="SubmitMe( 'download', [% record.id %] ); return false;">Download</a> >+ <a href="" onclick="ClearField(); SubmitMe( 'delete', [% record.id %] ); return false;">Delete</a> >+ </td> >+ </tr> >+ [% END %] >+ </tbody> >+ </table> >+[% END %] >+ >+<style type="text/css"> >+ #fileuploadstatus,#fileuploadfailed { display : none; } >+ #fileuploadstatus { margin:.4em; } >+ #fileuploadprogress { width:150px;height:10px;border:1px solid #666;background:url('[% interface %]/[% theme %]/img/progress.png') -300px 0px no-repeat; } >+</style> >+ >+<script type="text/javascript"> >+//<![CDATA[ >+ var errMESSAGES = [ >+ "Error 0: Not in use", >+ _("This file already exists (in this category)."), >+ _("File could not be created. Check permissions."), >+ _("Your koha-conf.xml does not contain a valid upload_path."), >+ _("No temporary directory found."), >+ _("File could not be read."), >+ _("File has been deleted."), >+ _("File could not be deleted."), >+ ]; >+//]]> >+</script> >+<script type="text/javascript" src="[% themelang %]/js/file-upload.js"></script> >+<script type="text/javascript"> >+//<![CDATA[ >+function StartUpload() { >+ if( $('#fileToUpload').prop('files').length == 0 ) return; >+ $('#fileToUpload').prop('disabled',true); >+ $('#fileuploadbutton').hide(); >+ $("#fileuploadcancel").show(); >+ $("#fileuploadfailed").html(''); >+ $("#myalerts").hide(''); >+ $("#myalerts").html(''); >+ $("#fileuploadstatus").show(); >+ $("#uploadedfileid").val(''); >+ $("#searchfile").hide(); >+ $("#lastbreadcrumb").text( _("Add a new upload") ); >+ >+ var xtra=''; >+ if( $("#uploadcategory").val() ) >+ xtra= xtra + 'category=' + $("#uploadcategory").val(); >+ if( $('#public').prop('checked') || $('#public').val() ) >+ // the second condition refers to the plugin environment >+ xtra = xtra + '&public=1'; >+ xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), xtra, cbUpload ); >+} >+function CancelUpload() { >+ if( xhr ) xhr.abort(); >+ $("#fileuploadstatus").hide(); >+ $('#fileToUpload').prop('disabled', false); >+ $('#fileuploadbutton').show(); >+ $("#fileuploadcancel").hide(); >+ $("#fileuploadfailed").show(); >+ $("#fileuploadfailed").text( _("Upload status: Cancelled ") ); >+} >+function cbUpload( status, fileid, err ) { >+ if( status=='done' ) { >+ var e = err? JSON.stringify(err): ''; >+ SubmitMe( 'search', fileid, e ); >+ } else { >+ $('#fileToUpload').prop('disabled', false); >+ $('#fileuploadbutton').show(); >+ $("#fileuploadcancel").hide(); >+ $("#fileuploadstatus").hide(); >+ $("#fileuploadfailed").show(); >+ $("#fileuploadfailed").html( _("Upload status: ") + >+ ( status=='failed'? _("Failed"): >+ ( status=='denied'? _("Denied"): status )) >+ ); >+ ShowAlerts( err ); >+ } >+} >+function ShowAlerts(err) { >+ var str = ''; >+ for( var file in err ) { >+ str= str + '<p>' + file + ': ' + >+ errMESSAGES[ err[file] ] + '</p>'; >+ } >+ $('#myalerts').html(str); >+ $('#myalerts').show(); >+} >+function SubmitMe(op, id, msg ) { >+ $("#submitter #op").val( op ); >+ $("#submitter #id").val( id ); >+ $("#submitter #msg").val( msg ); >+ $("#submitter").submit(); >+} >+function ClearField() { >+ [% IF plugin %] >+ $(window.opener.document).find('#[% index %]').val( '' ); >+ [% END %] >+} >+function Choose(hashval) { >+ var res = '[% Koha.Preference('OPACBaseURL') %]'; >+ res = res.replace( /\/$/, ''); >+ res = res + '/cgi-bin/koha/opac-retrieve-file.pl?id=' + hashval; >+ [% IF index %] >+ $(window.opener.document).find('#[% index %]').val( res ); >+ [% END %] >+ window.close(); >+} >+$(document).ready(function() { >+ [% IF msg %] >+ ShowAlerts( [% msg %] ); >+ [% END %] >+ $("#fileuploadcancel").hide(); >+}); >+//]]> >+</script> >+</head> >+ >+<body id="tools_upload" class="tools"> >+[% IF !plugin %] >+ [% INCLUDE 'header.inc' %] >+ [% INCLUDE 'cat-search.inc' %] >+ [% PROCESS breadcrumbs %] >+[% END %] >+ >+<div id="doc3" class="yui-t2"> >+ <div id="bd"> >+ <div id="yui-main"> >+ <div class="yui-b"> >+ >+<h1>Upload</h1> >+ >+<div class="dialog alert" id="myalerts" style="display:none;"></div> >+ >+[% PROCESS submitter %] >+[% IF mode == 'new' || mode == 'deleted' %] >+ [% PROCESS form_new %] >+ [% PROCESS form_search %] >+[% ELSIF mode == 'report' %] >+ [% IF uploads %] >+ <h3>Your request gave the following results:</h3> >+ [% PROCESS table_results %] >+ [% ELSE %] >+ <h4>Sorry, your request had no results.</h4> >+ [% END %] >+[% END %] >+[% PROCESS closer %] >+ >+</div> >+</div> >+</div> >+ >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/tools/upload-file.pl b/tools/upload-file.pl >index a1a2b65..2b3190d 100755 >--- a/tools/upload-file.pl >+++ b/tools/upload-file.pl >@@ -18,10 +18,11 @@ > # along with Koha; if not, see <http://www.gnu.org/licenses>. > > use Modern::Perl; >-use CGI::Cookie; > > use CGI qw ( -utf8 ); >-#use CGI::Session; >+use CGI::Cookie; >+use JSON; >+ > use C4::Context; > use C4::Auth qw/check_cookie_auth haspermission/; > use Koha::Upload; >@@ -57,18 +58,34 @@ if ($auth_failure) { > exit 0; > } > >-my $upload = Koha::Upload->new({ }); >-if( !$upload || !$upload->cgi || $upload->err ) { >- send_reply( 'failed' ); >+my $upload = Koha::Upload->new( extr_pars($ENV{QUERY_STRING}) ); >+if( !$upload || !$upload->cgi || !$upload->count ) { >+ # not one upload succeeded >+ send_reply( 'failed', undef, $upload? $upload->err: undef ); > } else { >- send_reply( 'done', $upload->result ); >+ # in case of multiple uploads, at least one got through >+ send_reply( 'done', $upload->result, $upload->err ); > } > exit 0; > > sub send_reply { # response will be sent back as JSON >- my ( $upload_status, $data ) = @_; >+ my ( $upload_status, $data, $error ) = @_; > my $reply = CGI->new(""); >- print $reply->header(-type => 'text/html'); >- print '{"status":"' . $upload_status . >- ( $data? '","fileid":"' . $data: '' ) . '"}'; >+ print $reply->header( -type => 'text/html', -charset => 'UTF-8' ); >+ print JSON::encode_json({ >+ status => $upload_status, >+ fileid => $data, >+ errors => $error, >+ }); >+} >+ >+sub extr_pars { >+ my ( $qstr ) = @_; >+ my $rv = {}; >+ foreach my $p ( qw[public category] ) { >+ if( $qstr =~ /(^|&)$p=(\w+)(&|$)/ ) { >+ $rv->{$p} = $2; >+ } >+ } >+ return $rv; > } >diff --git a/tools/upload.pl b/tools/upload.pl >new file mode 100755 >index 0000000..ed5b229 >--- /dev/null >+++ b/tools/upload.pl >@@ -0,0 +1,96 @@ >+#!/usr/bin/perl >+ >+# This file is part of Koha. >+# >+# Copyright (C) 2015 Rijksmuseum >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+use CGI qw/-utf8/; >+use JSON; >+ >+use C4::Auth; >+use C4::Output; >+use Koha::Upload; >+ >+my $input = CGI::->new; >+my $op = $input->param('op') // 'new'; >+my $plugin = $input->param('plugin'); >+my $index = $input->param('index'); # MARC editor input field id >+my $term = $input->param('term'); >+my $id = $input->param('id'); >+my $msg = $input->param('msg'); >+ >+my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >+ { template_name => "tools/upload.tt", >+ query => $input, >+ type => "intranet", >+ authnotrequired => 0, >+ flagsrequired => { editcatalogue => '*' }, >+ } >+); >+ >+$template->param( >+ plugin => $plugin, >+ index => $index, >+); >+if( $op eq 'new' ) { >+ $template->param( >+ mode => 'new', >+ uploadcategories => Koha::Upload->getCategories, >+ ); >+ output_html_with_http_headers $input, $cookie, $template->output; >+} elsif( $op eq 'search' ) { >+ my $h = $id? { id => $id }: { term => $term }; >+ my @uploads = Koha::Upload->new->get( $h ); >+ $template->param( >+ mode => 'report', >+ msg => $msg, >+ uploads => \@uploads, >+ ); >+ output_html_with_http_headers $input, $cookie, $template->output; >+} elsif( $op eq 'delete' ) { >+ # delete only takes the id parameter >+ my $upl = Koha::Upload->new; >+ my ( $fn ) = $upl->delete({ id => $id }); >+ my $e = $upl->err; >+ my $msg = $fn? JSON::to_json({ $fn => 6 }): >+ $e? JSON::to_json( $e ): undef; >+ $template->param( >+ mode => 'deleted', >+ msg => $msg, >+ uploadcategories => $upl->getCategories, >+ ); >+ output_html_with_http_headers $input, $cookie, $template->output; >+} elsif( $op eq 'download' ) { >+ my $upl = Koha::Upload->new; >+ my $rec = $upl->get({ id => $id, filehandle => 1 }); >+ my $fh = $rec->{fh}; >+ if( !$rec || !$fh ) { >+ $template->param( >+ mode => 'new', >+ msg => JSON::to_json({ $id => 5 }), >+ uploadcategories => $upl->getCategories, >+ ); >+ output_html_with_http_headers $input, $cookie, $template->output; >+ } else { >+ my @hdr = $upl->httpheaders( $rec->{name} ); >+ print $input->header( @hdr ); >+ while( <$fh> ) { >+ print $_; >+ } >+ $fh->close; >+ } >+} >-- >1.7.10.4
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 14321
:
41498
|
41499
|
41500
|
41501
|
41555
|
41556
|
41557
|
41558
|
41559
|
41560
|
41561
|
41562
|
41665
|
41666
|
41667
|
41668
|
41669
|
41677
|
41873
|
41874
|
41875
|
41876
|
41877
|
41878
|
41879
|
41880
|
41881
|
42411
|
42412
|
42413
|
42414
|
42558
|
42559
|
42560
|
42561
|
42584
|
42587
|
42588
|
42589
|
42590
|
42591
|
42660
|
42661
|
42662
|
42663
|
42664
|
42665
|
42666
|
42707
|
42726
|
42727
|
42728
|
42729
|
42730
|
42731
|
42732
|
42889
|
42890