3 # Copyright 2013 Rijksmuseum
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
22 use constant KEYLENGTH
=> 10;
23 use constant TEMPLATE_NAME
=> 'opac-shareshelf.tt';
24 use constant SHELVES_URL
=>
25 '/cgi-bin/koha/opac-shelves.pl?display=privateshelves&viewshelf=';
35 use C4
::VirtualShelves
;
37 #-------------------------------------------------------------------------------
39 my $pvar = _init
( {} );
40 if ( !$pvar->{errcode
} ) {
41 show_invite
($pvar) if $pvar->{op
} eq 'invite';
42 confirm_invite
($pvar) if $pvar->{op
} eq 'conf_invite';
43 show_accept
($pvar) if $pvar->{op
} eq 'accept';
45 load_template_vars
($pvar);
46 output_html_with_http_headers
$pvar->{query
}, $pvar->{cookie
},
47 $pvar->{template
}->output;
49 #-------------------------------------------------------------------------------
54 $param->{query
} = $query;
55 $param->{shelfnumber
} = $query->param('shelfnumber') || 0;
56 $param->{op
} = $query->param('op') || '';
57 $param->{addrlist
} = $query->param('invite_address') || '';
58 $param->{key
} = $query->param('key') || '';
59 $param->{appr_addr
} = [];
60 $param->{fail_addr
} = [];
61 $param->{errcode
} = check_common_errors
($param);
63 #get some list details
65 @temp = GetShelf
( $param->{shelfnumber
} ) if !$param->{errcode
};
66 $param->{shelfname
} = @temp ?
$temp[1] : '';
67 $param->{owner
} = @temp ?
$temp[2] : -1;
68 $param->{category
} = @temp ?
$temp[3] : -1;
70 load_template
($param);
74 sub check_common_errors
{
76 if ( $param->{op
} !~ /^(invite|conf_invite|accept)$/ ) {
77 return 1; #no operation specified
79 if ( $param->{shelfnumber
} !~ /^\d+$/ ) {
80 return 2; #invalid shelf number
82 if ( !C4
::Context
->preference('OpacAllowSharingPrivateLists') ) {
83 return 3; #not or no longer allowed?
90 return unless check_owner_category
($param);
95 return unless check_owner_category
($param);
96 process_addrlist
($param);
97 if ( @
{ $param->{appr_addr
} } ) {
98 send_invitekey
($param);
101 $param->{errcode
} = 6; #not one valid address
108 my @rv = ShelfPossibleAction
( $param->{loggedinuser
},
109 $param->{shelfnumber
}, 'acceptshare' );
110 $param->{errcode
} = $rv[1] if !$rv[0];
111 return if $param->{errcode
};
113 #errorcode 5: should be private list
114 #errorcode 8: should not be owner
116 my $dbkey = keytostring
( stringtokey
( $param->{key
}, 0 ), 1 );
117 if ( AcceptShare
( $param->{shelfnumber
}, $dbkey, $param->{loggedinuser
} ) )
119 notify_owner
($param);
121 #redirect to view of this shared list
122 print $param->{query
}->redirect(
123 -uri
=> SHELVES_URL
. $param->{shelfnumber
},
124 -cookie
=> $param->{cookie
}
129 $param->{errcode
} = 7; #not accepted (key not found or expired)
136 my $toaddr = C4
::Members
::GetNoticeEmailAddress
( $param->{owner
} );
140 my $letter = C4
::Letters
::GetPreparedLetter
(
142 letter_code
=> 'SHARE_ACCEPT',
143 branchcode
=> C4
::Context
->userenv->{"branch"},
144 tables
=> { borrowers
=> $param->{loggedinuser
}, },
145 substitute
=> { listname
=> $param->{shelfname
}, },
148 #send letter to queue
149 C4
::Letters
::EnqueueLetter
(
152 message_transport_type
=> 'email',
153 from_address
=> C4
::Context
->preference('KohaAdminEmailAddress'),
154 to_address
=> $toaddr,
159 sub process_addrlist
{
161 my @temp = split /[,:;]/, $param->{addrlist
};
164 foreach my $a (@temp) {
167 if ( IsEmailAddress
($a) ) {
174 $param->{appr_addr
} = \
@appr_addr;
175 $param->{fail_addr
} = \
@fail_addr;
180 my $fromaddr = C4
::Context
->preference('KohaAdminEmailAddress');
183 . C4
::Context
->preference('OPACBaseURL')
184 . "/cgi-bin/koha/opac-shareshelf.pl?shelfnumber="
185 . $param->{shelfnumber
}
188 #TODO Waiting for the right http or https solution (BZ 8952 a.o.)
190 my @ok; #the addresses that were processed well
191 foreach my $a ( @
{ $param->{appr_addr
} } ) {
192 my @newkey = randomlist
( KEYLENGTH
, 64 ); #generate a new key
194 #add a preliminary share record
195 if ( !AddShare
( $param->{shelfnumber
}, keytostring
( \
@newkey, 1 ) ) ) {
196 push @
{ $param->{fail_addr
} }, $a;
202 my $letter = C4
::Letters
::GetPreparedLetter
(
204 letter_code
=> 'SHARE_INVITE',
205 branchcode
=> C4
::Context
->userenv->{"branch"},
206 tables
=> { borrowers
=> $param->{loggedinuser
}, },
208 listname
=> $param->{shelfname
},
209 shareurl
=> $url . keytostring
( \
@newkey, 0 ),
213 #send letter to queue
214 C4
::Letters
::EnqueueLetter
(
217 message_transport_type
=> 'email',
218 from_address
=> $fromaddr,
223 $param->{appr_addr
} = \
@ok;
226 sub check_owner_category
{
229 #sharing user should be the owner
230 #list should be private
231 $param->{errcode
} = 4 if $param->{owner
} != $param->{loggedinuser
};
232 $param->{errcode
} = 5 if !$param->{errcode
} && $param->{category
} != 1;
233 return !defined $param->{errcode
};
238 ( $param->{template
}, $param->{loggedinuser
}, $param->{cookie
} ) =
239 get_template_and_user
(
241 template_name
=> TEMPLATE_NAME
,
242 query
=> $param->{query
},
244 authnotrequired
=> 0, #should be a user
249 sub load_template_vars
{
251 my $template = $param->{template
};
252 my $appr = join '; ', @
{ $param->{appr_addr
} };
253 my $fail = join '; ', @
{ $param->{fail_addr
} };
255 errcode
=> $param->{errcode
},
257 shelfnumber
=> $param->{shelfnumber
},
258 shelfname
=> $param->{shelfname
},
259 approvedaddress
=> $appr,
260 failaddress
=> $fail,
266 #TODO candidate for a module?
267 return Email
::Valid
->address( $_[0] ) ?
1 : 0;
272 #uses rand, safe enough for this application but not for more sensitive data
273 my ( $length, $base ) = @_;
274 return map { int( rand($base) ); } 1 .. $length;
278 my ( $keyref, $flgBase64 ) = @_;
280 my $alphabet = [ 'A' .. 'Z', 'a' .. 'z', 0 .. 9, '+', '/' ];
281 return join '', map { alphabet_char
( $_, $alphabet ); } @
$keyref;
283 return join '', map { sprintf( "%02d", $_ ); } @
$keyref;
287 my ( $str, $flgBase64 ) = @_;
288 my @temp = split '', $str || '';
290 my $alphabet = [ 'A' .. 'Z', 'a' .. 'z', 0 .. 9, '+', '/' ];
291 return [ map { alphabet_ordinal
( $_, $alphabet ); } @temp ];
293 return [] if $str !~ /^\d+$/;
295 for ( my $i = 0 ; $i < @temp - 1 ; $i += 2 ) {
296 push @retval, $temp[$i] * 10 + $temp[ $i + 1 ];
301 sub alphabet_ordinal
{
302 my ( $char, $alphabet ) = @_;
303 for my $ord ( 0 .. $#$alphabet ) {
304 return $ord if $char eq $alphabet->[$ord];
306 return ''; #ignore missing chars
311 #reverse operation for ordinal; ignore invalid numbers
312 my ( $num, $alphabet ) = @_;
313 return $num =~ /^\d+$/ && $num <= $#$alphabet ? $alphabet->[$num] : '';