virtualshelves => C4::Context->preference("virtualshelves"),
StaffSerialIssueDisplayCount => C4::Context->preference("StaffSerialIssueDisplayCount"),
NoZebra => C4::Context->preference('NoZebra'),
- EasyAnalyticalRecords => C4::Context->preference('EasyAnalyticalRecords'),
+ EasyAnalyticalRecords => C4::Context->preference('EasyAnalyticalRecords'),
+ LocalCoverImages => C4::Context->preference('LocalCoverImages'),
+ AllowMultipleCovers => C4::Context->preference('AllowMultipleCovers'),
);
}
else {
SyndeticsAwards => C4::Context->preference("SyndeticsAwards"),
SyndeticsSeries => C4::Context->preference("SyndeticsSeries"),
SyndeticsCoverImageSize => C4::Context->preference("SyndeticsCoverImageSize"),
+ OPACLocalCoverImages => C4::Context->preference("OPACLocalCoverImages"),
);
$template->param(OpacPublic => '1') if ($user || C4::Context->preference("OpacPublic"));
--- /dev/null
+package C4::Images;
+use strict;
+use warnings;
+use 5.010;
+
+use C4::Context;
+use GD;
+
+use vars qw($debug $VERSION @ISA @EXPORT);
+
+BEGIN {
+ # set the version for version checking
+ $VERSION = 3.03;
+ require Exporter;
+ @ISA = qw(Exporter);
+ @EXPORT = qw(
+ &PutImage
+ &RetrieveImage
+ &ListImagesForBiblio
+ &DelImage
+ );
+ $debug = $ENV{KOHA_DEBUG} || $ENV{DEBUG} || 0;
+}
+
+=head2 PutImage
+
+ PutImage($biblionumber, $srcimage, $replace);
+
+Stores binary image data and thumbnail in database, optionally replacing existing images for the given biblio.
+
+=cut
+
+sub PutImage {
+ my ($biblionumber, $srcimage, $replace) = @_;
+
+ return -1 unless defined($srcimage);
+
+ if ($replace) {
+ foreach (ListImagesForBiblio($biblionumber)) {
+ DelImage($_);
+ }
+ }
+
+ my $dbh = C4::Context->dbh;
+ my $query = "INSERT INTO biblioimages (biblionumber, mimetype, imagefile, thumbnail) VALUES (?,?,?,?);";
+ my $sth = $dbh->prepare($query);
+
+ my $mimetype = 'image/png'; # GD autodetects three basic image formats: PNG, JPEG, XPM; we will convert all to PNG which is lossless...
+# Check the pixel size of the image we are about to import...
+ my $thumbnail = _scale_image($srcimage, 140, 200); # MAX pixel dims are 140 X 200 for thumbnail...
+ my $fullsize = _scale_image($srcimage, 600, 800); # MAX pixel dims are 600 X 800 for full-size image...
+ $debug and warn "thumbnail is " . length($thumbnail) . " bytes.";
+
+ $sth->execute($biblionumber,$mimetype,$fullsize->png(),$thumbnail->png());
+ my $dberror = $sth->errstr;
+ warn "Error returned inserting $biblionumber.$mimetype." if $sth->errstr;
+ undef $thumbnail;
+ undef $fullsize;
+ return $dberror;
+}
+
+=head2 RetrieveImage
+ my ($imagedata, $error) = RetrieveImage($imagenumber);
+
+Retrieves the specified image.
+
+=cut
+
+sub RetrieveImage {
+ my ($imagenumber) = @_;
+
+ my $dbh = C4::Context->dbh;
+ my $query = 'SELECT mimetype, imagefile, thumbnail FROM biblioimages WHERE imagenumber = ?';
+ my $sth = $dbh->prepare($query);
+ $sth->execute($imagenumber);
+ my $imagedata = $sth->fetchrow_hashref;
+ if ($sth->err) {
+ warn "Database error!";
+ return undef;
+ } else {
+ return $imagedata;
+ }
+}
+
+=head2 ListImagesForBiblio
+ my (@images) = ListImagesForBiblio($biblionumber);
+
+Gets a list of all images associated with a particular biblio.
+
+=cut
+
+
+sub ListImagesForBiblio {
+ my ($biblionumber) = @_;
+
+ my @imagenumbers;
+ my $dbh = C4::Context->dbh;
+ my $query = 'SELECT imagenumber FROM biblioimages WHERE biblionumber = ?';
+ my $sth = $dbh->prepare($query);
+ $sth->execute($biblionumber);
+ warn "Database error!" if $sth->errstr;
+ if (!$sth->errstr && $sth->rows > 0) {
+ while (my $row = $sth->fetchrow_hashref) {
+ push @imagenumbers, $row->{'imagenumber'};
+ }
+ return @imagenumbers;
+ } else {
+ return undef;
+ }
+}
+
+=head2 DelImage
+
+ my ($dberror) = DelImage($imagenumber);
+
+Removes the image with the supplied imagenumber.
+
+=cut
+
+sub DelImage {
+ my ($imagenumber) = @_;
+ warn "Imagenumber passed to DelImage is $imagenumber" if $debug;
+ my $dbh = C4::Context->dbh;
+ my $query = "DELETE FROM biblioimages WHERE imagenumber = ?;";
+ my $sth = $dbh->prepare($query);
+ $sth->execute($imagenumber);
+ my $dberror = $sth->errstr;
+ warn "Database error!" if $sth->errstr;
+ return $dberror;
+}
+
+sub _scale_image {
+ my ($image, $maxwidth, $maxheight) = @_;
+ my ($width, $height) = $image->getBounds();
+ $debug and warn "image is $width pix X $height pix.";
+ if ($width > $maxwidth || $height > $maxheight) {
+# $debug and warn "$filename exceeds the maximum pixel dimensions of $maxwidth X $maxheight. Resizing...";
+ my $percent_reduce; # Percent we will reduce the image dimensions by...
+ if ($width > $maxwidth) {
+ $percent_reduce = sprintf("%.5f",($maxwidth/$width)); # If the width is oversize, scale based on width overage...
+ } else {
+ $percent_reduce = sprintf("%.5f",($maxheight/$height)); # otherwise scale based on height overage.
+ }
+ my $width_reduce = sprintf("%.0f", ($width * $percent_reduce));
+ my $height_reduce = sprintf("%.0f", ($height * $percent_reduce));
+ $debug and warn "Reducing image by " . ($percent_reduce * 100) . "\% or to $width_reduce pix X $height_reduce pix";
+ my $newimage = GD::Image->new($width_reduce, $height_reduce, 1); #'1' creates true color image...
+ $newimage->copyResampled($image,0,0,0,0,$width_reduce,$height_reduce,$width,$height);
+ return $newimage;
+ } else {
+ return $image;
+ }
+}
+
+1;
}
}
+=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();
--- /dev/null
+#! /usr/bin/perl
+use strict;
+use warnings;
+use C4::Context;
+my $dbh=C4::Context->dbh;
+
+$dbh->do( q|CREATE TABLE `biblioimages` (
+ `imagenumber` int(11) NOT NULL AUTO_INCREMENT,
+ `biblionumber` int(11) NOT NULL,
+ `mimetype` varchar(15) NOT NULL,
+ `imagefile` mediumblob NOT NULL,
+ `thumbnail` mediumblob NOT NULL,
+ PRIMARY KEY (`imagenumber`),
+ CONSTRAINT `bibliocoverimage_fk1` FOREIGN KEY (`biblionumber`) REFERENCES `biblio` (`biblionumber`) ON DELETE CASCADE ON UPDATE CASCADE
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8|);
+$dbh->do( q|INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('OPACLocalCoverImages','0','Display local cover images on OPAC search and details pages.','1','YesNo')|);
+$dbh->do( q|INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('LocalCoverImages','0','Display local cover images on intranet search and details pages.','1','YesNo')|);
+$dbh->do( q|INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('AllowMultipleCovers','0','Allow multiple cover images to be attached to each bibliographic record.','1','YesNo')|);
+$dbh->do( q|INSERT INTO permissions (module_bit, code, description) VALUES (13, 'upload_local_cover_images', 'Upload local cover images')|);
+print "Upgrade done (Added support for local cover images)\n";
(13, 'manage_csv_profiles', 'Manage CSV export profiles'),
(13, 'moderate_tags', 'Moderate patron tags'),
(13, 'rotating_collections', 'Manage rotating collections'),
+ (13, 'upload_local_cover_images', 'Upload local cover images'),
(15, 'check_expiration', 'Check the expiration of a serial'),
(15, 'claim_serials', 'Claim missing serials'),
(15, 'create_subscription', 'Create a new subscription'),
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+--
+-- Table structure for table `bibliocoverimage`
+--
+
+DROP TABLE IF EXISTS `bibliocoverimage`;
+
+CREATE TABLE `bibliocoverimage` (
+ `imagenumber` int(11) NOT NULL AUTO_INCREMENT,
+ `biblionumber` int(11) NOT NULL,
+ `mimetype` varchar(15) NOT NULL,
+ `imagefile` mediumblob NOT NULL,
+ `thumbnail` mediumblob NOT NULL,
+ PRIMARY KEY (`imagenumber`),
+ CONSTRAINT `bibliocoverimage_fk1` FOREIGN KEY (`biblionumber`) REFERENCES `biblio` (`biblionumber`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('EasyAnalyticalRecords','0','If on, display in the catalogue screens tools to easily setup analytical record relationships','','YesNo');
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacShowRecentComments',0,'If ON a link to recent comments will appear in the OPAC masthead',NULL,'YesNo');
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('CircAutoPrintQuickSlip', '1', 'Choose what should happen when an empty barcode field is submitted in circulation: Display a print quick slip window or Clear the screen.',NULL,'YesNo');
+INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('OPACLocalCoverImages','0','Display local cover images on OPAC search and details pages.','1','YesNo');
+INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('LocalCoverImages','0','Display local cover images on intranet details pages.','1','YesNo');
+INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('AllowMultipleCovers','0','Allow multiple cover images to be attached to each bibliographic record.','1','YesNo');
[% IF ( CAN_user_editcatalogue_edit_catalogue ) %]{ text: _("Edit Record"), url: "/cgi-bin/koha/cataloguing/addbiblio.pl?biblionumber=[% biblionumber %]&frameworkcode=&op=" },[% END %]
[% IF ( CAN_user_editcatalogue_edit_items ) %]{ text: _("Edit Items"), url: "/cgi-bin/koha/cataloguing/additem.pl?biblionumber=[% biblionumber %]" },[% END %]
[% IF ( CAN_user_editcatalogue_edit_items ) %]{ text: _("Attach Item"), url: "/cgi-bin/koha/cataloguing/moveitem.pl?biblionumber=[% biblionumber %]" },[% END %]
- [% IF ( EasyAnalyticalRecords ) %][% IF ( CAN_user_editcatalogue_edit_items ) %]{ text: _("Link to Host Item"), url: "/cgi-bin/koha/cataloguing/linkitem.pl?biblionumber=[% biblionumber %]" },[% END %][% END %]
+ [% IF ( EasyAnalyticalRecords ) %][% IF ( CAN_user_editcatalogue_edit_items ) %]{ text: _("Link to Host Item"), url: "/cgi-bin/koha/cataloguing/linkitem.pl?biblionumber=[% biblionumber %]" },[% END %][% END %]
+ [% IF ( LocalCoverImages ) %][% IF ( CAN_user_tools_upload_local_cover_images ) %]{ text: _("Upload Image"), url: "/cgi-bin/koha/tools/upload-cover-image.pl?biblionumber=[% biblionumber %]&filetype=image" },[% END %][% END %]
[% IF ( CAN_user_editcatalogue_edit_catalogue ) %]{ text: _("Edit as New (Duplicate)"), url: "/cgi-bin/koha/cataloguing/addbiblio.pl?biblionumber=[% biblionumber %]&frameworkcode=&op=duplicate" },[% END %]
[% IF ( CAN_user_editcatalogue_edit_catalogue ) %]{ text: _("Replace Record via Z39.50"), onclick: {fn: PopupZ3950 } },[% END %]
[% IF ( CAN_user_editcatalogue_edit_catalogue ) %]{ text: _("Delete Record"), onclick: {fn: confirm_deletion }[% IF ( count ) %],id:'disabled'[% END %] },[% END %]
[% IF ( CAN_user_tools_manage_staged_marc ) %]
<li><a href="/cgi-bin/koha/tools/manage-marc-import.pl">Staged MARC management</a></li>
[% END %]
+ [% IF ( CAN_user_tools_upload_local_cover_images ) %]
+ <li><a href="/cgi-bin/koha/tools/upload-cover-image.pl">Upload Local Cover Image</a></li>
+ [% END %]
</ul>
<h5>Additional Tools</h5>
<ul>
- pref: TagsExternalDictionary
class: file
- on the server to be approved without moderation.
+ Local Cover Images:
+ -
+ - pref: LocalCoverImages
+ choices:
+ yes: Display
+ no: "Don't display"
+ - local cover images on intranet search and details pages.
+ -
+ - pref: OPACLocalCoverImages
+ choices:
+ yes: Display
+ no: "Don't display"
+ - local cover images on OPAC search and details pages.
+ -
+ - pref: AllowMultipleCovers
+ choices:
+ yes: Allow
+ no: "Don't allow"
+ - multiple images to be attached to each bibliographic record.
<dd>Managed staged MARC records, including completing and reversing imports</dd>
[% END %]
+ [% IF ( CAN_user_tools_upload_local_cover_images ) %]
+ <dt><a href="/cgi-bin/koha/tools/upload-cover-image.pl">Upload Local Cover Image</a></dt>
+ <dd>Utility to upload scanned cover images for display in OPAC</dd>
+ [% END %]
+
</dl>
</div>
--- /dev/null
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Koha › Tools › Upload Images</title>
+[% INCLUDE 'doc-head-close.inc' %]
+[% INCLUDE 'file-upload.inc' %]
+[% INCLUDE 'background-job.inc' %]
+<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('/intranet-tmpl/prog/img/progress.png') -300px 0px no-repeat; }</style>
+<script type="text/javascript">
+//<![CDATA[
+$(document).ready(function(){
+ $("#processfile").hide();
+ $("#zipfile").click(function(){
+ $("#bibnum").hide();
+ });
+ $("#image").click(function(){
+ $("#bibnum").show();
+ });
+});
+function CheckForm(f) {
+ if ($("#fileToUpload").value == '') {
+ alert(_('Please upload a file first.'));
+ } else {
+ return submitBackgroundJob(f);
+ }
+ return false;
+}
+
+//]]>
+</script>
+</head>
+<body>
+[% INCLUDE 'header.inc' %]
+[% INCLUDE 'cat-search.inc' %]
+
+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> › [% IF ( uploadimage ) %]<a href="/cgi-bin/koha/tools/upload-cover-image.pl">Upload Local Cover Image</a> › Upload Results[% ELSE %]Upload Local Cover Image[% END %]</div>
+
+<div id="doc3" class="yui-t2">
+
+ <div id="bd">
+ <div id="yui-main">
+ <div class="yui-b">
+
+<h1>Upload Local Cover Image</h1>
+[% IF ( uploadimage ) %]
+<p>Image upload results :</p>
+<ul>
+ <li>[% total %] images found</li>
+ [% IF ( error ) %]
+ <div class="dialog alert">
+ [% IF ( error == 'UZIPFAIL' ) %]<p><b>Failed to unzip archive.<br />Please ensure you are uploading a valid zip file and try again.</b></p>
+ [% ELSIF ( error == 'OPNLINK' ) %]<p><b>Cannot open folder index (idlink.txt or datalink.txt) to read.<br />Please verify that it exists.</b></p>
+ [% ELSIF ( error == 'OPNIMG' ) %]<p><b>Cannot process file as an image.<br />Please ensure you only upload GIF, JPEG, PNG, or XPM images.</b></p>
+ [% ELSIF ( error == 'DELERR' ) %]<p><b>Unrecognized or missing field delimiter.<br />Please verify that you are using either a single quote or a tab.</b></p>
+ [% ELSIF ( error == 'DBERR' ) %]<p><b>Unable to save image to database.</b></p>
+ [% ELSE %]<p><b>An unknown error has occurred.<br />Please review the error log for more details.</b></p>[% END %]
+ </div>
+ </li>
+ [% END %]
+ <li><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblionumber %]">View final record</a></li>
+ <li><a href="/cgi-bin/koha/tools/tools-home.pl">Back</a></li>
+</ul>
+<hr />
+[% END %]
+<ul>
+ <li>Select an image file or ZIP file to upload. The tool will accept images in GIF, JPEG, PNG, and XPM formats.</li>
+</ul>
+<form method="post" action="[% SCRIPT_NAME %]" id="uploadfile" enctype="multipart/form-data">
+<fieldset class="rows" id="uploadform">
+<legend>Upload images</legend>
+<ol>
+ <li>
+ <div id="fileuploadform">
+ <label for="fileToUpload">Select the file to upload: </label>
+ <input type="file" id="fileToUpload" name="fileToUpload" />
+ </div> </li>
+</ol>
+ <fieldset class="action"><button class="submit" onclick="return ajaxFileUpload();">Upload file</button></fieldset>
+</fieldset>
+
+ <div id="uploadpanel"><div id="fileuploadstatus">Upload progress: <div id="fileuploadprogress"></div> <span id="fileuploadpercent">0</span>%</div>
+ <div id="fileuploadfailed"></div></div>
+</form>
+
+ <form method="post" id="processfile" action="[% SCRIPT_NAME %]" enctype="multipart/form-data">
+<fieldset class="rows">
+ <input type="hidden" name="uploadedfileid" id="uploadedfileid" value="" />
+ <input type="hidden" name="runinbackground" id="runinbackground" value="" />
+ <input type="hidden" name="completedJobID" id="completedJobID" value="" />
+ </fieldset>
+ <fieldset class="rows">
+ <legend>File type</legend>
+ <ol>
+ <li class="radio">
+ <input type="radio" id="zipfile" name="filetype" value="zip" [% IF (filetype != 'image' ) %]checked="checked"[% END %] />
+ <label for="zipfile">ZIP file</label>
+ </li>
+ <li class="radio">
+ <input type="radio" id="image" name="filetype" value="image" [% IF (filetype == 'image' ) %]checked="checked"[% END %] />
+ <label for="imagefile">Image file</label>
+ </li>
+ <li class="radio">
+ [% IF ( filetype == 'image' ) %]<span id="bibnum">[% ELSE %]<span id="bibnum" style="display: none">[% END %]<label for="biblionumber">Enter cover biblionumber: </label><input type="text" id="biblionumber" name="biblionumber" value="[% biblionumber %]" size="15" /></span>
+ </li>
+ </ol>
+ </fieldset>
+ <fieldset class="rows">
+ <legend>Options</legend>
+ <ol>
+ <li class="checkbox">
+ <input type="checkbox" id="replace" name="replace" [% IF AllowMultipleCovers == 0 %]checked="checked" disabled="disabled"[% END %] />
+ <label for="replace">Replace existing covers</label>
+ </li>
+ </ol>
+ </fieldset>
+ <fieldset class="action"><input type="submit" value="Process images" /></fieldset>
+
+ <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>
+<div class="yui-b">
+[% INCLUDE 'tools-menu.inc' %]
+</div>
+</div>
+[% INCLUDE 'intranet-bottom.inc' %]
--- /dev/null
+#!/usr/bin/perl
+#
+# Copyright 2011 C & P Bibliography Services
+#
+# 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place,
+# Suite 330, Boston, MA 02111-1307 USA
+#
+#
+#
+=head1 NAME
+
+upload-cover-image.pl - Script for handling uploading of both single and bulk coverimages and importing them into the database.
+
+=head1 SYNOPSIS
+
+upload-cover-image.pl
+
+=head1 DESCRIPTION
+
+This script is called and presents the user with an interface allowing him/her to upload a single cover image or bulk cover images via a zip file.
+Images will be resized into thumbnails of 140x200 pixels and larger images of
+800x600 pixels. If the images that are uploaded are larger, they will be
+resized, maintaining aspect ratio.
+
+=cut
+
+
+use strict;
+use warnings;
+
+use File::Temp;
+use CGI;
+use GD;
+use C4::Context;
+use C4::Auth;
+use C4::Output;
+use C4::Images;
+use C4::UploadedFile;
+
+my $debug = 1;
+
+my $input = new CGI;
+
+my $fileID=$input->param('uploadedfileid');
+my ($template, $loggedinuser, $cookie)
+ = get_template_and_user({template_name => "tools/upload-images.tmpl",
+ query => $input,
+ type => "intranet",
+ authnotrequired => 0,
+ flagsrequired => { tools => 'upload_cover_images'},
+ debug => 0,
+ });
+
+my $filetype = $input->param('filetype');
+my $biblionumber = $input->param('biblionumber');
+my $uploadfilename = $input->param('uploadfile');
+my $replace = $input->param('replace');
+my $op = $input->param('op');
+my %cookies = parse CGI::Cookie($cookie);
+my $sessionID = $cookies{'CGISESSID'}->value;
+
+my $error;
+
+$template->{VARS}->{'filetype'} = $filetype;
+$template->{VARS}->{'biblionumber'} = $biblionumber;
+
+my $total = 0;
+
+if ($fileID) {
+ my $uploaded_file = C4::UploadedFile->fetch($sessionID, $fileID);
+ if ($filetype eq 'image') {
+ my $fh = $uploaded_file->fh();
+ my $srcimage = GD::Image->new($fh);
+ if (defined $srcimage) {
+ my $dberror = PutImage($biblionumber, $srcimage, $replace);
+ if ($dberror) {
+ $error = 'DBERR';
+ } else {
+ $total = 1;
+ }
+ } else {
+ $error = 'OPNIMG';
+ }
+ undef $srcimage;
+ } else {
+ my $filename = $uploaded_file->filename();
+ my $dirname = File::Temp::tempdir( CLEANUP => 1);
+ unless (system("unzip", $filename, '-d', $dirname) == 0) {
+ $error = 'UZIPFAIL';
+ } else {
+ my @directories;
+ push @directories, "$dirname";
+ foreach my $recursive_dir ( @directories ) {
+ my $dir;
+ opendir $dir, $recursive_dir;
+ while ( my $entry = readdir $dir ) {
+ push @directories, "$recursive_dir/$entry" if ( -d "$recursive_dir/$entry" and $entry !~ /^[._]/ );
+ }
+ closedir $dir;
+ }
+ foreach my $dir ( @directories ) {
+ my $file;
+ if ( -e "$dir/idlink.txt" ) {
+ $file = "$dir/idlink.txt";
+ } elsif ( -e "$dir/datalink.txt" ) {
+ $file = "$dir/datalink.txt";
+ } else {
+ next;
+ }
+ if (open (FILE, $file)) {
+ while (my $line = <FILE>) {
+ my $delim = ($line =~ /\t/) ? "\t" : ($line =~ /,/) ? "," : "";
+ #$debug and warn "Delimeter is \'$delim\'";
+ unless ( $delim eq "," || $delim eq "\t" ) {
+ warn "Unrecognized or missing field delimeter. Please verify that you are using either a ',' or a 'tab'";
+ $error = 'DELERR';
+ } else {
+ ($biblionumber, $filename) = split $delim, $line;
+ $biblionumber =~ s/[\"\r\n]//g; # remove offensive characters
+ $filename =~ s/[\"\r\n\s]//g;
+ my $srcimage = GD::Image->new("$dir/$filename");
+ if (defined $srcimage) {
+ $total++;
+ my $dberror = PutImage($biblionumber, $srcimage, $replace);
+ if ($dberror) {
+ $error = 'DBERR';
+ }
+ } else {
+ $error = 'OPNIMG';
+ }
+ undef $srcimage;
+ }
+ }
+ close(FILE);
+ } else {
+ $error = 'OPNLINK';
+ }
+ }
+ }
+ }
+ $template->{VARS}->{'total'} = $total;
+ $template->{VARS}->{'uploadimage'} = 1;
+ $template->{VARS}->{'error'} = $error;
+ $template->{VARS}->{'biblionumber'} = $biblionumber;
+}
+
+output_html_with_http_headers $input, $cookie, $template->output;
+
+exit 0;
+
+=head1 AUTHORS
+
+Written by Jared Camins-Esakov of C & P Bibliography Services, in part based on
+code by Koustubha Kale of Anant Corporation and Chris Nighswonger of Foundation
+Bible College.
+
+=cut