Bugzilla – Attachment 41562 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: Final cleanup, removing obsolete files
Bug-14321-Final-cleanup-removing-obsolete-files.patch (text/plain), 46.30 KB, created by
Marcel de Rooy
on 2015-08-17 13:18:53 UTC
(
hide
)
Description:
Bug 14321: Final cleanup, removing obsolete files
Filename:
MIME Type:
Creator:
Marcel de Rooy
Created:
2015-08-17 13:18:53 UTC
Size:
46.30 KB
patch
obsolete
>From e91af2cca181ba5bf1fcc39949090a8dc1c89034 Mon Sep 17 00:00:00 2001 >From: Marcel de Rooy <m.de.rooy@rijksmuseum.nl> >Date: Mon, 17 Aug 2015 13:54:44 +0200 >Subject: [PATCH] Bug 14321: Final cleanup, removing obsolete files >Content-Type: text/plain; charset=utf-8 > >The new Upload.pm, unit test and file-upload.js obsolete a number of >files, including an older jQuery plugin. >The test files progressbar.pl and progressbarsubmit.pl are outdated and >do not serve any purpose in this form. (Actually, we could argue if they >should be here or just be part of a debugging phase.) > >Test plan: >[1] Git grep on file-progress, file-upload.inc, UploadedFile, > ajaxfileupload, ajaxFileUpload > UploadedFile: Only a reference to DBIx file is found > ajaxfileupload: Only release notes >[2] Upload a file with tools/upload and stage-marc-import. >--- > C4/UploadedFile.pm | 309 ------------------- > C4/UploadedFiles.pm | 323 -------------------- > .../lib/jquery/plugins/ajaxfileupload.js | 200 ------------ > .../intranet-tmpl/prog/en/includes/file-upload.inc | 70 ----- > .../en/modules/cataloguing/value_builder/upload.tt | 103 ------- > .../value_builder/upload_delete_file.tt | 63 ---- > .../prog/en/modules/test/progressbar.tt | 43 --- > t/db_dependent/UploadedFile.t | 16 - > t/db_dependent/UploadedFiles.t | 61 ---- > test/progressbar.pl | 55 ---- > test/progressbarsubmit.pl | 104 ------- > tools/upload-file-progress.pl | 61 ---- > 12 files changed, 1408 deletions(-) > delete mode 100644 C4/UploadedFile.pm > delete mode 100644 C4/UploadedFiles.pm > delete mode 100644 koha-tmpl/intranet-tmpl/lib/jquery/plugins/ajaxfileupload.js > delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/includes/file-upload.inc > delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/upload.tt > delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/upload_delete_file.tt > delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/test/progressbar.tt > delete mode 100755 t/db_dependent/UploadedFile.t > delete mode 100644 t/db_dependent/UploadedFiles.t > delete mode 100755 test/progressbar.pl > delete mode 100755 test/progressbarsubmit.pl > delete mode 100755 tools/upload-file-progress.pl > >diff --git a/C4/UploadedFile.pm b/C4/UploadedFile.pm >deleted file mode 100644 >index 0c366a0..0000000 >--- a/C4/UploadedFile.pm >+++ /dev/null >@@ -1,309 +0,0 @@ >-package C4::UploadedFile; >- >-# Copyright (C) 2007 LibLime >-# Galen Charlton <galen.charlton@liblime.com> >-# >-# This file is part of Koha. >-# >-# 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 strict; >-#use warnings; FIXME - Bug 2505 >-use C4::Context; >-use C4::Auth qw/get_session/; >-use IO::File; >- >-use vars qw($VERSION); >- >-BEGIN { >- # set the version for version checking >- $VERSION = 3.07.00.049; >-} >- >-=head1 NAME >- >-C4::UploadedFile - manage files uploaded by the user >-for later processing. >- >-=head1 SYNOPSIS >- >- # create and store data >- my $uploaded_file = C4::UploadedFile->new($sessionID); >- my $fileID = $uploaded_file->id(); >- $uploaded_file->name('c:\temp\file.mrc'); >- $uploaded_file->max_size(1024); >- while ($have_more_data) { >- $uploaded_file->stash($data, $bytes_read); >- } >- $uploaded_file->done(); >- >- # check status of current file upload >- my $progress = C4::UploadedFile->upload_progress($sessionID); >- >- # get file handle for reading uploaded file >- my $uploaded_file = C4::UploadedFile->fetch($fileID); >- my $fh = $uploaded_file->fh(); >- >- >-Stores files uploaded by the user from their web browser. The >-uploaded files are temporary and at present are not guaranteed >-to survive beyond the life of the user's session. >- >-This module allows for tracking the progress of the file >-currently being uploaded. >- >-TODO: implement secure persistent storage of uploaded files. >- >-=cut >- >-=head1 METHODS >- >-=cut >- >-=head2 new >- >- my $uploaded_file = C4::UploadedFile->new($sessionID); >- >-Creates a new object to represent the uploaded file. Requires >-the current session ID. >- >-=cut >- >-sub new { >- my $class = shift; >- my $sessionID = shift; >- >- my $self = {}; >- >- $self->{'sessionID'} = $sessionID; >- $self->{'fileID'} = Digest::MD5::md5_hex(Digest::MD5::md5_hex(time().{}.rand().{}.$$)); >- # FIXME - make staging area configurable >- my $TEMPROOT = "/tmp"; >- my $OUTPUTDIR = "$TEMPROOT/$sessionID"; >- mkdir $OUTPUTDIR; >- my $tmp_file_name = "$OUTPUTDIR/$self->{'fileID'}"; >- my $fh = new IO::File $tmp_file_name, "w"; >- unless (defined $fh) { >- return undef; >- } >- $fh->binmode(); # Windows compatibility >- $self->{'fh'} = $fh; >- $self->{'tmp_file_name'} = $tmp_file_name; >- $self->{'max_size'} = 0; >- $self->{'progress'} = 0; >- $self->{'name'} = ''; >- >- bless $self, $class; >- $self->_serialize(); >- >- my $session = get_session($sessionID); >- $session->param('current_upload', $self->{'fileID'}); >- $session->flush(); >- >- return $self; >- >-} >- >-sub _serialize { >- my $self = shift; >- >- my $prefix = "upload_" . $self->{'fileID'}; >- my $session = get_session($self->{'sessionID'}); >- >- # temporarily take file handle out of structure >- my $fh = $self->{'fh'}; >- delete $self->{'fh'}; >- $session->param($prefix, $self); >- $session->flush(); >- $self->{'fh'} =$fh; >-} >- >-=head2 id >- >- my $fileID = $uploaded_file->id(); >- >-=cut >- >-sub id { >- my $self = shift; >- return $self->{'fileID'}; >-} >- >-=head2 name >- >- my $name = $uploaded_file->name(); >- $uploaded_file->name($name); >- >-Accessor method for the name by which the file is to be known. >- >-=cut >- >-sub name { >- my $self = shift; >- if (@_) { >- $self->{'name'} = shift; >- $self->_serialize(); >- } else { >- return $self->{'name'}; >- } >-} >- >-=head2 filename >- >- my $filename = $uploaded_file->filename(); >- >-Accessor method for the name by which the file is to be known. >- >-=cut >- >-sub filename { >- my $self = shift; >- if (@_) { >- $self->{'tmp_file_name'} = shift; >- $self->_serialize(); >- } else { >- return $self->{'tmp_file_name'}; >- } >-} >- >-=head2 max_size >- >- my $max_size = $uploaded_file->max_size(); >- $uploaded_file->max_size($max_size); >- >-Accessor method for the maximum size of the uploaded file. >- >-=cut >- >-sub max_size { >- my $self = shift; >- @_ ? $self->{'max_size'} = shift : $self->{'max_size'}; >-} >- >-=head2 stash >- >- $uploaded_file->stash($dataref, $bytes_read); >- >-Write C<$dataref> to the temporary file. C<$bytes_read> represents >-the number of bytes (out of C<$max_size>) transmitted so far. >- >-=cut >- >-sub stash { >- my $self = shift; >- my $dataref = shift; >- my $bytes_read = shift; >- >- my $fh = $self->{'fh'}; >- print $fh $$dataref; >- >- my $percentage = int(($bytes_read / $self->{'max_size'}) * 100); >- if ($percentage > $self->{'progress'}) { >- $self->{'progress'} = $percentage; >- $self->_serialize(); >- } >-} >- >-=head2 done >- >- $uploaded_file->done(); >- >-Indicates that all of the bytes have been uploaded. >- >-=cut >- >-sub done { >- my $self = shift; >- $self->{'progress'} = 'done'; >- $self->{'fh'}->close(); >- $self->_serialize(); >-} >- >-=head2 upload_progress >- >- my $upload_progress = C4::UploadFile->upload_progress($sessionID); >- >-Returns (as an integer from 0 to 100) the percentage >-progress of the current file upload. >- >-=cut >- >-sub upload_progress { >- my ($class, $sessionID) = shift; >- >- my $session = get_session($sessionID); >- >- my $fileID = $session->param('current_upload'); >- >- my $reported_progress = 0; >- if (defined $fileID and $fileID ne "") { >- my $file = C4::UploadedFile->fetch($sessionID, $fileID); >- my $progress = $file->{'progress'}; >- if (defined $progress) { >- if ($progress eq "done") { >- $reported_progress = 100; >- } else { >- $reported_progress = $progress; >- } >- } >- } >- return $reported_progress; >-} >- >-=head2 fetch >- >- my $uploaded_file = C4::UploadedFile->fetch($sessionID, $fileID); >- >-Retrieves an uploaded file object from the current session. >- >-=cut >- >-sub fetch { >- my $class = shift; >- my $sessionID = shift; >- my $fileID = shift; >- >- my $session = get_session($sessionID); >- my $prefix = "upload_$fileID"; >- my $self = $session->param($prefix); >- my $fh = new IO::File $self->{'tmp_file_name'}, "r"; >- $self->{'fh'} = $fh; >- >- bless $self, $class; >- return $self; >-} >- >-=head2 fh >- >- my $fh = $uploaded_file->fh(); >- >-Returns an IO::File handle to read the uploaded file. >- >-=cut >- >-sub fh { >- my $self = shift; >- return $self->{'fh'}; >-} >- >-1; >-__END__ >- >-=head1 AUTHOR >- >-Koha Development Team <http://koha-community.org/> >- >-Galen Charlton <galen.charlton@liblime.com> >- >-=cut >diff --git a/C4/UploadedFiles.pm b/C4/UploadedFiles.pm >deleted file mode 100644 >index f426b60..0000000 >--- a/C4/UploadedFiles.pm >+++ /dev/null >@@ -1,323 +0,0 @@ >-package C4::UploadedFiles; >- >-# This file is part of Koha. >-# >-# Copyright (C) 2011-2012 BibLibre >-# >-# 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>. >- >-=head1 NAME >- >-C4::UploadedFiles - Functions to deal with files uploaded with cataloging plugin upload.pl >- >-=head1 SYNOPSIS >- >- use C4::UploadedFiles; >- >- my $filename = $cgi->param('uploaded_file'); >- my $file = $cgi->upload('uploaded_file'); >- my $dir = $input->param('dir'); >- >- # upload file >- my $id = C4::UploadedFiles::UploadFile($filename, $dir, $file->handle); >- >- # retrieve file infos >- my $uploaded_file = C4::UploadedFiles::GetUploadedFile($id); >- >- # delete file >- C4::UploadedFiles::DelUploadedFile($id); >- >-=head1 DESCRIPTION >- >-This module provides basic functions for adding, retrieving and deleting files related to >-cataloging plugin upload.pl. >- >-It uses uploaded_files table. >- >-It is not related to C4::UploadedFile >- >-=head1 FUNCTIONS >- >-=cut >- >-use Modern::Perl; >-use Digest::SHA; >-use Fcntl; >-use Encode; >- >-use C4::Context; >-use C4::Koha; >- >-sub _get_file_path { >- my ($hash, $dirname, $filename) = @_; >- >- my $upload_path = C4::Context->config('upload_path'); >- if( !-d "$upload_path/$dirname" ) { >- mkdir "$upload_path/$dirname"; >- } >- my $filepath = "$upload_path/$dirname/${hash}_$filename"; >- $filepath =~ s|/+|/|g; >- >- return $filepath; >-} >- >-=head2 GetUploadedFile >- >- my $file = C4::UploadedFiles::GetUploadedFile($id); >- >-Returns a hashref containing infos on uploaded files. >-Hash keys are: >- >-=over 2 >- >-=item * id: id of the file (same as given in argument) >- >-=item * filename: name of the file >- >-=item * dir: directory where file is stored (relative to config variable 'upload_path') >- >-=back >- >-It returns undef if file is not found >- >-=cut >- >-sub GetUploadedFile { >- my ( $hashvalue ) = @_; >- >- return unless $hashvalue; >- >- my $dbh = C4::Context->dbh; >- my $query = qq{ >- SELECT hashvalue, filename, dir >- FROM uploaded_files >- WHERE hashvalue = ? >- }; >- my $sth = $dbh->prepare($query); >- $sth->execute( $hashvalue ); >- my $file = $sth->fetchrow_hashref; >- if ($file) { >- $file->{filepath} = _get_file_path($file->{hashvalue}, $file->{dir}, >- $file->{filename}); >- } >- >- return $file; >-} >- >-=head2 UploadFile >- >- my $id = C4::UploadedFiles::UploadFile($filename, $dir, $io_handle); >- >-Upload a new file and returns its id (its SHA-1 sum, actually). >- >-Parameters: >- >-=over 2 >- >-=item * $filename: name of the file >- >-=item * $dir: directory where to store the file (path relative to config variable 'upload_path' >- >-=item * $io_handle: valid IO::Handle object, can be retrieved with >-$cgi->upload('uploaded_file')->handle; >- >-=back >- >-=cut >- >-sub UploadFile { >- my ($filename, $dir, $handle) = @_; >- $filename = decode_utf8($filename); >- if($filename =~ m#(^|/)\.\.(/|$)# or $dir =~ m#(^|/)\.\.(/|$)#) { >- warn "Filename or dirname contains '..'. Aborting upload"; >- return; >- } >- >- my $buffer; >- my $data = ''; >- while($handle->read($buffer, 1024)) { >- $data .= $buffer; >- } >- $handle->close; >- >- my $sha = new Digest::SHA; >- $sha->add($data); >- $sha->add($filename); >- $sha->add($dir); >- my $hash = $sha->hexdigest; >- >- # Test if this id already exist >- my $file = GetUploadedFile($hash); >- if ($file) { >- return $file->{hashvalue}; >- } >- >- my $file_path = _get_file_path($hash, $dir, $filename); >- >- my $out_fh; >- # Create the file only if it doesn't exist >- unless( sysopen($out_fh, $file_path, O_WRONLY|O_CREAT|O_EXCL) ) { >- warn "Failed to open file '$file_path': $!"; >- return; >- } >- >- print $out_fh $data; >- my $size= tell($out_fh); >- close $out_fh; >- >- my $dbh = C4::Context->dbh; >- my $query = qq{ >- INSERT INTO uploaded_files (hashvalue, filename, filesize, dir, categorycode, owner) VALUES (?,?,?,?,?,?); >- }; >- my $sth = $dbh->prepare($query); >- my $uid= C4::Context->userenv? C4::Context->userenv->{number}: undef; >- # uid is null in unit test >- if($sth->execute($hash, $filename, $size, $dir, $dir, $uid)) { >- return $hash; >- } >- >- return; >-} >- >-=head2 DanglingEntry >- >- C4::UploadedFiles::DanglingEntry($id,$isfileuploadurl); >- >-Determine if a entry is dangling. >- >-Returns: 2 == no db entry >- 1 == no plain file >- 0 == both a file and db entry. >- -1 == N/A (undef id / non-file-upload URL) >- >-=cut >- >-sub DanglingEntry { >- my ($id,$isfileuploadurl) = @_; >- my $retval; >- >- if (defined($id)) { >- my $file = GetUploadedFile($id); >- if($file) { >- my $file_path = $file->{filepath}; >- my $file_deleted = 0; >- unless( -f $file_path ) { >- $retval = 1; >- } else { >- $retval = 0; >- } >- } >- else { >- if ( $isfileuploadurl ) { >- $retval = 2; >- } >- else { >- $retval = -1; >- } >- } >- } >- else { >- $retval = -1; >- } >- return $retval; >-} >- >-=head2 DelUploadedFile >- >- C4::UploadedFiles::DelUploadedFile( $hash ); >- >-Remove a previously uploaded file, given its hash value. >- >-Returns: 1 == file deleted >- 0 == file not deleted >- -1== no file to delete / no meaninful id passed >- >-=cut >- >-sub DelUploadedFile { >- my ( $hashval ) = @_; >- my $retval; >- >- if ( $hashval ) { >- my $file = GetUploadedFile( $hashval ); >- if($file) { >- my $file_path = $file->{filepath}; >- my $file_deleted = 0; >- unless( -f $file_path ) { >- warn "Id $file->{hashvalue} is in database but no plain file found, removing id from database"; >- $file_deleted = 1; >- } else { >- if(unlink $file_path) { >- $file_deleted = 1; >- } >- } >- >- unless($file_deleted) { >- warn "File $file_path cannot be deleted: $!"; >- } >- >- my $dbh = C4::Context->dbh; >- my $query = qq{ >- DELETE FROM uploaded_files >- WHERE hashvalue = ? >- }; >- my $sth = $dbh->prepare($query); >- my $numrows = $sth->execute( $hashval ); >- # if either a DB entry or file was deleted, >- # then clearly we have a deletion. >- if ($numrows>0 || $file_deleted==1) { >- $retval = 1; >- } >- else { >- $retval = 0; >- } >- } >- else { >- warn "There was no file for hash $hashval."; >- $retval = -1; >- } >- } >- else { >- warn "DelUploadFile called without hash value."; >- $retval = -1; >- } >- return $retval; >-} >- >-=head2 getCategories >- >- getCategories returns a list of upload category codes and names >- >-=cut >- >-sub getCategories { >- 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 $file= shift; >- return >- ( '-type' => 'application/octet-stream', >- '-attachment' => $file, ); >-} >- >-1; >diff --git a/koha-tmpl/intranet-tmpl/lib/jquery/plugins/ajaxfileupload.js b/koha-tmpl/intranet-tmpl/lib/jquery/plugins/ajaxfileupload.js >deleted file mode 100644 >index 0e1d75b..0000000 >--- a/koha-tmpl/intranet-tmpl/lib/jquery/plugins/ajaxfileupload.js >+++ /dev/null >@@ -1,200 +0,0 @@ >- >-jQuery.extend({ >- >- createUploadIframe: function(id, uri) >- { >- //create frame >- var frameId = 'jUploadFrame' + id; >- >- try { >- var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />'); >- if(typeof uri== 'boolean'){ >- io.src = 'javascript:false'; >- } >- else if(typeof uri== 'string'){ >- io.src = uri; >- } >- } >- catch(e) { >- var io = document.createElement('iframe'); >- io.id = frameId; >- io.name = frameId; >- } >- io.style.position = 'absolute'; >- io.style.top = '-1000px'; >- io.style.left = '-1000px'; >- >- document.body.appendChild(io); >- >- return io >- }, >- createUploadForm: function(id, fileElementId) >- { >- //create form >- var formId = 'jUploadForm' + id; >- var fileId = 'jUploadFile' + id; >- var form = $('<form action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>'); >- var oldElement = $('#' + fileElementId); >- var newElement = $(oldElement).clone(); >- $(oldElement).attr('id', fileId); >- $(oldElement).before(newElement); >- $(oldElement).appendTo(form); >- //set attributes >- $(form).css('position', 'absolute'); >- $(form).css('top', '-1200px'); >- $(form).css('left', '-1200px'); >- $(form).appendTo('body'); >- return form; >- }, >- >- ajaxFileUpload: function(s) { >- // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout >- s = jQuery.extend({}, jQuery.ajaxSettings, s); >- var id = new Date().getTime() >- var form = jQuery.createUploadForm(id, s.fileElementId); >- var io = jQuery.createUploadIframe(id, s.secureuri); >- var frameId = 'jUploadFrame' + id; >- var formId = 'jUploadForm' + id; >- // Watch for a new set of requests >- if ( s.global && ! jQuery.active++ ) >- { >- jQuery.event.trigger( "ajaxStart" ); >- } >- var requestDone = false; >- // Create the request object >- var xml = {} >- if ( s.global ) >- jQuery.event.trigger("ajaxSend", [xml, s]); >- // Wait for a response to come back >- var uploadCallback = function(isTimeout) >- { >- var io = document.getElementById(frameId); >- try >- { >- if(io.contentWindow) >- { >- xml.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null; >- xml.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document; >- >- }else if(io.contentDocument) >- { >- xml.responseText = io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:null; >- xml.responseXML = io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocument:io.contentDocument.document; >- } >- }catch(e) >- { >- jQuery.handleError(s, xml, null, e); >- } >- if ( xml || isTimeout == "timeout") >- { >- requestDone = true; >- var status; >- try { >- status = isTimeout != "timeout" ? "success" : "error"; >- // Make sure that the request was successful or notmodified >- if ( status != "error" ) >- { >- // process the data (runs the xml through httpData regardless of callback) >- var data = jQuery.uploadHttpData( xml, s.dataType ); >- // If a local callback was specified, fire it and pass it the data >- if ( s.success ) >- s.success( data, status ); >- >- // Fire the global callback >- if( s.global ) >- jQuery.event.trigger( "ajaxSuccess", [xml, s] ); >- } else >- jQuery.handleError(s, xml, status); >- } catch(e) >- { >- status = "error"; >- jQuery.handleError(s, xml, status, e); >- } >- >- // The request was completed >- if( s.global ) >- jQuery.event.trigger( "ajaxComplete", [xml, s] ); >- >- // Handle the global AJAX counter >- if ( s.global && ! --jQuery.active ) >- jQuery.event.trigger( "ajaxStop" ); >- >- // Process result >- if ( s.complete ) >- s.complete(xml, status); >- >- jQuery(io).unbind() >- >- setTimeout(function() >- { try >- { >- $(io).remove(); >- $(form).remove(); >- >- } catch(e) >- { >- jQuery.handleError(s, xml, null, e); >- } >- >- }, 100) >- >- xml = null >- >- } >- } >- // Timeout checker >- if ( s.timeout > 0 ) >- { >- setTimeout(function(){ >- // Check to see if the request is still happening >- if( !requestDone ) uploadCallback( "timeout" ); >- }, s.timeout); >- } >- try >- { >- // var io = $('#' + frameId); >- var form = $('#' + formId); >- $(form).attr('action', s.url); >- $(form).attr('method', 'POST'); >- $(form).attr('target', frameId); >- if(form.encoding) >- { >- form.encoding = 'multipart/form-data'; >- } >- else >- { >- form.enctype = 'multipart/form-data'; >- } >- $(form).submit(); >- >- } catch(e) >- { >- jQuery.handleError(s, xml, null, e); >- } >- if(window.attachEvent){ >- document.getElementById(frameId).attachEvent('onload', uploadCallback); >- } >- else{ >- document.getElementById(frameId).addEventListener('load', uploadCallback, false); >- } >- return {abort: function () {}}; >- >- }, >- >- uploadHttpData: function( r, type ) { >- var data = !type; >- data = type == "xml" || data ? r.responseXML : r.responseText; >- // If the type is "script", eval it in global context >- if ( type == "script" ) >- jQuery.globalEval( data ); >- // Get the JavaScript object, if JSON is used. >- if ( type == "json" ) >- eval( "data = " + data ); >- // evaluate scripts within html >- if ( type == "html" ) >- jQuery("<div>").html(data).evalScripts(); >- //alert($('param', data).each(function(){alert($(this).attr('value'));})); >- return data; >- } >-}) >- >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/file-upload.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/file-upload.inc >deleted file mode 100644 >index d8e9e00..0000000 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/file-upload.inc >+++ /dev/null >@@ -1,70 +0,0 @@ >-<!-- AJAX file upload stuff --> >-<script type="text/javascript" src="[% interface %]/lib/jquery/plugins/ajaxfileupload.js"></script> >-<script type="text/javascript"> >- //<![CDATA[ >- var fileUploadProgressTimer = 0; >- var inFileUploadProgressTimer = false; >- var fileUploadProgressTimerCanceled = false; >- function updateProgress() { >- if (inFileUploadProgressTimer) { >- // since $.getJSON is asynchronous, wait >- // until the last one is finished >- return; >- } >- inFileUploadProgressTimer = true; >- $.getJSON("/cgi-bin/koha/tools/upload-file-progress.pl", function(json) { >- if (!fileUploadProgressTimerCanceled) { >- var bgproperty = (parseInt(json.progress)*2-300)+"px 0px"; >- $("#fileuploadprogress").css("background-position",bgproperty); >- $("#fileuploadpercent").text(json.progress); >- } >- inFileUploadProgressTimer = false; >- }); >- } >- function ajaxFileUpload() >- { >- fileUploadProgressTimerCanceled = false; >- $("#uploadpanel").show(); >- $("#fileuploadstatus").show(); >- fileUploadProgressTimer = setInterval("updateProgress()",500); >- $.ajaxFileUpload ( >- { >- url:'/cgi-bin/koha/tools/upload-file.pl', >- secureuri:false, >- global:false, >- fileElementId:'fileToUpload', >- dataType: 'json', >- success: function (data, status) { >- if (data.status == 'denied') { >- $("#fileuploadstatus").hide(); >- $("#fileuploadfailed").show(); >- $("#fileuploadfailed").text("Upload failed -- no permission to upload files"); >- } else if (data.status == 'failed') { >- $("#fileuploadstatus").hide(); >- $("#fileuploadfailed").show(); >- $("#fileuploadfailed").text("Upload failed -- unable to store file on server"); >- } else if (data.status == 'maintenance') { >- $("#fileuploadstatus").hide(); >- $("#fileuploadfailed").show(); >- $("#fileuploadfailed").text("Upload failed -- database in maintenance state"); >- } else { >- $("#uploadedfileid").val(data.fileid); >- $("#fileuploadprogress").css("background-position","0px 0px"); >- $("#processfile").show(); >- $("#fileuploadpercent").text("100"); >- } >- fileUploadProgressTimerCanceled = true; >- clearInterval(fileUploadProgressTimer); >- }, >- error: function (data, status, e) { >- fileUploadProgressTimerCanceled = true; >- alert(e); >- clearInterval(fileUploadProgressTimer); >- } >- } >- ) >- return false; >- >- } >- //]]> >-</script> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/upload.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/upload.tt >deleted file mode 100644 >index 87f0051..0000000 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/upload.tt >+++ /dev/null >@@ -1,103 +0,0 @@ >-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" >- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> >-<html xmlns="http://www.w3.org/1999/xhtml"> >-<head> >- <title>Upload plugin</title> >- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> >- <script type="text/javascript" src="[% interface %]/lib/jquery/jquery.js"></script> >- <link rel="stylesheet" type="text/css" href="[% themelang %]/css/staff-global.css" /> >- <script type="text/javascript"> >- function ValidateForm() { >- var filename = document.forms["UploadForm"]["uploaded_file"].value; >- if (!filename) { >- alert("Please select a file to upload."); >- return false; >- } >- return true; >- } >- </script> >- >-</head> >-<body> >- >-<div id="doc3" class="yui-t2"><div id="bd"><div id="yui-main"> >- >-[% IF ( success ) %] >- >- <script type="text/javascript"> >- function report() { >- var doc = opener.document; >- var field = doc.getElementById("[% index %]"); >- field.value = "[% return %]"; >- } >- $(document).ready(function() { >- report(); >- }); >- </script> >- >- >- The file [% uploaded_file | html %] has been successfully uploaded. >- <p><input type="button" value="close" onclick="window.close();" /></p> >- >-[% ELSE %] >- >- [% IF ( MissingURL ) %] >- <p>Error: The OPAC system preference OPACBaseURL is not configured.</p> >- <p><input type="button" value="close" onclick="window.close();" /></p> >- [% ELSIF ( error ) %] >- <p>Error: Failed to upload file. See logs for details.</p> >- <p><input type="button" value="close" onclick="window.close();" /></p> >- [% ELSE %] >- [% IF (error_upload_path_not_configured) %] >- <h2>Configuration error</h2> >- <p>Configuration variable 'upload_path' is not configured.</p> >- <p>Please configure it in your koha-conf.xml</p> >- [% ELSE %] >- [% IF (error_nothing_selected) %] >- <p class="error">Error: You have to choose the file to upload and select where to upload the file.</p> >- [% END %] >- [% IF (error_no_file_selected) %] >- <p class="error">Error: You have to choose the file to upload.</p> >- [% END %] >- [% IF (error_no_dir_selected) %] >- <p class="error">Error: You have to select where to upload the file.</p> >- [% END %] >- [% IF (dangling) %] >- <p class="error">Error: The URL has no file to retrieve.</p> >- [% END %] >- >- <h2>Please select the file to upload:</h2> >- <form name="UploadForm" method="post" enctype="multipart/form-data" action="/cgi-bin/koha/cataloguing/plugin_launcher.pl" onsubmit="return ValidateForm()"> >- <input type="hidden" name="from_popup" value="1" /> >- <input type="hidden" name="plugin_name" value="upload.pl" /> >- <input type="hidden" name="index" value="[% index %]" /> >- >- <div>[% filefield %]</div> >- <p/> >- <div> >- <label for="uploadcategory">Category: </label> >- [% IF uploadcategories %] >- <select id="uploadcategory" name="uploadcategory"> >- [% FOREACH cat IN uploadcategories %] >- <option value="[% cat.code %]">[% cat.name %]</option> >- [% END %] >- </select> >- [% ELSE %] >- <input type="hidden" name="uploadcategory" value="CATALOGUING" /> >- [% END %] >- </div> >- <p/> >- <fieldset class="action"> >- <input type="submit" value="Upload"> >- <input type="button" value="Cancel" onclick="window.close();" /> >- </fieldset> >- </form> >- [% END %] >- [% END %] >- >-[% END %] >- >-</div></div></div> >- >-</body> >-</html> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/upload_delete_file.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/upload_delete_file.tt >deleted file mode 100644 >index 7f5e05d..0000000 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/upload_delete_file.tt >+++ /dev/null >@@ -1,63 +0,0 @@ >-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" >- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> >-<html xmlns="http://www.w3.org/1999/xhtml"> >-<head> >- <title>Upload plugin</title> >- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> >- <script type="text/javascript" src="[% interface %]/lib/jquery/jquery.js"></script> >- <link rel="stylesheet" type="text/css" href="[% themelang %]/css/staff-global.css" /> >- <script type="text/javascript"> >- //<![CDATA[ >- function goToUploadPage() { >- var url = "/cgi-bin/koha/cataloguing/plugin_launcher.pl?" >- + "plugin_name=upload.pl&index=[% index %]"; >- window.location.href = url; >- } >- //]]> >- </script> >- >-</head> >-<body> >-[% IF ( success ) %] >- >- <script type="text/javascript"> >- function report() { >- var doc = opener.document; >- var field = doc.getElementById("[% index %]"); >- field.value = ""; >- } >- $(document).ready(function() { >- report(); >- }); >- </script> >- >- <p>The file has been successfully deleted.</p> >- >- <input type="button" value="Upload a new file" onclick="goToUploadPage();" /> >- <input type="button" value="Close" onclick="window.close();" /> >- >-[% ELSE %] >- >- [% IF ( MissingURL ) %] >- <p>Error: The OPAC system preference OPACBaseURL is not configured.</p> >- <p><input type="button" value="close" onclick="window.close();" /></p> >- [% ELSIF ( error ) %] >- <p>Error: Unable to delete the file.</p> >- <p><input type="button" value="close" onclick="window.close();" /></p> >- [% ELSE %] >- <h2>File deletion</h2> >- <p>A file has already been uploaded for this field. Do you want to delete it?</p> >- <form method="post" action="/cgi-bin/koha/cataloguing/plugin_launcher.pl"> >- <input type="hidden" name="plugin_name" value="upload.pl" /> >- <input type="hidden" name="delete" value="delete" /> >- <input type="hidden" name="id" value="[% id %]" /> >- <input type="hidden" name="index" value="[% index %]" /> >- <input type="button" value="Cancel" onclick="javascript:window.close();" /> >- <input type="submit" value="Delete" /> >- </form> >- [% END %] >- >-[% END %] >- >-</body> >-</html> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/test/progressbar.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/test/progressbar.tt >deleted file mode 100644 >index 3ad4d33..0000000 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/test/progressbar.tt >+++ /dev/null >@@ -1,43 +0,0 @@ >-[% INCLUDE 'doc-head-open.inc' %] >-<title>Koha › Tools › Stage MARC records for import</title> >-[% INCLUDE 'doc-head-close.inc' %] >-[% INCLUDE 'file-upload.inc' %] >-<script type="text/javascript" src="[% themelang %]/js/background-job-progressbar.js"></script> >-<style type="text/css"> >- #uploadpanel,#fileuploadstatus,#fileuploadfailed,#jobpanel,#jobstatus,#jobfailed { display : none; } >- #fileuploadstatus,#jobstatus { margin:.4em; } >- #fileuploadprogress,#jobprogress{ 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[ >-$(document).ready(function(){ >-}); >-function CheckForm(f) { >- submitBackgroundJob(f); >- return false; >-} >- >-//]]> >-</script> >-</head> >-<body id="test_progressbar" class="test"> >-<div id="doc3" class="yui-t2"> >- >-<form method="post" action="progressbarsubmit.pl"> >-<input type="hidden" name="submitted" id="submitted" value="1" /> >-<input type="hidden" name="runinbackground" id="runinbackground" value="" /> >-<input type="hidden" name="completedJobID" id="completedJobID" value="" /> >- >-<input type="button" id="mainformsubmit" onclick="return CheckForm(this.form);" value="Start" /> >- >- <div id="jobpanel"> >- <div id="jobstatus">Job progress: <div id="jobprogress"></div> <span id="jobprogresspercent">0</span>%</div> >- <div id="jobfailed"></div> >- </div> >- >-</form> >-</div> >- >-<div> >-Completed: <span id="completed">[% completedJobID %] </span> >-</div> >-</body> >diff --git a/t/db_dependent/UploadedFile.t b/t/db_dependent/UploadedFile.t >deleted file mode 100755 >index e6008d9..0000000 >--- a/t/db_dependent/UploadedFile.t >+++ /dev/null >@@ -1,16 +0,0 @@ >-#!/usr/bin/perl >-# >- >-# A simple test for UploadedFile >-# only ->new is covered >- >-use strict; >-use warnings; >- >-use Test::More tests => 2; >- >-BEGIN { >- use_ok('C4::UploadedFile'); >-} >- >-ok(my $file = C4::UploadedFile->new()); >diff --git a/t/db_dependent/UploadedFiles.t b/t/db_dependent/UploadedFiles.t >deleted file mode 100644 >index f933546..0000000 >--- a/t/db_dependent/UploadedFiles.t >+++ /dev/null >@@ -1,61 +0,0 @@ >-#!/usr/bin/perl >- >-use Modern::Perl; >-use File::Temp qw/ tempdir /; >-use Test::CGI::Multipart; >-use Test::More tests => 18; >-use Test::Warn; >- >-use t::lib::Mocks; >- >-use C4::Context; >-use C4::UploadedFiles; >- >-# This simulates a multipart POST request with a file upload. >-my $tcm = new Test::CGI::Multipart; >-$tcm->upload_file( >- name => 'testfile', >- file => 'testfilename.txt', >- value => "This is the content of testfilename.txt", >-); >-my $cgi = $tcm->create_cgi; >- >-my $tempdir = tempdir(CLEANUP => 1); >-t::lib::Mocks::mock_config('upload_path', $tempdir); >- >-my $testfilename = $cgi->param('testfile'); >-my $testfile_fh = $cgi->upload('testfile'); >-my $id = C4::UploadedFiles::UploadFile($testfilename, '', $testfile_fh->handle); >-ok($id, "File uploaded, id is $id"); >- >-my $file = C4::UploadedFiles::GetUploadedFile($id); >-isa_ok($file, 'HASH', "GetUploadedFiles($id)"); >-foreach my $key (qw(hashvalue filename filepath dir)) { >- ok(exists $file->{$key}, "GetUploadedFile($id)->{$key} exists"); >-} >- >-ok(-e $file->{filepath}, "File $file->{filepath} exists"); >- >-ok(C4::UploadedFiles::DanglingEntry()==-1, "DanglingEntry() returned -1 as expected."); >-ok(C4::UploadedFiles::DanglingEntry($id)==0, "DanglingEntry($id) returned 0 as expected."); >-unlink ($file->{filepath}); >-ok(C4::UploadedFiles::DanglingEntry($id)==1, "DanglingEntry($id) returned 1 as expected."); >- >-open my $fh,">",($file->{filepath}); >-print $fh ""; >-close $fh; >- >-my $DelResult; >-is(C4::UploadedFiles::DelUploadedFile($id),1, "DelUploadedFile($id) returned 1 as expected."); >-warning_like { $DelResult=C4::UploadedFiles::DelUploadedFile($id); } qr/file for hash/, "Expected warning for deleting Dangling Entry."; >-is($DelResult,-1, "DelUploadedFile($id) returned -1 as expected."); >-ok(! -e $file->{filepath}, "File $file->{filepath} does not exist anymore"); >- >-my $UploadResult; >-warning_like { $UploadResult=C4::UploadedFiles::UploadFile($testfilename,'../',$testfile_fh->handle); } qr/^Filename or dirname contains '..'. Aborting upload/, "Expected warning for bad file upload."; >-is($UploadResult, undef, "UploadFile with dir containing \"..\" return undef"); >-is(C4::UploadedFiles::GetUploadedFile(), undef, 'GetUploadedFile without parameters returns undef'); >- >-#trivial test for httpheaders >-my @hdrs = C4::UploadedFiles::httpheaders('does_not_matter_yet'); >-is( @hdrs == 4 && $hdrs[1] =~ /application\/octet-stream/, 1, 'Simple test for httpheaders'); #TODO Will be extended on report 14282 >diff --git a/test/progressbar.pl b/test/progressbar.pl >deleted file mode 100755 >index 87cd84c..0000000 >--- a/test/progressbar.pl >+++ /dev/null >@@ -1,55 +0,0 @@ >-#!/usr/bin/perl >- >-# Script for testing progressbar, part 1 - initial screem >-# it is split into two scripts so we can use firebug to debug it >- >-# Koha library project www.koha-community.org >- >-# Licensed under the GPL >- >-# Copyright 2010 Catalyst IT, Ltd >-# >-# This file is part of Koha. >-# >-# 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 strict; >-use warnings; >- >-# standard or CPAN modules used >-use CGI qw ( -utf8 ); >-use CGI::Cookie; >- >-# Koha modules used >-use C4::Context; >-use C4::Auth; >-use C4::Output; >-use C4::BackgroundJob; >- >-my $input = new CGI; >-my $dbh = C4::Context->dbh; >-$dbh->{AutoCommit} = 0; >- >-my ($template, $loggedinuser, $cookie) >- = get_template_and_user({template_name => "test/progressbar.tt", >- query => $input, >- type => "intranet", >- debug => 1, >- }); >- >-output_html_with_http_headers $input, $cookie, $template->output; >- >-exit 0; >- >- >diff --git a/test/progressbarsubmit.pl b/test/progressbarsubmit.pl >deleted file mode 100755 >index 0a4a497..0000000 >--- a/test/progressbarsubmit.pl >+++ /dev/null >@@ -1,104 +0,0 @@ >-#!/usr/bin/perl >- >-# Script for testing progressbar, part 2 - json submit handler >-# and Z39.50 lookups >- >-# Koha library project www.koha-community.org >- >-# Licensed under the GPL >- >-# Copyright 2010 Catalyst IT, Ltd >-# >-# This file is part of Koha. >-# >-# 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 strict; >-use warnings; >- >-# standard or CPAN modules used >-use CGI qw ( -utf8 ); >-use CGI::Cookie; >- >-# Koha modules used >-use C4::Context; >-use C4::Auth; >-use C4::Output; >-use C4::BackgroundJob; >- >-my $input = new CGI; >- >-my $submitted=$input->param('submitted'); >-my $runinbackground = $input->param('runinbackground'); >-my $jobID = $input->param('jobID'); >-my $completedJobID = $input->param('completedJobID'); >- >-my ($template, $loggedinuser, $cookie) >- = get_template_and_user({template_name => "test/progressbar.tt", >- query => $input, >- type => "intranet", >- debug => 1, >- }); >- >-my %cookies = parse CGI::Cookie($cookie); >-my $sessionID = $cookies{'CGISESSID'}->value; >-if ($completedJobID) { >-} elsif ($submitted) { >- my $job = undef; >- if ($runinbackground) { >- my $job_size = 100; >- $job = C4::BackgroundJob->new($sessionID, undef, $ENV{'SCRIPT_NAME'}, $job_size); >- $jobID = $job->id(); >- >- # fork off >- if (my $pid = fork) { >- # parent >- # return job ID as JSON >- >- # prevent parent exiting from >- # destroying the kid's database handle >- # FIXME: according to DBI doc, this may not work for Oracle >- >- my $reply = CGI->new(""); >- print $reply->header(-type => 'text/html'); >- print '{"jobID":"' . $jobID . '"}'; >- exit 0; >- } elsif (defined $pid) { >- # if we get here, we're a child that has detached >- # itself from Apache >- >- # close STDOUT to signal to Apache that >- # we're now running in the background >- close STDOUT; >- close STDERR; >- >- foreach (1..100) { >- $job->progress( $_ ); >- sleep 1; >- } >- $job->finish(); >- } else { >- # fork failed, so exit immediately >- die "fork failed while attempting to run $ENV{'SCRIPT_NAME'} as a background job"; >- } >- >- } >-} else { >- # initial form >- die "We should not be here"; >-} >- >-exit 0; >- >- >diff --git a/tools/upload-file-progress.pl b/tools/upload-file-progress.pl >deleted file mode 100755 >index cdb940b..0000000 >--- a/tools/upload-file-progress.pl >+++ /dev/null >@@ -1,61 +0,0 @@ >-#!/usr/bin/perl >- >-# Copyright (C) 2007 LibLime >-# >-# This file is part of Koha. >-# >-# 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 strict; >-#use warnings; FIXME - Bug 2505 >- >-# standard or CPAN modules used >-use IO::File; >-use CGI qw ( -utf8 ); >-use CGI::Session; >-use C4::Context; >-use C4::Auth qw/check_cookie_auth haspermission/; >-use C4::UploadedFile; >-use CGI::Cookie; # need to check cookies before >- # having CGI parse the POST request >- >-my $flags_required = [ >- {circulate => 'circulate_remaining_permissions'}, >- {tools => 'stage_marc_import'}, >- {tools => 'upload_local_cover_images'}, >-]; >- >-my %cookies = CGI::Cookie->fetch; >- >-my ($auth_status, $sessionID) = check_cookie_auth($cookies{'CGISESSID'}->value); >- >-my $auth_failure = 1; >-foreach my $flag_required ( @{$flags_required} ) { >- if ( my $flags = haspermission( C4::Context->config('user'), $flag_required ) ) { >- $auth_failure = 0 if $auth_status eq 'ok'; >- } >-} >- >-my $reply = CGI::->new; >-if ($auth_failure) { >- print $reply->header(-type => 'text/html'); >- print '{"progress":"0"}'; >- exit 0; >-} >- >-my $reported_progress = C4::UploadedFile->upload_progress($sessionID); >- >-print $reply->header(-type => 'text/html'); >-# response will be sent back as JSON >-print '{"progress":"' . $reported_progress . '"}'; >-- >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