Revert "Commenting out some noisy warns"
[koha_fer] / C4 / Auth.pm
1 # -*- tab-width: 8 -*-
2 # NOTE: This file uses 8-character tabs; do not change the tab size!
3
4 package C4::Auth;
5
6 # Copyright 2000-2002 Katipo Communications
7 #
8 # This file is part of Koha.
9 #
10 # Koha is free software; you can redistribute it and/or modify it under the
11 # terms of the GNU General Public License as published by the Free Software
12 # Foundation; either version 2 of the License, or (at your option) any later
13 # version.
14 #
15 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
16 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License along with
20 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
21 # Suite 330, Boston, MA  02111-1307 USA
22
23 use strict;
24 use Digest::MD5 qw(md5_base64);
25 use CGI::Session;
26
27
28 require Exporter;
29 use C4::Context;
30 use C4::Output;    # to get the template
31 use C4::Members;
32 use C4::Koha;
33 use C4::Branch; # GetBranches
34
35 # use utf8;
36 # use Net::LDAP;
37 # use Net::LDAP qw(:all);
38
39 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
40
41 # set the version for version checking
42 $VERSION = 3.00;
43
44 =head1 NAME
45
46 C4::Auth - Authenticates Koha users
47
48 =head1 SYNOPSIS
49
50   use CGI;
51   use C4::Auth;
52
53   my $query = new CGI;
54
55   my ($template, $borrowernumber, $cookie) 
56     = get_template_and_user(
57         {
58             template_name   => "opac-main.tmpl",
59             query           => $query,
60       type            => "opac",
61       authnotrequired => 1,
62       flagsrequired   => {borrow => 1},
63   }
64     );
65
66   print $query->header(
67     -type => 'utf-8',
68     -cookie => $cookie
69   ), $template->output;
70
71
72 =head1 DESCRIPTION
73
74     The main function of this module is to provide
75     authentification. However the get_template_and_user function has
76     been provided so that a users login information is passed along
77     automatically. This gets loaded into the template.
78
79 =head1 FUNCTIONS
80
81 =over 2
82
83 =cut
84
85 @ISA    = qw(Exporter);
86 @EXPORT = qw(
87   &checkauth
88   &get_template_and_user
89 );
90
91 =item get_template_and_user
92
93   my ($template, $borrowernumber, $cookie)
94     = get_template_and_user(
95         {
96            template_name   => "opac-main.tmpl",
97            query           => $query,
98      type            => "opac",
99      authnotrequired => 1,
100      flagsrequired   => {borrow => 1},
101   }
102     );
103
104     This call passes the C<query>, C<flagsrequired> and C<authnotrequired>
105     to C<&checkauth> (in this module) to perform authentification.
106     See C<&checkauth> for an explanation of these parameters.
107
108     The C<template_name> is then used to find the correct template for
109     the page. The authenticated users details are loaded onto the
110     template in the HTML::Template LOOP variable C<USER_INFO>. Also the
111     C<sessionID> is passed to the template. This can be used in templates
112     if cookies are disabled. It needs to be put as and input to every
113     authenticated page.
114
115     More information on the C<gettemplate> sub can be found in the
116     Output.pm module.
117
118 =cut
119
120 sub get_template_and_user {
121     my $in       = shift;
122     my $template =
123       gettemplate( $in->{'template_name'}, $in->{'type'}, $in->{'query'} );
124     my ( $user, $cookie, $sessionID, $flags ) = checkauth(
125         $in->{'query'},
126         $in->{'authnotrequired'},
127         $in->{'flagsrequired'},
128         $in->{'type'}
129     ) unless ($in->{'template_name'}=~/maintenance/);
130
131     my $borrowernumber;
132     my $insecure = C4::Context->preference('insecure');
133     if ($user or $insecure) {
134
135                 # load the template variables for stylesheets and JavaScript
136                 $template->param( css_libs => $in->{'css_libs'} );
137                 $template->param( css_module => $in->{'css_module'} );
138                 $template->param( css_page => $in->{'css_page'} );
139                 $template->param( css_widgets => $in->{'css_widgets'} );
140
141         $template->param( js_libs => $in->{'js_libs'} );
142         $template->param( js_module => $in->{'js_module'} );
143         $template->param( js_page => $in->{'js_page'} );
144         $template->param( js_widgets => $in->{'js_widgets'} );
145
146                 # user info
147         $template->param( loggedinusername => $user );
148         $template->param( sessionID        => $sessionID );
149
150         $borrowernumber = getborrowernumber($user);
151         my ( $borr, $alternativeflags ) =
152           GetMemberDetails( $borrowernumber );
153         my @bordat;
154         $bordat[0] = $borr;
155         $template->param( "USER_INFO" => \@bordat );
156
157         # We are going to use the $flags returned by checkauth
158         # to create the template's parameters that will indicate
159         # which menus the user can access.
160         if (( $flags && $flags->{superlibrarian}==1) or $insecure==1) {
161             $template->param( CAN_user_circulate        => 1 );
162             $template->param( CAN_user_catalogue        => 1 );
163             $template->param( CAN_user_parameters       => 1 );
164             $template->param( CAN_user_borrowers        => 1 );
165             $template->param( CAN_user_permission       => 1 );
166             $template->param( CAN_user_reserveforothers => 1 );
167             $template->param( CAN_user_borrow           => 1 );
168             $template->param( CAN_user_editcatalogue    => 1 );
169             $template->param( CAN_user_updatecharge     => 1 );
170             $template->param( CAN_user_acquisition      => 1 );
171             $template->param( CAN_user_management       => 1 );
172             $template->param( CAN_user_tools            => 1 ); 
173             $template->param( CAN_user_editauthorities  => 1 );
174             $template->param( CAN_user_serials          => 1 );
175             $template->param( CAN_user_reports          => 1 );
176         }
177
178         if ( $flags && $flags->{circulate} == 1 ) {
179             $template->param( CAN_user_circulate => 1 );
180         }
181
182         if ( $flags && $flags->{catalogue} == 1 ) {
183             $template->param( CAN_user_catalogue => 1 );
184         }
185
186         if ( $flags && $flags->{parameters} == 1 ) {
187             $template->param( CAN_user_parameters => 1 );
188             $template->param( CAN_user_management => 1 );
189         }
190
191         if ( $flags && $flags->{borrowers} == 1 ) {
192             $template->param( CAN_user_borrowers => 1 );
193         }
194
195         if ( $flags && $flags->{permissions} == 1 ) {
196             $template->param( CAN_user_permission => 1 );
197         }
198
199         if ( $flags && $flags->{reserveforothers} == 1 ) {
200             $template->param( CAN_user_reserveforothers => 1 );
201         }
202
203         if ( $flags && $flags->{borrow} == 1 ) {
204             $template->param( CAN_user_borrow => 1 );
205         }
206
207         if ( $flags && $flags->{editcatalogue} == 1 ) {
208             $template->param( CAN_user_editcatalogue => 1 );
209         }
210
211         if ( $flags && $flags->{updatecharges} == 1 ) {
212             $template->param( CAN_user_updatecharge => 1 );
213         }
214
215         if ( $flags && $flags->{acquisition} == 1 ) {
216             $template->param( CAN_user_acquisition => 1 );
217         }
218
219         if ( $flags && $flags->{tools} == 1 ) {
220             $template->param( CAN_user_tools => 1 );
221         }
222   
223         if ( $flags && $flags->{editauthorities} == 1 ) {
224             $template->param( CAN_user_editauthorities => 1 );
225         }
226     
227         if ( $flags && $flags->{serials} == 1 ) {
228             $template->param( CAN_user_serials => 1 );
229         }
230
231         if ( $flags && $flags->{reports} == 1 ) {
232             $template->param( CAN_user_reports => 1 );
233         }
234     }
235     if ( $in->{'type'} eq "intranet" ) {
236         $template->param(
237             intranetcolorstylesheet => C4::Context->preference("intranetcolorstylesheet"),
238             intranetstylesheet => C4::Context->preference("intranetstylesheet"),
239             IntranetNav        => C4::Context->preference("IntranetNav"),
240             intranetuserjs     => C4::Context->preference("intranetuserjs"),
241             TemplateEncoding   => C4::Context->preference("TemplateEncoding"),
242             AmazonContent      => C4::Context->preference("AmazonContent"),
243             LibraryName        => C4::Context->preference("LibraryName"),
244             LoginBranchcode    => (C4::Context->userenv?C4::Context->userenv->{"branch"}:"insecure"),
245             LoginBranchname    => (C4::Context->userenv?C4::Context->userenv->{"branchname"}:"insecure"),
246             LoginFirstname     => (C4::Context->userenv?C4::Context->userenv->{"firstname"}:"Bel"),
247             LoginSurname       => C4::Context->userenv?C4::Context->userenv->{"surname"}:"Inconnu", 
248             AutoLocation       => C4::Context->preference("AutoLocation"),
249             hide_marc          => C4::Context->preference("hide_marc"),
250             patronimages       => C4::Context->preference("patronimages"),
251             "BiblioDefaultView".C4::Context->preference("IntranetBiblioDefaultView") => 1,
252             advancedMARCEditor      => C4::Context->preference("advancedMARCEditor"),
253             suggestion              => C4::Context->preference("suggestion"),
254             virtualshelves          => C4::Context->preference("virtualshelves"),
255             LibraryName             => C4::Context->preference("LibraryName"),
256             KohaAdminEmailAddress   => "" . C4::Context->preference("KohaAdminEmailAddress"),
257             IntranetmainUserblock       => C4::Context->preference("IntranetmainUserblock"),
258             IndependantBranches     => C4::Context->preference("IndependantBranches"),
259         );
260     }
261     else {
262         warn "template type should be OPAC, here it is=[" . $in->{'type'} . "]" unless ( $in->{'type'} eq 'opac' );
263         my $LibraryNameTitle = C4::Context->preference("LibraryName");
264         $LibraryNameTitle =~ s/<(?:\/?)(?:br|p)\s*(?:\/?)>/ /sgi;
265         $LibraryNameTitle =~ s/<(?:[^<>'"]|'(?:[^']*)'|"(?:[^"]*)")*>//sg;
266   $template->param(
267             KohaAdminEmailAddress  => "" . C4::Context->preference("KohaAdminEmailAddress"),
268             suggestion             => "" . C4::Context->preference("suggestion"),
269             virtualshelves         => "" . C4::Context->preference("virtualshelves"),
270             OpacNav                => "" . C4::Context->preference("OpacNav"),
271             opacheader             => "" . C4::Context->preference("opacheader"),
272             opaccredits            => "" . C4::Context->preference("opaccredits"),
273             opacsmallimage         => "" . C4::Context->preference("opacsmallimage"),
274             opaclargeimage         => "" . C4::Context->preference("opaclargeimage"),
275             opaclayoutstylesheet   => "". C4::Context->preference("opaclayoutstylesheet"),
276             opaccolorstylesheet    => "". C4::Context->preference("opaccolorstylesheet"),
277             opaclanguagesdisplay   => "". C4::Context->preference("opaclanguagesdisplay"),
278             opacuserlogin          => "" . C4::Context->preference("opacuserlogin"),
279             opacbookbag            => "" . C4::Context->preference("opacbookbag"),
280             TemplateEncoding       => "". C4::Context->preference("TemplateEncoding"),
281             AmazonContent          => "" . C4::Context->preference("AmazonContent"),
282             LibraryName            => "" . C4::Context->preference("LibraryName"),
283             LibraryNameTitle       => "" . $LibraryNameTitle,
284             LoginBranchcode        => (C4::Context->userenv?C4::Context->userenv->{"branch"}:"insecure"),
285             LoginBranchname        => C4::Context->userenv?C4::Context->userenv->{"branchname"}:"", 
286             LoginFirstname        => (C4::Context->userenv?C4::Context->userenv->{"firstname"}:"Bel"),
287             LoginSurname        => C4::Context->userenv?C4::Context->userenv->{"surname"}:"Inconnu", 
288             OpacPasswordChange     => C4::Context->preference("OpacPasswordChange"),
289             opacreadinghistory     => C4::Context->preference("opacreadinghistory"),
290             opacuserjs             => C4::Context->preference("opacuserjs"),
291             OpacCloud              => C4::Context->preference("OpacCloud"),
292             OpacTopissue           => C4::Context->preference("OpacTopissue"),
293             OpacAuthorities        => C4::Context->preference("OpacAuthorities"),
294             OpacBrowser            => C4::Context->preference("OpacBrowser"),
295             RequestOnOpac          => C4::Context->preference("RequestOnOpac"),
296             reviewson              => C4::Context->preference("reviewson"),
297             hide_marc              => C4::Context->preference("hide_marc"),
298             patronimages           => C4::Context->preference("patronimages"),
299             mylibraryfirst   => C4::Context->preference("SearchMyLibraryFirst"),
300             "BiblioDefaultView".C4::Context->preference("BiblioDefaultView") => 1,
301         );
302     }
303     return ( $template, $borrowernumber, $cookie );
304 }
305
306 =item checkauth
307
308   ($userid, $cookie, $sessionID) = &checkauth($query, $noauth, $flagsrequired, $type);
309
310 Verifies that the user is authorized to run this script.  If
311 the user is authorized, a (userid, cookie, session-id, flags)
312 quadruple is returned.  If the user is not authorized but does
313 not have the required privilege (see $flagsrequired below), it
314 displays an error page and exits.  Otherwise, it displays the
315 login page and exits.
316
317 Note that C<&checkauth> will return if and only if the user
318 is authorized, so it should be called early on, before any
319 unfinished operations (e.g., if you've opened a file, then
320 C<&checkauth> won't close it for you).
321
322 C<$query> is the CGI object for the script calling C<&checkauth>.
323
324 The C<$noauth> argument is optional. If it is set, then no
325 authorization is required for the script.
326
327 C<&checkauth> fetches user and session information from C<$query> and
328 ensures that the user is authorized to run scripts that require
329 authorization.
330
331 The C<$flagsrequired> argument specifies the required privileges
332 the user must have if the username and password are correct.
333 It should be specified as a reference-to-hash; keys in the hash
334 should be the "flags" for the user, as specified in the Members
335 intranet module. Any key specified must correspond to a "flag"
336 in the userflags table. E.g., { circulate => 1 } would specify
337 that the user must have the "circulate" privilege in order to
338 proceed. To make sure that access control is correct, the
339 C<$flagsrequired> parameter must be specified correctly.
340
341 The C<$type> argument specifies whether the template should be
342 retrieved from the opac or intranet directory tree.  "opac" is
343 assumed if it is not specified; however, if C<$type> is specified,
344 "intranet" is assumed if it is not "opac".
345
346 If C<$query> does not have a valid session ID associated with it
347 (i.e., the user has not logged in) or if the session has expired,
348 C<&checkauth> presents the user with a login page (from the point of
349 view of the original script, C<&checkauth> does not return). Once the
350 user has authenticated, C<&checkauth> restarts the original script
351 (this time, C<&checkauth> returns).
352
353 The login page is provided using a HTML::Template, which is set in the
354 systempreferences table or at the top of this file. The variable C<$type>
355 selects which template to use, either the opac or the intranet 
356 authentification template.
357
358 C<&checkauth> returns a user ID, a cookie, and a session ID. The
359 cookie should be sent back to the browser; it verifies that the user
360 has authenticated.
361
362 =cut
363
364 sub checkauth {
365     my $query = shift;
366   # warn "Checking Auth";
367     # $authnotrequired will be set for scripts which will run without authentication
368     my $authnotrequired = shift;
369     my $flagsrequired   = shift;
370     my $type            = shift;
371     $type = 'opac' unless $type;
372
373     my $dbh     = C4::Context->dbh;
374     my $timeout = C4::Context->preference('timeout');
375     $timeout = 600 unless $timeout;
376
377
378     # If Version syspref is unavailable, it means Koha is beeing installed,
379     # and so we must redirect to OPAC maintenance page or to the WebInstaller
380     warn "about to check version";
381     unless (C4::Context->preference('Version')) {
382       if ($type ne 'opac') {
383         warn "Install required, redirecting to Installer";
384         print $query->redirect("/cgi-bin/koha/installer/install.pl");
385       } 
386       else {
387         warn "OPAC Install required, redirecting to maintenance";
388         print $query->redirect("/cgi-bin/koha/maintenance.pl");
389       }
390       exit;
391     }
392
393
394     # state variables
395     my $loggedin = 0;
396     my %info;
397     my ( $userid, $cookie, $sessionID, $flags );
398     my $logout = $query->param('logout.x');
399     if ( $userid = $ENV{'REMOTE_USER'} ) {
400         # Using Basic Authentication, no cookies required
401         $cookie = $query->cookie(
402             -name    => 'CGISESSID',
403             -value   => '',
404             -expires => ''
405         );
406         $loggedin = 1;
407     }
408     elsif ( $sessionID = $query->cookie("CGISESSID")) {
409 <<<<<<< HEAD:C4/Auth.pm
410                 my $storage_method = C4::Context->preference('SessionStorage');
411                 my $session;
412                 if ($storage_method eq 'mysql'){
413                     $session = new CGI::Session("driver:MySQL", $sessionID, {Handle=>$dbh});
414                 }
415                 else {
416                         # catch all defaults to tmp should work on all systems
417                         $session = new CGI::Session("driver:File", $sessionID, {Directory=>'/tmp'});                    
418                 }
419 =======
420 #         my $session = new CGI::Session("driver:MySQL", $sessionID, {Handle=>$dbh});
421         my $session = new CGI::Session("driver:File", $sessionID, {Directory=>'/tmp'});
422 >>>>>>> Commenting out some noisy warns:C4/Auth.pm
423         C4::Context->_new_userenv($sessionID);
424         if ($session){
425             C4::Context::set_userenv(
426                 $session->param('number'),       $session->param('id'),
427                 $session->param('cardnumber'),   $session->param('firstname'),
428                 $session->param('surname'),      $session->param('branch'),
429                 $session->param('branchname'),   $session->param('flags'),
430                 $session->param('emailaddress'), $session->param('branchprinter')
431             );
432 #             warn       "".$session->param('cardnumber').",   ".$session->param('firstname').",
433 #                 ".$session->param('surname').",      ".$session->param('branch');
434         }
435         my $ip;
436         my $lasttime;
437         if ($session) {
438           $ip = $session->param('ip');
439           $lasttime = $session->param('lasttime');
440                 $userid = $session->param('id');
441         }
442         
443     
444         if ($logout) {
445
446             # voluntary logout the user
447
448             $session->flush;      
449                         $session->delete();
450             C4::Context->_unset_userenv($sessionID);
451             $sessionID = undef;
452             $userid    = undef;
453             open L, ">>/tmp/sessionlog";
454             my $time = localtime( time() );
455             printf L "%20s from %16s logged out at %30s (manually).\n", $userid,
456               $ip, $time;
457             close L;
458         }
459         if ($userid) {
460             if ( $lasttime < time() - $timeout ) {
461                 # timed logout
462                 $info{'timed_out'} = 1;
463                 $session->delete();
464                 C4::Context->_unset_userenv($sessionID);
465                 $userid    = undef;
466                 $sessionID = undef;
467                 open L, ">>/tmp/sessionlog";
468                 my $time = localtime( time() );
469                 printf L "%20s from %16s logged out at %30s (inactivity).\n",
470                   $userid, $ip, $time;
471                 close L;
472             }
473             elsif ( $ip ne $ENV{'REMOTE_ADDR'} ) {
474                 # Different ip than originally logged in from
475                 $info{'oldip'}        = $ip;
476                 $info{'newip'}        = $ENV{'REMOTE_ADDR'};
477                 $info{'different_ip'} = 1;
478         $session->delete();
479                 C4::Context->_unset_userenv($sessionID);
480                 $sessionID = undef;
481                 $userid    = undef;
482                 open L, ">>/tmp/sessionlog";
483                 my $time = localtime( time() );
484                 printf L
485 "%20s from logged out at %30s (ip changed from %16s to %16s).\n",
486                   $userid, $time, $ip, $info{'newip'};
487                 close L;
488             }
489             else {
490                 $cookie = $query->cookie( CGISESSID => $session->id );
491                 $session->param('lasttime',time());
492                 $flags = haspermission( $dbh, $userid, $flagsrequired );
493                 if ($flags) {
494                     $loggedin = 1;
495                 }
496                 else {
497                     $info{'nopermission'} = 1;
498                 }
499             }
500         }
501     }
502     unless ($userid) {
503                 my $storage_method = C4::Context->preference('SessionStorage');
504                 my $session;
505                 if ($storage_method eq 'mysql'){
506                     $session = new CGI::Session("driver:MySQL", $sessionID, {Handle=>$dbh});
507                 }
508                 else {
509                         # catch all defaults to tmp should work on all systems
510                         $session = new CGI::Session("driver:File", $sessionID, {Directory=>'/tmp'});                    
511                 }
512
513         my $sessionID;
514                 if ($session) {
515                         $sessionID = $session->id;
516                 }
517         $userid    = $query->param('userid');
518         C4::Context->_new_userenv($sessionID);
519         my $password = $query->param('password');
520         C4::Context->_new_userenv($sessionID);
521         my ( $return, $cardnumber ) = checkpw( $dbh, $userid, $password );
522         if ($return) {
523             open L, ">>/tmp/sessionlog";
524             my $time = localtime( time() );
525             printf L "%20s from %16s logged in  at %30s.\n", $userid,
526               $ENV{'REMOTE_ADDR'}, $time;
527             close L;
528             $cookie = $query->cookie(CGISESSID => $sessionID);
529             if ( $flags = haspermission( $dbh, $userid, $flagsrequired ) ) {
530                 $loggedin = 1;
531             }
532             else {
533                 $info{'nopermission'} = 1;
534                 C4::Context->_unset_userenv($sessionID);
535             }
536             if ( $return == 1 ) {
537                 my (
538                     $borrowernumber, $firstname,  $surname,
539                     $userflags,      $branchcode, $branchname,
540                     $branchprinter,  $emailaddress
541                 );
542                 my $sth =
543                   $dbh->prepare(
544 "select borrowernumber, firstname, surname, flags, borrowers.branchcode, branches.branchname as branchname,branches.branchprinter as branchprinter, email from borrowers left join branches on borrowers.branchcode=branches.branchcode where userid=?"
545                   );
546                 $sth->execute($userid);
547                 (
548                     $borrowernumber, $firstname,  $surname,
549                     $userflags,      $branchcode, $branchname,
550                     $branchprinter,  $emailaddress
551                   )
552                   = $sth->fetchrow
553                   if ( $sth->rows );
554
555 #         warn "$cardnumber,$borrowernumber,$userid,$firstname,$surname,$userflags,$branchcode,$emailaddress";
556                 unless ( $sth->rows ) {
557                     my $sth =
558                       $dbh->prepare(
559 "select borrowernumber, firstname, surname, flags, borrowers.branchcode, branches.branchname as branchname, branches.branchprinter as branchprinter, email from borrowers left join branches on borrowers.branchcode=branches.branchcode where cardnumber=?"
560                       );
561                     $sth->execute($cardnumber);
562                     (
563                         $borrowernumber, $firstname,  $surname,
564                         $userflags,      $branchcode, $branchname,
565                         $branchprinter,  $emailaddress
566                       )
567                       = $sth->fetchrow
568                       if ( $sth->rows );
569
570 #           warn "$cardnumber,$borrowernumber,$userid,$firstname,$surname,$userflags,$branchcode,$emailaddress";
571                     unless ( $sth->rows ) {
572                         $sth->execute($userid);
573                         (
574                             $borrowernumber, $firstname, $surname, $userflags,
575                             $branchcode, $branchname, $branchprinter, $emailaddress
576                           )
577                           = $sth->fetchrow
578                           if ( $sth->rows );
579                     }
580                 }
581
582 # launch a sequence to check if we have a ip for the branch, if we have one we replace the branchcode of the userenv by the branch bound in the ip.
583                 my $ip       = $ENV{'REMOTE_ADDR'};
584                 # if they specify at login, use that
585                 if ($query->param('branch')) {
586                     $branchcode  = $query->param('branch');
587                     $branchname = GetBranchName($branchcode);
588                 }
589                 my $branches = GetBranches();
590                 my @branchesloop;
591                 foreach my $br ( keys %$branches ) {
592                     #     now we work with the treatment of ip
593                     my $domain = $branches->{$br}->{'branchip'};
594                     if ( $domain && $ip =~ /^$domain/ ) {
595                         $branchcode = $branches->{$br}->{'branchcode'};
596
597                         # new op dev : add the branchprinter and branchname in the cookie
598                         $branchprinter = $branches->{$br}->{'branchprinter'};
599                         $branchname    = $branches->{$br}->{'branchname'};
600                     }
601                 }
602                 $session->param('number',$borrowernumber);
603                 $session->param('id',$userid);
604                 $session->param('cardnumber',$cardnumber);
605                 $session->param('firstname',$firstname);
606                 $session->param('surname',$surname);
607                 $session->param('branch',$branchcode);
608                 $session->param('branchname',$branchname);
609                 $session->param('flags',$userflags);
610                 $session->param('emailaddress',$emailaddress);
611                 $session->param('ip',$session->remote_addr());
612                 $session->param('lasttime',time());
613 #            warn       "".$session->param('cardnumber').",   ".$session->param('firstname').",
614 #                 ".$session->param('surname').",      ".$session->param('branch');
615             }
616             elsif ( $return == 2 ) {
617                 #We suppose the user is the superlibrarian
618                         $session->param('number',0);
619                         $session->param('id',C4::Context->config('user'));
620                         $session->param('cardnumber',C4::Context->config('user'));
621                         $session->param('firstname',C4::Context->config('user'));
622                         $session->param('surname',C4::Context->config('user'));
623                         $session->param('branch','NO_LIBRARY_SET');
624                         $session->param('branchname','NO_LIBRARY_SET');
625                         $session->param('flags',1);
626                         $session->param('emailaddress', C4::Context->preference('KohaAdminEmailAddress'));
627                         $session->param('ip',$session->remote_addr());
628                         $session->param('lasttime',time());
629                 }
630                 if ($session){
631                     C4::Context::set_userenv(
632                         $session->param('number'),       $session->param('id'),
633                         $session->param('cardnumber'),   $session->param('firstname'),
634                         $session->param('surname'),      $session->param('branch'),
635                         $session->param('branchname'),   $session->param('flags'),
636                         $session->param('emailaddress'), $session->param('branchprinter')
637                     );
638                 }
639         }
640
641         else {
642             if ($userid) {
643                 $info{'invalid_username_or_password'} = 1;
644                 C4::Context->_unset_userenv($sessionID);
645             }
646         }
647     }
648     my $insecure = C4::Context->boolean_preference('insecure');
649
650     # finished authentification, now respond
651     if ( $loggedin || $authnotrequired || ( defined($insecure) && $insecure ) )
652     {
653         # successful login
654         unless ($cookie) {
655             $cookie = $query->cookie( CGISESSID => ''
656             );
657         }
658     return ( $userid, $cookie, $sessionID, $flags );
659
660     }
661
662 #
663 #
664 # AUTH rejected, show the login/password template, after checking the DB.
665 #
666 #
667     
668     # get the inputs from the incoming query
669     my @inputs = ();
670     foreach my $name ( param $query) {
671         (next) if ( $name eq 'userid' || $name eq 'password' );
672         my $value = $query->param($name);
673         push @inputs, { name => $name, value => $value };
674     }
675     # get the branchloop, which we need for authentication
676     my $branches = GetBranches();
677     my @branch_loop;
678     for my $branch_hash (keys %$branches) {
679                 push @branch_loop, {branchcode => "$branch_hash", branchname => $branches->{$branch_hash}->{'branchname'}, };
680     }
681
682     # check that database and koha version are the same
683     # there is no DB version, it's a fresh install,
684     # go to web installer
685     # there is a DB version, compare it to the code version
686     my $kohaversion=C4::Context::KOHAVERSION;
687     # remove the 3 last . to have a Perl number
688     $kohaversion =~ s/(.*\..*)\.(.*)\.(.*)/$1$2$3/;
689 #     warn "kohaversion : $kohaversion";
690     if (C4::Context->preference('Version') < $kohaversion){
691       if ($type ne 'opac'){
692       warn "Database update needed, redirecting to Installer. Database is ".C4::Context->preference('Version')." and Koha is : ".C4::Context->config("kohaversion");
693         print $query->redirect("/cgi-bin/koha/installer/install.pl?step=3");
694       } else {
695       warn "OPAC :Database update needed, redirecting to maintenance. Database is ".C4::Context->preference('Version')." and Koha is : ".C4::Context->config("kohaversion");
696         print $query->redirect("/cgi-bin/koha/maintenance.pl");
697       }       
698       exit;
699     }
700     my $template_name;
701     if ( $type eq 'opac' ) {
702         $template_name = "opac-auth.tmpl";
703     }
704     else {
705         $template_name = "auth.tmpl";
706     }
707     my $template = gettemplate( $template_name, $type, $query );
708     $template->param(branchloop => \@branch_loop,);
709     $template->param(
710     login        => 1,
711         INPUTS               => \@inputs,
712         suggestion           => C4::Context->preference("suggestion"),
713         virtualshelves       => C4::Context->preference("virtualshelves"),
714         opaclargeimage       => C4::Context->preference("opaclargeimage"),
715         LibraryName          => C4::Context->preference("LibraryName"),
716         OpacNav              => C4::Context->preference("OpacNav"),
717         opaccredits          => C4::Context->preference("opaccredits"),
718         opacreadinghistory   => C4::Context->preference("opacreadinghistory"),
719         opacsmallimage       => C4::Context->preference("opacsmallimage"),
720         opaclayoutstylesheet => C4::Context->preference("opaclayoutstylesheet"),
721         opaccolorstylesheet  => C4::Context->preference("opaccolorstylesheet"),
722         opaclanguagesdisplay => C4::Context->preference("opaclanguagesdisplay"),
723         opacuserjs           => C4::Context->preference("opacuserjs"),
724
725         intranetcolorstylesheet =>
726           C4::Context->preference("intranetcolorstylesheet"),
727         intranetstylesheet => C4::Context->preference("intranetstylesheet"),
728         IntranetNav        => C4::Context->preference("IntranetNav"),
729         intranetuserjs     => C4::Context->preference("intranetuserjs"),
730         TemplateEncoding   => C4::Context->preference("TemplateEncoding"),
731         IndependantBranches     => C4::Context->preference("IndependantBranches"),
732     );
733     $template->param( loginprompt => 1 ) unless $info{'nopermission'};
734
735     my $self_url = $query->url( -absolute => 1 );
736     $template->param(
737         url         => $self_url,
738         LibraryName => => C4::Context->preference("LibraryName"),
739     );
740     $template->param( \%info );
741 #    $cookie = $query->cookie(CGISESSID => $session->id
742 #   );
743     print $query->header(
744                 -type   => 'text/html',
745         -charset => 'utf-8',
746         -cookie => $cookie
747       ),
748       $template->output;
749     exit;
750 }
751
752 sub checkpw {
753
754     my ( $dbh, $userid, $password ) = @_;
755
756     # INTERNAL AUTH
757     my $sth =
758       $dbh->prepare(
759 "select password,cardnumber,borrowernumber,userid,firstname,surname,branchcode,flags from borrowers where userid=?"
760       );
761     $sth->execute($userid);
762     if ( $sth->rows ) {
763         my ( $md5password, $cardnumber, $borrowernumber, $userid, $firstname,
764             $surname, $branchcode, $flags )
765           = $sth->fetchrow;
766         if ( md5_base64($password) eq $md5password ) {
767
768             C4::Context->set_userenv( "$borrowernumber", $userid, $cardnumber,
769                 $firstname, $surname, $branchcode, $flags );
770             return 1, $cardnumber;
771         }
772     }
773     $sth =
774       $dbh->prepare(
775 "select password,cardnumber,borrowernumber,userid, firstname,surname,branchcode,flags from borrowers where cardnumber=?"
776       );
777     $sth->execute($userid);
778     if ( $sth->rows ) {
779         my ( $md5password, $cardnumber, $borrowernumber, $userid, $firstname,
780             $surname, $branchcode, $flags )
781           = $sth->fetchrow;
782         if ( md5_base64($password) eq $md5password ) {
783
784             C4::Context->set_userenv( $borrowernumber, $userid, $cardnumber,
785                 $firstname, $surname, $branchcode, $flags );
786             return 1, $userid;
787         }
788     }
789     if (   $userid && $userid eq C4::Context->config('user')
790         && "$password" eq C4::Context->config('pass') )
791     {
792
793 # Koha superuser account
794 #     C4::Context->set_userenv(0,0,C4::Context->config('user'),C4::Context->config('user'),C4::Context->config('user'),"",1);
795         return 2;
796     }
797     if (   $userid && $userid eq 'demo'
798         && "$password" eq 'demo'
799         && C4::Context->config('demo') )
800     {
801
802 # DEMO => the demo user is allowed to do everything (if demo set to 1 in koha.conf
803 # some features won't be effective : modify systempref, modify MARC structure,
804         return 2;
805     }
806     return 0;
807 }
808
809 sub getuserflags {
810     my $cardnumber = shift;
811     my $dbh        = shift;
812     my $userflags;
813     my $sth = $dbh->prepare("SELECT flags FROM borrowers WHERE cardnumber=?");
814     $sth->execute($cardnumber);
815     my ($flags) = $sth->fetchrow;
816     $flags = 0 unless $flags;
817     $sth = $dbh->prepare("SELECT bit, flag, defaulton FROM userflags");
818     $sth->execute;
819
820     while ( my ( $bit, $flag, $defaulton ) = $sth->fetchrow ) {
821         if ( ( $flags & ( 2**$bit ) ) || $defaulton ) {
822             $userflags->{$flag} = 1;
823         }
824         else {
825             $userflags->{$flag} = 0;
826         }
827     }
828     return $userflags;
829 }
830
831 sub haspermission {
832     my ( $dbh, $userid, $flagsrequired ) = @_;
833     my $sth = $dbh->prepare("SELECT cardnumber FROM borrowers WHERE userid=?");
834     $sth->execute($userid);
835     my ($cardnumber) = $sth->fetchrow;
836     ($cardnumber) || ( $cardnumber = $userid );
837     my $flags = getuserflags( $cardnumber, $dbh );
838     my $configfile;
839     if ( $userid eq C4::Context->config('user') ) {
840
841         # Super User Account from /etc/koha.conf
842         $flags->{'superlibrarian'} = 1;
843     }
844     if ( $userid eq 'demo' && C4::Context->config('demo') ) {
845
846         # Demo user that can do "anything" (demo=1 in /etc/koha.conf)
847         $flags->{'superlibrarian'} = 1;
848     }
849     return $flags if $flags->{superlibrarian};
850     foreach ( keys %$flagsrequired ) {
851         return $flags if $flags->{$_};
852     }
853     return 0;
854 }
855
856 sub getborrowernumber {
857     my ($userid) = @_;
858     my $dbh = C4::Context->dbh;
859     for my $field ( 'userid', 'cardnumber' ) {
860         my $sth =
861           $dbh->prepare("select borrowernumber from borrowers where $field=?");
862         $sth->execute($userid);
863         if ( $sth->rows ) {
864             my ($bnumber) = $sth->fetchrow;
865             return $bnumber;
866         }
867     }
868     return 0;
869 }
870
871 END { }    # module clean-up code here (global destructor)
872 1;
873 __END__
874
875 =back
876
877 =head1 SEE ALSO
878
879 CGI(3)
880
881 C4::Output(3)
882
883 Digest::MD5(3)
884
885 =cut