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

(-)a/installer/data/mysql/en/mandatory/userpermissions.sql (+1 lines)
Lines 36-41 INSERT INTO permissions (module_bit, code, description) VALUES Link Here
36
   (13, 'manage_csv_profiles', 'Manage CSV export profiles'),
36
   (13, 'manage_csv_profiles', 'Manage CSV export profiles'),
37
   (13, 'moderate_tags', 'Moderate patron tags'),
37
   (13, 'moderate_tags', 'Moderate patron tags'),
38
   (13, 'rotating_collections', 'Manage rotating collections'),
38
   (13, 'rotating_collections', 'Manage rotating collections'),
39
   (13, 'upload_local_cover_images', 'Upload local cover images'),
39
   (15, 'check_expiration', 'Check the expiration of a serial'),
40
   (15, 'check_expiration', 'Check the expiration of a serial'),
40
   (15, 'claim_serials', 'Claim missing serials'),
41
   (15, 'claim_serials', 'Claim missing serials'),
41
   (15, 'create_subscription', 'Create a new subscription'),
42
   (15, 'create_subscription', 'Create a new subscription'),
(-)a/installer/data/mysql/kohastructure.sql (+13 lines)
Lines 2665-2670 CREATE TABLE `fieldmapping` ( -- koha to keyword mapping Link Here
2665
  PRIMARY KEY  (`id`)
2665
  PRIMARY KEY  (`id`)
2666
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2666
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2667
2667
2668
--
2669
-- Table structure for table `bibliocoverimage`
2670
--
2671
2672
DROP TABLE IF EXISTS `bibliocoverimage`;
2673
2674
CREATE TABLE `bibliocoverimage` (
2675
 `biblionumber` int(11) NOT NULL,
2676
 `mimetype` varchar(15) NOT NULL,
2677
 `imagefile` mediumblob NOT NULL,
2678
 PRIMARY KEY (`biblionumber`),
2679
 CONSTRAINT `bibliocoverimage_fk1` FOREIGN KEY (`biblionumber`) REFERENCES `biblio` (`biblionumber`) ON DELETE CASCADE ON UPDATE CASCADE
2680
) ENGINE=InnoDB DEFAULT CHARSET=utf8
2668
2681
2669
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
2682
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
2670
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
2683
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
(-)a/installer/data/mysql/sysprefs.sql (-1 / +1 lines)
Lines 328-331 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES(' Link Here
328
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('OpacKohaUrl','1',"Show 'Powered by Koha' text on OPAC footer.",NULL,NULL);
328
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('OpacKohaUrl','1',"Show 'Powered by Koha' text on OPAC footer.",NULL,NULL);
329
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');
329
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');
330
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');
330
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');
331
331
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('OPACLocalCoverImages','0','Display local cover images on OPAC search and details pages.','1','YesNo');
(-)a/installer/data/mysql/updatedatabase.pl (+16 lines)
Lines 4550-4555 if (C4::Context->preference("Version") < TransformToNum($DBversion)) { Link Here
4550
    SetVersion ($DBversion);
4550
    SetVersion ($DBversion);
4551
}
4551
}
4552
4552
4553
$DBversion = '3.06.00.XXX';
4554
if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
4555
    $dbh->do( q|CREATE TABLE `bibliocoverimage` (
4556
      `biblionumber` int(11) NOT NULL,
4557
      `mimetype` varchar(15) NOT NULL,
4558
      `imagefile` mediumblob NOT NULL,
4559
      PRIMARY KEY (`biblionumber`),
4560
      CONSTRAINT `bibliocoverimage_fk1` FOREIGN KEY (`biblionumber`) REFERENCES `biblio` (`biblionumber`) ON DELETE CASCADE ON UPDATE CASCADE
4561
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8|);
4562
   $dbh->do( q|INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('OPACLocalCoverImages','0','Display local cover mages on OPAC search and details pages.','1','YesNo')|);
4563
   $dbh->do( q|INSERT INTO permissions (module_bit, code, description) VALUES (13, 'upload_local_cover_images', 'Upload local cover images')|);
4564
    print "Upgrade to $DBversion done (Added bibliocoverimage table to stover local cover images)\n";
4565
    SetVersion ($DBversion);
4566
}
4567
4568
4553
=head1 FUNCTIONS
4569
=head1 FUNCTIONS
4554
4570
4555
=head2 DropAllForeignKeys($table)
4571
=head2 DropAllForeignKeys($table)
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc (+3 lines)
Lines 70-75 Link Here
70
    [% IF ( CAN_user_tools_manage_staged_marc ) %]
70
    [% IF ( CAN_user_tools_manage_staged_marc ) %]
71
	<li><a href="/cgi-bin/koha/tools/manage-marc-import.pl">Staged MARC management</a></li>
71
	<li><a href="/cgi-bin/koha/tools/manage-marc-import.pl">Staged MARC management</a></li>
72
    [% END %]
72
    [% END %]
73
    [% IF ( CAN_user_tools_upload_local_cover_images ) %]
74
	<li><a href="/cgi-bin/koha/tools/upload-cover-image.pl">Upload Local Cover Image</a></li>
75
    [% END %]
73
</ul>
76
</ul>
74
<h5>Additional Tools</h5>
77
<h5>Additional Tools</h5>
75
<ul>
78
<ul>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/enhanced_content.pref (+7 lines)
Lines 311-313 Enhanced Content: Link Here
311
            - pref: TagsExternalDictionary
311
            - pref: TagsExternalDictionary
312
              class: file
312
              class: file
313
            - on the server to be approved without moderation.
313
            - on the server to be approved without moderation.
314
    Local Cover Images:
315
        -
316
            - pref: OPACLocalCoverImages
317
              choices:
318
                  yes: Display
319
                  no: "Don't display"
320
            - local cover images on OPAC search and details pages.
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt (+5 lines)
Lines 140-145 Link Here
140
    <dd>Managed staged MARC records, including completing and reversing imports</dd>
140
    <dd>Managed staged MARC records, including completing and reversing imports</dd>
141
    [% END %]
141
    [% END %]
142
142
143
    [% IF ( CAN_user_tools_upload_local_cover_images ) %]
144
    <dt><a href="/cgi-bin/koha/tools/upload-cover-image.pl">Upload Local Cover Image</a></dt>
145
    <dd>Utility to upload scanned cover images for display in OPAC</dd>
146
    [% END %]
147
143
</dl>
148
</dl>
144
</div>
149
</div>
145
150
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-cover-image.tt (+126 lines)
Line 0 Link Here
1
[% INCLUDE 'doc-head-open.inc' %]
2
<title>Koha &rsaquo; Tools &rsaquo; Upload Cover Images</title>
3
[% INCLUDE 'doc-head-close.inc' %]
4
<script type="text/javascript">
5
 $(document).ready(function() {
6
	$("#zipfile").click(function(){
7
		$("#bibnum").hide();
8
	});
9
	$("#image").click(function(){
10
		$("#bibnum").show();
11
	});
12
});
13
</script>
14
</head>
15
<body>
16
17
[% INCLUDE 'header.inc' %]
18
[%# [% INCLUDE 'cover-search.inc' %] %]
19
20
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> &rsaquo; Upload Cover Images </div>
21
22
<div id="doc3" class="yui-t2">
23
    <div id="bd">
24
        <div id="yui-main">
25
[% IF ( TOTAL ) %]
26
    <div class="yui-b">
27
        <div class="yui-g">
28
            <div class="yui-u first">
29
            [% IF ( ERRORS ) %]
30
				[% IF ( TCOUNTS ) %]
31
					<div class="dialog alert">
32
					<h3>Cover Image(s) Uploaded With Some Errors</h3>
33
				[% ELSE %]
34
					<div class="dialog alert">
35
					<h3>Cover Image Failed to Upload</h3>
36
				[% END %]
37
            [% ELSE %]
38
                <div class="dialog message">
39
                <h3>Cover Image(s) Successfully Uploaded</h3>
40
            [% END %]
41
	        <ul class="data">
42
	            <li>Unpacking completed</li>
43
                  <li>[% TOTAL %] directorie(s) scanned.</li>
44
                    <li>[% HANDLED %] directorie(s) processed.</li>
45
                </ul>
46
                [% FOREACH COUNT IN COUNTS %]
47
	            <ul class="data">
48
                        [% IF ( COUNT.TCOUNTS ) %]<li>[% COUNT.TCOUNTS %] image(s) moved into the database:</li>[% END %]
49
                        [% FOREACH filename IN COUNT.filenames %]
50
                            <li>[% filename.source %] - Biblionumber: [% filename.biblionumber %]
51
                                    [% IF ( filename.filerrors ) %]<br /> <b>WARNING:</b> This image <i>not</i> imported because 
52
                                    [% FOREACH filerror IN filename.filerrors %]
53
                                        [% IF ( filerror.DBERR ) %]the database returned an error. Please refer to the error log for more details.</li>
54
                                        [% ELSIF ( filerror.IMGEXISTS ) %]this cover does not exist in the database.</li>
55
                                        [% ELSIF ( filerror.MIMERR ) %]the image format is unrecognized.</li>
56
                                        [% ELSIF ( filerror.CORERR ) %]the image file is corrupted.</li>
57
                                        [% ELSIF ( filerror.OPNERR ) %]Koha was unable to open the image for reading.</li>
58
                                        [% ELSIF ( filerror.OVRSIZ ) %]the image file is too big.</li>
59
                                        [% ELSIF ( filerror.CRDFIL ) %]the [% filerror.CRDFIL %] is missing.</li>
60
                                        [% ELSE %]of an unknown error. Please refer to the error log for more details.</li>[% END %]
61
                                    [% END %]
62
                                        [% ELSE %] imported successfully.</li>
63
                                    [% END %]
64
                        [% END %]
65
                        </ul>
66
                [% END %]
67
68
				</div>
69
				
70
					<a id="uploadmore" href="/cgi-bin/koha/tools/upload-cover-image.pl">Upload More Images</a>
71
					<a id="doneupload" href="/cgi-bin/koha/tools/tools-home.pl">Return to Tools</a>
72
            </div>
73
[% ELSE %]
74
    <div class="yui-b">
75
        <div class="yui-g">
76
            <div class="yui-u first">
77
                <h1>Upload Cover Images</h1>
78
                [% IF ( ERRORS ) %]
79
                <div class="dialog alert">
80
                    [% FOREACH ERROR IN ERRORS %]
81
                        [% IF ( ERROR.NOTZIP ) %]<li><b>The upload file does not appear to be a zip file.  The extension is not '.zip'.</b></li>
82
                        [% ELSIF ( ERROR.NOWRITETEMP ) %]<li><b>This script is not able to create/write to the necessary temporary directory.</b></li>
83
                        [% ELSIF ( ERROR.EMPTYUPLOAD ) %]<li><b>The upload file appears to be empty.</b></li>
84
                        [% ELSIF ( ERROR.OPNLINK ) %]<li><b>Cannot open [% ERROR.OPNLINK %] to read.<br />Please verify that it exists.</b></li>
85
                        [% ELSIF ( ERROR.OPNIMG ) %]<li><b>Cannot open [% ERROR.OPNIMG %] to read.<br />Please verify that it exists.</b></li>
86
                        [% ELSIF ( ERROR.DELERR ) %]<li><b>Unrecognized or missing field delimiter.<br />Please verify that you are using either a single quote or a tab.</b></li>
87
                        [% ELSIF ( ERROR.UZIPFAIL ) %]<li><b>[% ERROR.UZIPFAIL %] failed to unpack.<br />Please verify the integrity of the zip file and retry.</b></li>
88
                        [% ELSE %]<li><b>[% ERROR.CORERR %] An unknown error has occurred.<br />Please review the error log for more details.</b></li>[% END %]
89
                    [% END %]
90
                </div>
91
                [% END %]
92
	        <form method="post" action="/cgi-bin/koha/tools/upload-cover-image.pl" enctype="multipart/form-data">
93
	            <fieldset class="brief">
94
			 <div class="hint"><b>NOTE:</b> Only PNG, GIF, JPEG, XPM formats are supported.</div>
95
                        <ol class="radio">
96
                            <li class="radio">
97
                                <label for="zipfile"><input type="radio" id="zipfile" name="filetype" value="zip" checked="checked" /> zip file</label></li>
98
                                <li>
99
                                <label for="image">
100
								[% IF ( filetype == 'image' ) %]<input type="radio" id="image" name="filetype" value="image" checked="checked" />[% ELSE %]<input type="radio" id="image" name="filetype" value="image" />[% END %]
101
								 image file</label>
102
	                <ol>
103
                            <li>
104
                                <label for="uploadfile">Select the file to upload: </label><input type="file" id="uploadfile" name="uploadfile" />
105
                                [% 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>
106
                            </li>
107
    	                </ol>
108
					</li></ol>
109
	            </fieldset>
110
                    <fieldset class="action">
111
                        <input type="hidden" name="op" value="Upload" />
112
                        <input type="submit" value="Upload" class="submit" />
113
						<a href="/cgi-bin/koha/tools/tools-home.pl" class="cancel">Cancel</a>
114
                    </fieldset>
115
                </form>
116
	
117
            </div>	
118
[% END %]
119
        </div>
120
    </div>
121
</div>
122
<div class="yui-b noprint">
123
    [% INCLUDE 'tools-menu.inc' %]
124
</div>
125
</div>
126
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt (+1 lines)
Lines 224-229 YAHOO.util.Event.onContentReady("furtherm", function () { Link Here
224
    <div id="catalogue_detail_biblio">
224
    <div id="catalogue_detail_biblio">
225
225
226
    <div id="bookcover">
226
    <div id="bookcover">
227
	 [% IF ( OPACLocalCoverImages ) %] <img src="/cgi-bin/koha/opac-coverimage.pl?bibnum=[% biblionumber %]" alt="No Local Cover Image" class="thumbnail" />[% ELSE %]<span class="no-image">No Local cover image available</span>[% END %]
227
    [% IF ( OPACAmazonEnabled ) %][% IF ( OPACAmazonCoverImages ) %][% IF ( OPACurlOpenInNewWindow ) %]<a href="http://www.amazon[% AmazonTld %]/gp/reader/[% normalized_isbn %]/ref=sib_dp_pt/002-7879865-0184864#reader-link" target="_blank"><img border="0" src="http://images.amazon.com/images/P/[% normalized_isbn %].01.MZZZZZZZ.jpg" alt="Cover Image" /></a>[% ELSE %]<a href="http://www.amazon[% AmazonTld %]/gp/reader/[% normalized_isbn %]/ref=sib_dp_pt/002-7879865-0184864#reader-link"><img border="0" src="http://images.amazon.com/images/P/[% normalized_isbn %].01.MZZZZZZZ.jpg" alt="Cover Image" /></a>[% END %][% END %][% END %]
228
    [% IF ( OPACAmazonEnabled ) %][% IF ( OPACAmazonCoverImages ) %][% IF ( OPACurlOpenInNewWindow ) %]<a href="http://www.amazon[% AmazonTld %]/gp/reader/[% normalized_isbn %]/ref=sib_dp_pt/002-7879865-0184864#reader-link" target="_blank"><img border="0" src="http://images.amazon.com/images/P/[% normalized_isbn %].01.MZZZZZZZ.jpg" alt="Cover Image" /></a>[% ELSE %]<a href="http://www.amazon[% AmazonTld %]/gp/reader/[% normalized_isbn %]/ref=sib_dp_pt/002-7879865-0184864#reader-link"><img border="0" src="http://images.amazon.com/images/P/[% normalized_isbn %].01.MZZZZZZZ.jpg" alt="Cover Image" /></a>[% END %][% END %][% END %]
228
229
229
    [% IF ( SyndeticsEnabled ) %][% IF ( SyndeticsCoverImages ) %][% IF ( content_identifier_exists ) %][% IF ( using_https ) %]
230
    [% IF ( SyndeticsEnabled ) %][% IF ( SyndeticsCoverImages ) %][% IF ( content_identifier_exists ) %][% IF ( using_https ) %]
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt (+1 lines)
Lines 528-533 $(document).ready(function(){ Link Here
528
				</span>
528
				</span>
529
				</td><td>
529
				</td><td>
530
					<a class="p1" href="/cgi-bin/koha/opac-detail.pl?biblionumber=[% SEARCH_RESULT.biblionumber %]">
530
					<a class="p1" href="/cgi-bin/koha/opac-detail.pl?biblionumber=[% SEARCH_RESULT.biblionumber %]">
531
			[% IF ( OPACLocalCoverImages ) %] <img src="/cgi-bin/koha/opac-coverimage.pl?bibnum=[% SEARCH_RESULT.biblionumber %] alt="No Local Cover Image" class="thumbnail" />[% ELSE %]<span class="no-image">No Local cover image available</span>[% END %]
531
                    [% IF ( OPACAmazonEnabled ) %][% IF ( OPACAmazonCoverImages ) %][% IF ( SEARCH_RESULT.normalized_isbn ) %]<img src="http://images.amazon.com/images/P/[% SEARCH_RESULT.normalized_isbn %].01.TZZZZZZZ.jpg" alt="" class="thumbnail" />[% ELSE %]<span class="no-image">No cover image available</span>[% END %][% END %][% END %]
532
                    [% IF ( OPACAmazonEnabled ) %][% IF ( OPACAmazonCoverImages ) %][% IF ( SEARCH_RESULT.normalized_isbn ) %]<img src="http://images.amazon.com/images/P/[% SEARCH_RESULT.normalized_isbn %].01.TZZZZZZZ.jpg" alt="" class="thumbnail" />[% ELSE %]<span class="no-image">No cover image available</span>[% END %][% END %][% END %]
532
533
533
					[% IF ( SyndeticsEnabled ) %][% IF ( SyndeticsCoverImages ) %][% IF ( using_https ) %]
534
					[% IF ( SyndeticsEnabled ) %][% IF ( SyndeticsCoverImages ) %][% IF ( using_https ) %]
(-)a/opac/opac-coverimage.pl (+105 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
#
3
# based on patronimage.pl
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
#
20
#
21
#
22
23
use strict;
24
use warnings;
25
26
use CGI; #qw(:standard escapeHTML);
27
use C4::Context;
28
29
$|=1;
30
31
my $DEBUG = 0;
32
my $data = new CGI;
33
my $biblionumber;
34
35
=head1 NAME
36
37
opac-coverimage.pl - Script for retrieving and formatting local cover images for display
38
39
=head1 SYNOPSIS
40
41
<img src="opac-coverimage.pl?bibnum= />
42
43
=head1 DESCRIPTION
44
45
This script, when called from within HTML and passed a valid biblionumber, will retrieve the image data associated with that biblionumber if one exists, format it in proper HTML format and pass it back to be displayed.
46
47
=cut
48
49
if ($data->param('bibnum')) {
50
    $biblionumber = $data->param('bibnum');
51
} else {
52
    $biblionumber = shift;
53
}
54
55
56
warn "biblionumber passed in: $biblionumber" if $DEBUG;
57
58
my ($imagedata, $dberror) = GetCoverImage($biblionumber);
59
60
if ($dberror) {
61
    warn "Database Error!";
62
    exit;
63
}
64
65
# NOTE: Never dump the contents of $imagedata->{'patronimage'} via a warn to a log or nasty
66
# things will result... you have been warned!
67
68
if ($imagedata) {
69
    print $data->header (-type => $imagedata->{'mimetype'}, -'Cache-Control' => 'no-store', -Content_Length => length ($imagedata->{'imagefile'})), $imagedata->{'imagefile'};
70
    exit;
71
} else {
72
    warn "No image exists for $biblionumber";
73
    exit;
74
}
75
76
=head2 GetCoverImage
77
78
    my ($imagedata, $dberror) = GetCoverImage($biblionumber);
79
80
Returns the mimetype and binary image data of the local cover image for the biblio with the supplied biblionumber.
81
82
=cut
83
84
sub GetCoverImage {
85
    my ($biblionumber) = @_;
86
    warn "Biblionumber passed to GetCoverImage is $biblionumber" if $DEBUG;
87
    my $dbh = C4::Context->dbh;
88
    my $query = 'SELECT mimetype, imagefile FROM bibliocoverimage WHERE biblionumber = ?';
89
    my $sth = $dbh->prepare($query);
90
    $sth->execute($biblionumber);
91
    my $imagedata = $sth->fetchrow_hashref;
92
    warn "Database error!" if $sth->errstr;
93
    return $imagedata, $sth->errstr;
94
}
95
96
97
exit;
98
99
=head1 AUTHOR
100
101
Chris Nighswonger cnighswonger <at> foundations <dot> edu
102
103
modified for local cover images by Koustubha Kale kmkale <at> anantcorp <dot> com
104
105
=cut
(-)a/opac/opac-detail.pl (+5 lines)
Lines 681-686 if (scalar(@serialcollections) > 0) { Link Here
681
	serialcollections => \@serialcollections);
681
	serialcollections => \@serialcollections);
682
}
682
}
683
683
684
# Local cover Images stuff
685
if (C4::Context->preference("OPACLocalCoverImages")){
686
		$template->param(OPACLocalCoverImages => 1);
687
}
688
684
# Amazon.com Stuff
689
# Amazon.com Stuff
685
if ( C4::Context->preference("OPACAmazonEnabled") ) {
690
if ( C4::Context->preference("OPACAmazonEnabled") ) {
686
    $template->param( AmazonTld => get_amazon_tld() );
691
    $template->param( AmazonTld => get_amazon_tld() );
(-)a/opac/opac-search.pl (+4 lines)
Lines 611-616 for (my $i=0;$i<@servers;$i++) { Link Here
611
            $template->param(SEARCH_RESULTS => \@newresults,
611
            $template->param(SEARCH_RESULTS => \@newresults,
612
                                OPACItemsResultsDisplay => (C4::Context->preference("OPACItemsResultsDisplay") eq "itemdetails"?1:0),
612
                                OPACItemsResultsDisplay => (C4::Context->preference("OPACItemsResultsDisplay") eq "itemdetails"?1:0),
613
                            );
613
                            );
614
	    if (C4::Context->preference("OPACLocalCoverImages")){
615
		$template->param(OPACLocalCoverImages => 1);
616
		$template->param(OPACLocalCoverImagesPriority => C4::Context->preference("OPACLocalCoverImagesPriority"));
617
	    }
614
            ## Build the page numbers on the bottom of the page
618
            ## Build the page numbers on the bottom of the page
615
            my @page_numbers;
619
            my @page_numbers;
616
            # total number of pages there will be
620
            # total number of pages there will be
(-)a/tools/upload-cover-image.pl (-1 / +341 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
#
3
#
4
# This file is part of Koha.
5
#
6
# Koha is free software; you can redistribute it and/or modify it under the
7
# terms of the GNU General Public License as published by the Free Software
8
# Foundation; either version 2 of the License, or (at your option) any later
9
# version.
10
#
11
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
12
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License along with
16
# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
17
# Suite 330, Boston, MA  02111-1307 USA
18
#
19
#
20
#
21
22
#use strict;
23
#use warnings; FIXME - Bug 2505
24
25
use File::Temp;
26
use File::Copy;
27
use CGI;
28
use GD;
29
use C4::Context;
30
use C4::Auth;
31
use C4::Output;
32
use C4::Debug;
33
34
my $input = new CGI;
35
36
my ($template, $loggedinuser, $cookie)
37
	= get_template_and_user({template_name => "tools/upload-cover-image.tmpl",
38
					query => $input,
39
					type => "intranet",
40
					authnotrequired => 0,
41
					flagsrequired => { tools => '*'},
42
					debug => 0,
43
					});
44
45
my $filetype            = $input->param('filetype');
46
my $biblionumber          = $input->param('biblionumber');
47
my $uploadfilename      = $input->param('uploadfile');
48
my $uploadfile          = $input->upload('uploadfile');
49
my $op                  = $input->param('op');
50
51
#FIXME: This code is really in the rough. The variables need to be re-scoped as the two subs depend on global vars to operate.
52
#       Other parts of this code could be optimized as well, I think. Perhaps the file upload could be done with YUI's upload
53
#       coded. -fbcit
54
55
$debug and warn "Params are: filetype=$filetype, biblionumber=$biblionumber, uploadfile=$uploadfilename";
56
57
=head1 NAME
58
59
upload-cover-image.pl - Script for handling uploading of both single and bulk coverimages and importing them into the database.
60
61
=head1 SYNOPSIS
62
63
Copied from picture-upload.pl
64
65
=head1 DESCRIPTION
66
67
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.
68
Files greater than 100K will be refused. Images should be 140x200 pixels. If they are larger they will be auto-resized to comply.
69
70
=cut
71
72
$debug and warn "Operation requested: $op";
73
74
my ( $total, $handled, @counts, $tempfile, $tfh );
75
76
if ( ($op eq 'Upload') && $uploadfile ) {       # Case is important in these operational values as the template must use case to be visually pleasing!
77
    my $dirname = File::Temp::tempdir( CLEANUP => 1);
78
    $debug and warn "dirname = $dirname";
79
    my $filesuffix = $1 if $uploadfilename =~ m/(\..+)$/i;
80
    ( $tfh, $tempfile ) = File::Temp::tempfile( SUFFIX => $filesuffix, UNLINK => 1 );
81
    $debug and warn "tempfile = $tempfile";
82
    my ( @directories, $errors );
83
84
    $errors{'NOTZIP'} = 1 if ( $uploadfilename !~ /\.zip$/i && $filetype =~ m/zip/i );
85
    $errors{'NOWRITETEMP'} = 1 unless ( -w $dirname );
86
    $errors{'EMPTYUPLOAD'} = 1 unless ( length( $uploadfile ) > 0 );
87
88
    if ( %errors ) {
89
	$template->param( ERRORS => [ \%errors ] );
90
    } else {
91
	while ( <$uploadfile> ) {
92
	    print $tfh $_;
93
        }
94
        close $tfh;
95
        if ( $filetype eq 'zip' ) {
96
            unless (system("unzip", $tempfile,  '-d', $dirname) == 0) {
97
                $errors{'UZIPFAIL'} = $uploadfilename;
98
	        $template->param( ERRORS => [ \%errors ] );
99
                output_html_with_http_headers $input, $cookie, $template->output;   # This error is fatal to the import, so bail out here
100
                exit;
101
            }
102
            push @directories, "$dirname";
103
            foreach $recursive_dir ( @directories ) {
104
                opendir $dir, $recursive_dir;
105
                while ( my $entry = readdir $dir ) {
106
	        push @directories, "$recursive_dir/$entry" if ( -d "$recursive_dir/$entry" and $entry !~ /^\./ );
107
                $debug and warn "$recursive_dir/$entry";
108
                }
109
                closedir $dir;
110
            }
111
            my $results;
112
            foreach my $dir ( @directories ) {
113
                $results = handle_dir( $dir, $filesuffix );
114
                $handled++ if $results == 1;
115
            }
116
            $total = scalar @directories;
117
        } else {       #if ($filetype eq 'zip' )
118
            $results = handle_dir( $dirname, $filesuffix );
119
            $handled = 1;
120
            $total = 1;
121
        }
122
123
        if ( %$results || %errors ) {
124
            $template->param( ERRORS => [ \%$results ] );
125
        } else {
126
			my $filecount;
127
			map {$filecount += $_->{count}} @counts;
128
            $debug and warn "Total directories processed: $total";
129
            $debug and warn "Total files processed: $filecount";
130
            $template->param(
131
		 	TOTAL => $total,
132
		 	HANDLED => $handled,
133
		 	COUNTS => \@counts,
134
			TCOUNTS => ($filecount > 0 ? $filecount : undef),
135
            );
136
			$template->param( biblionumber => $biblionumber ) if $biblionumber;
137
        }
138
    }
139
} elsif ( ($op eq 'Upload') && !$uploadfile ) {
140
    warn "Problem uploading file or no file uploaded.";
141
    $template->param(biblionumber => $biblionumber);
142
    $template->param(filetype => $filetype);
143
} elsif ( $op eq 'Delete' ) {
144
    my $dberror = RmBiblioImage($biblionumber);
145
	$debug and warn "Cover image deleted for $biblionumber";
146
    warn "Database returned $dberror" if $dberror;
147
}
148
149
output_html_with_http_headers $input, $cookie, $template->output;
150
151
152
sub handle_dir {
153
    my ( $dir, $suffix ) = @_;
154
    my $source;
155
    $debug and warn "Entering sub handle_dir; passed \$dir=$dir, \$suffix=$suffix";
156
    if ($suffix =~ m/zip/i) {     # If we were sent a zip file, process any included data/idlink.txt files
157
        my ( $file, $filename, $biblionumber );
158
        $debug and warn "Passed a zip file.";
159
        opendir my $dirhandle, $dir;
160
        while ( my $filename = readdir $dirhandle ) {
161
            $file = "$dir/$filename" if ($filename =~ m/datalink\.txt/i || $filename =~ m/idlink\.txt/i);
162
        }
163
        unless (open (FILE, $file)) {
164
		warn "Opening $dir/$file failed!";
165
                $errors{'OPNLINK'} = $file;
166
		return $errors; # This error is fatal to the import of this directory contents, so bail and return the error to the caller
167
        };
168
169
        while (my $line = <FILE>) {
170
            $debug and warn "Reading contents of $file";
171
	    chomp $line;
172
            $debug and warn "Examining line: $line";
173
	    my $delim = ($line =~ /\t/) ? "\t" : ($line =~ /,/) ? "," : "";
174
            $debug and warn "Delimeter is \'$delim\'";
175
            unless ( $delim eq "," || $delim eq "\t" ) {
176
                warn "Unrecognized or missing field delimeter. Please verify that you are using either a ',' or a 'tab'";
177
                $errors{'DELERR'} = 1;      # This error is fatal to the import of this directory contents, so bail and return the error to the caller
178
                return $errors;
179
            }
180
	    ($biblionumber, $filename) = split $delim, $line;
181
	    $biblionumber =~ s/[\"\r\n]//g;  # remove offensive characters
182
	    $filename   =~ s/[\"\r\n\s]//g;
183
            $debug and warn "Biblionumber: $biblionumber Filename: $filename";
184
            $source = "$dir/$filename";
185
            %counts = handle_file($biblionumber, $source, %counts);
186
        }
187
        close FILE;
188
        closedir ($dirhandle);
189
    } else {
190
        $source = $tempfile;
191
        %counts = handle_file($biblionumber, $source, %counts);
192
    }
193
push @counts, \%counts;
194
return 1;
195
}
196
197
sub handle_file {
198
    my ($biblionumber, $source, %count) = @_;
199
    $debug and warn "Entering sub handle_file; passed \$biblionumber=$biblionumber, \$source=$source";
200
    $count{filenames} = () if !$count{filenames};
201
    $count{source} = $source if !$count{source};
202
    if ($biblionumber && $source) {     # Now process any imagefiles
203
        my %filerrors;
204
        my $filename;
205
        if ($filetype eq 'image') {
206
            $filename = $uploadfilename;
207
        } else {
208
            $filename = $1 if ($source =~ /\/([^\/]+)$/);
209
        }
210
        $debug and warn "Source: $source";
211
        my $size = (stat($source))[7];
212
            if ($size > 550000) {    # This check is necessary even with image resizing to avoid possible security/performance issues...
213
                $filerrors{'OVRSIZ'} = 1;
214
                push my @filerrors, \%filerrors;
215
                push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, biblionumber => $biblionumber };
216
                $template->param( ERRORS => 1 );
217
                return %count;    # this one is fatal so bail here...
218
            }
219
        my ($srcimage, $image);
220
        if (open (IMG, "$source")) {
221
            $srcimage = GD::Image->new(*IMG);
222
            close (IMG);
223
			if (defined $srcimage) {
224
				my $mimetype = 'image/png';	# GD autodetects three basic image formats: PNG, JPEG, XPM; we will convert all to PNG which is lossless...
225
				# Check the pixel size of the image we are about to import...
226
				my ($width, $height) = $srcimage->getBounds();
227
				$debug and warn "$filename is $width pix X $height pix.";
228
				if ($width > 200 || $height > 300) {    # MAX pixel dims are 200 X 300...
229
					$debug and warn "$filename exceeds the maximum pixel dimensions of 200 X 300. Resizing...";
230
					my $percent_reduce;    # Percent we will reduce the image dimensions by...
231
					if ($width > 200) {
232
						$percent_reduce = sprintf("%.5f",(140/$width));    # If the width is oversize, scale based on width overage...
233
					} else {
234
						$percent_reduce = sprintf("%.5f",(200/$height));    # otherwise scale based on height overage.
235
					}
236
					my $width_reduce = sprintf("%.0f", ($width * $percent_reduce));
237
					my $height_reduce = sprintf("%.0f", ($height * $percent_reduce));
238
					$debug and warn "Reducing $filename by " . ($percent_reduce * 100) . "\% or to $width_reduce pix X $height_reduce pix";
239
					$image = GD::Image->new($width_reduce, $height_reduce, 1); #'1' creates true color image...
240
					$image->copyResampled($srcimage,0,0,0,0,$width_reduce,$height_reduce,$width,$height);
241
					$imgfile = $image->png();
242
					$debug and warn "$filename is " . length($imgfile) . " bytes after resizing.";
243
					undef $image;
244
					undef $srcimage;    # This object can get big...
245
				} else {
246
					$image = $srcimage;
247
					$imgfile = $image->png();
248
					$debug and warn "$filename is " . length($imgfile) . " bytes.";
249
					undef $image;
250
					undef $srcimage;    # This object can get big...
251
				}
252
				$debug and warn "Image is of mimetype $mimetype";
253
				my $dberror = PutCoverImage($biblionumber,$mimetype, $imgfile) if $mimetype;
254
				if ( !$dberror && $mimetype ) { # Errors from here on are fatal only to the import of a particular image, so don't bail, just note the error and keep going
255
					$count{count}++;
256
					push @{ $count{filenames} }, { source => $filename, biblionumber => $biblionumber };
257
				} elsif ( $dberror ) {
258
						warn "Database returned error: $dberror";
259
						($dberror =~ /coverimage_fk1/) ? $filerrors{'IMGEXISTS'} = 1 : $filerrors{'DBERR'} = 1;
260
						push my @filerrors, \%filerrors;
261
						push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, biblionumber => $biblionumber };
262
						$template->param( ERRORS => 1 );
263
				} elsif ( !$mimetype ) {
264
					warn "Unable to determine mime type of $filename. Please verify mimetype.";
265
					$filerrors{'MIMERR'} = 1;
266
					push my @filerrors, \%filerrors;
267
					push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, biblionumber => $biblionumber };
268
					$template->param( ERRORS => 1 );
269
				}
270
			} else {
271
				warn "Contents of $filename corrupted!";
272
			#	$count{count}--;
273
				$filerrors{'CORERR'} = 1;
274
				push my @filerrors, \%filerrors;
275
				push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, biblionumber => $biblionumber };
276
				$template->param( ERRORS => 1 );
277
			}
278
		} else {
279
			warn "Opening $dir/$filename failed!";
280
			$filerrors{'OPNERR'} = 1;
281
			push my @filerrors, \%filerrors;
282
			push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, biblionumber => $biblionumber };
283
			$template->param( ERRORS => 1 );
284
		}
285
    } else {    # The need for this seems a bit unlikely, however, to maximize error trapping it is included
286
        warn "Missing " . ($biblionumber ? "filename" : ($filename ? "biblionumber" : "biblionumber and filename"));
287
        $filerrors{'CRDFIL'} = ($biblionumber ? "filename" : ($filename ? "biblionumber" : "biblionumber and filename"));
288
        push my @filerrors, \%filerrors;
289
		push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, biblionumber => $biblionumber };
290
        $template->param( ERRORS => 1 );
291
    }
292
    return (%count);
293
}
294
=head2 PutCoverImage
295
296
    PutCoverImage($biblionumber, $mimetype, $imgfile);
297
298
Stores cover binary image data and mimetype in database.
299
NOTE: This function is good for updating images as well as inserting new images in the database.
300
301
=cut
302
303
sub PutCoverImage {
304
    my ($biblionumber, $mimetype, $imgfile) = @_;
305
    warn "Parameters passed in: Biblionumber=$biblionumber, Mimetype=$mimetype, " . ($imgfile ? "Imagefile" : "No Imagefile") if $debug;
306
    my $dbh = C4::Context->dbh;
307
    my $query = "INSERT INTO bibliocoverimage (biblionumber, mimetype, imagefile) VALUES (?,?,?) ON DUPLICATE KEY UPDATE imagefile = ?;";
308
    my $sth = $dbh->prepare($query);
309
    $sth->execute($biblionumber,$mimetype,$imgfile,$imgfile);
310
    warn "Error returned inserting $biblionumber.$mimetype." if $sth->errstr;
311
    return $sth->errstr;
312
}
313
314
=head2 RmCoverImage
315
316
    my ($dberror) = RmCoverImage($biblionumber);
317
318
Removes the image for the cover with the supplied biblionumber.
319
320
=cut
321
322
sub RmCoverImage {
323
    my ($biblionumber) = @_;
324
    warn "Biblionumber passed to RmBiblioImage is $biblionumber" if $debug;
325
    my $dbh = C4::Context->dbh;
326
    my $query = "DELETE FROM bibliocoverimage WHERE biblionumber = ?;";
327
    my $sth = $dbh->prepare($query);
328
    $sth->execute($biblionumber);
329
    my $dberror = $sth->errstr;
330
    warn "Database error!" if $sth->errstr;
331
    return $dberror;
332
}
333
334
=head1 AUTHORS
335
336
Copied from picture-upload.pl
337
338
Database storage, single coverimage upload option, and extensive error trapping contributed by Chris Nighswonger cnighswonger <at> foundations <dot> edu
339
Image scaling/resizing contributed by the same.
340
341
=cut

Return to bug 1633