3 # Copyright 2013 Rijksmuseum
5 # This file is part of Koha.
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
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.
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.
23 use constant KEYLENGTH => 10;
32 use C4::VirtualShelves;
34 #-------------------------------------------------------------------------------
37 my ($shelfname, $owner);
38 my ($template, $loggedinuser, $cookie);
40 my (@addr, $fail_addr, @newkey);
41 my @base64alphabet= ('A'..'Z', 'a'..'z', 0..9, '+', '/');
43 my $shelfnumber= $query->param('shelfnumber')||0;
44 my $op= $query->param('op')||'';
45 my $addrlist= $query->param('invite_address')||'';
46 my $key= $query->param('key')||'';
48 #-------------------------------------------------------------------------------
50 check_common_errors();
51 load_template("opac-shareshelf.tmpl");
55 elsif($op eq 'invite') {
58 elsif($op eq 'conf_invite') {
61 elsif($op eq 'accept') {
65 output_html_with_http_headers $query, $cookie, $template->output;
67 #-------------------------------------------------------------------------------
69 sub check_common_errors {
70 if($op!~/^(invite|conf_invite|accept)$/) {
71 $errcode=1; #no operation specified
74 if($shelfnumber!~/^\d+$/) {
75 $errcode=2; #invalid shelf number
78 if(!C4::Context->preference('OpacAllowSharingPrivateLists')) {
79 $errcode=3; #not or no longer allowed?
85 return unless check_owner_category();
89 return unless check_owner_category();
95 $errcode=6; #not one valid address
100 #TODO Add some code here to accept an invitation (followup report)
103 sub process_addrlist {
104 my @temp= split /[,:;]/, $addrlist;
106 foreach my $a (@temp) {
109 if(IsEmailAddress($a)) {
113 $fail_addr.= ($fail_addr? '; ': '').$a;
119 my $fromaddr= C4::Context->preference('KohaAdminEmailAddress');
120 my $url= 'http://'.C4::Context->preference('OPACBaseURL');
121 $url.= "/cgi-bin/koha/opac-shareshelf.pl?shelfnumber=$shelfnumber";
122 $url.= "&op=accept&key=";
123 #FIXME Waiting for the right http or https solution (BZ 8952 a.o.)
125 foreach my $a (@addr) {
126 @newkey=randomlist(KEYLENGTH, 64); #generate a new key
129 my $letter= C4::Letters::GetPreparedLetter(
131 letter_code => 'SHARE_INVITE',
132 branchcode => C4::Context->userenv->{"branch"},
133 tables => { borrowers => $loggedinuser, },
135 listname => $shelfname,
136 shareurl => $url.keytostring(\@newkey,0),
140 #send letter to queue
141 C4::Letters::EnqueueLetter( {
143 message_transport_type => 'email',
144 from_address => $fromaddr,
147 #add a preliminary share record
148 AddShare($shelfnumber,keytostring(\@newkey,1));
152 sub check_owner_category {
153 #FIXME candidate for a module? what held me back is: getting back the two different error codes and the shelfname
154 (undef,$shelfname,$owner,my $category)= GetShelf($shelfnumber);
155 $errcode=4 if $owner!= $loggedinuser; #should be owner
156 $errcode=5 if !$errcode && $category!=1; #should be private
162 ($template, $loggedinuser, $cookie)= get_template_and_user({
163 template_name => $file,
166 authnotrequired => 0, #should be a user
170 sub load_template_vars {
174 shelfnumber => $shelfnumber,
175 shelfname => $shelfname,
176 approvedaddress => (join '; ', @addr),
177 failaddress => $fail_addr,
182 #FIXME candidate for a module?
183 return Email::Valid->address($_[0])? 1: 0;
187 #uses rand, safe enough for this application but not for more sensitive data
188 my ($length, $base)= @_;
189 return map { int(rand($base)); } 1..$length;
193 my ($keyref, $flgBase64)= @_;
195 return join '', map { base64chr($_); } @$keyref;
197 return join '', map { sprintf("%02d",$_); } @$keyref;
201 my ($str, $flgBase64)= @_;
202 my @temp=split '', $str||'';
204 return map { base64ord($_); } @temp;
206 return () if $str!~/^\d+$/;
208 for(my $i=0; $i<@temp-1; $i+=2) {
209 push @retval, $temp[$i]*10+$temp[$i+1];
214 sub base64ord { #base64 ordinal
216 return 0 -ord('A')+ord($char) if $char=~/[A-Z]/;
217 return 26-ord('a')+ord($char) if $char=~/[a-z]/;
218 return 52-ord('0')+ord($char) if $char=~/[0-9]/;
219 return 62 if $char eq '+';
220 return 63 if $char eq '/';
224 sub base64chr { #reverse operation for ord
225 return $_[0]=~/^\d+$/ && $_[0]<64? $base64alphabet[$_[0]]: undef;