Working on a fix for bug 1456
[koha.git] / C4 / Context.pm
1 package C4::Context;
2 # Copyright 2002 Katipo Communications
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 use strict;
20
21 BEGIN {
22         if ($ENV{'USER_AGENT'}) {
23                 require CGI::Carp;
24                 import CGI::Carp qw(fatalsToBrowser);
25                         sub handle_errors {
26                                 my $msg = shift;
27                                 my $debug_level =  C4::Context->preference("DebugLevel");
28
29                                 if ($debug_level eq "2"){
30                                         # debug 2 , print extra info too.
31                                         my %versions = get_versions();
32
33                 # a little example table with various version info";
34                                         print "
35                                                 <h1>debug level $debug_level </h1>
36                                                 <p>Got an error: $msg</p>
37                                                 <table>
38                                                 <tr><th>Apache<td>  $versions{apacheVersion}</tr>
39                                                 <tr><th>Koha<td>    $versions{kohaVersion}</tr>
40                                                 <tr><th>MySQL<td>   $versions{mysqlVersion}</tr>
41                                                 <tr><th>OS<td>      $versions{osVersion}</tr>
42                                                 <tr><th>Perl<td>    $versions{perlVersion}</tr>
43                                                 </table>";
44
45                                 } elsif ($debug_level eq "1"){
46                                         print "<h1>debug level $debug_level </h1>";
47                                         print "<p>Got an error: $msg</p>";
48                                 } else {
49                                         print "production mode - trapped fatal";
50                                 }       
51                         }       
52                 CGI::Carp->set_message(\&handle_errors);
53     }   # else there is no browser to send fatals to!
54 }
55
56 use DBI;
57 use ZOOM;
58 use XML::Simple;
59
60 use C4::Boolean;
61
62 use vars qw($VERSION $AUTOLOAD $context @context_stack);
63
64 $VERSION = '3.00.00.005';
65
66 =head1 NAME
67
68 C4::Context - Maintain and manipulate the context of a Koha script
69
70 =head1 SYNOPSIS
71
72   use C4::Context;
73
74   use C4::Context("/path/to/koha.xml");
75
76   $config_value = C4::Context->config("config_variable");
77
78   $koha_preference = C4::Context->preference("preference");
79
80   $db_handle = C4::Context->dbh;
81
82   $Zconn = C4::Context->Zconn;
83
84   $stopwordhash = C4::Context->stopwords;
85
86 =head1 DESCRIPTION
87
88 When a Koha script runs, it makes use of a certain number of things:
89 configuration settings in F</etc/koha.xml>, a connection to the Koha
90 databases, and so forth. These things make up the I<context> in which
91 the script runs.
92
93 This module takes care of setting up the context for a script:
94 figuring out which configuration file to load, and loading it, opening
95 a connection to the right database, and so forth.
96
97 Most scripts will only use one context. They can simply have
98
99   use C4::Context;
100
101 at the top.
102
103 Other scripts may need to use several contexts. For instance, if a
104 library has two databases, one for a certain collection, and the other
105 for everything else, it might be necessary for a script to use two
106 different contexts to search both databases. Such scripts should use
107 the C<&set_context> and C<&restore_context> functions, below.
108
109 By default, C4::Context reads the configuration from
110 F</etc/koha.xml>. This may be overridden by setting the C<$KOHA_CONF>
111 environment variable to the pathname of a configuration file to use.
112
113 =head1 METHODS
114
115 =over 2
116
117 =cut
118
119 #'
120 # In addition to what is said in the POD above, a Context object is a
121 # reference-to-hash with the following fields:
122 #
123 # config
124 #    A reference-to-hash whose keys and values are the
125 #    configuration variables and values specified in the config
126 #    file (/etc/koha.xml).
127 # dbh
128 #    A handle to the appropriate database for this context.
129 # dbh_stack
130 #    Used by &set_dbh and &restore_dbh to hold other database
131 #    handles for this context.
132 # Zconn
133 #     A connection object for the Zebra server
134
135 use constant CONFIG_FNAME => "/etc/koha.xml";
136                 # Default config file, if none is specified
137
138 $context = undef;        # Initially, no context is set
139 @context_stack = ();        # Initially, no saved contexts
140
141
142 =item KOHAVERSION
143     returns the kohaversion stored in kohaversion.pl file
144 =cut
145
146 sub KOHAVERSION {
147     my $cgidir = C4::Context->intranetdir ."/cgi-bin";
148     unless (opendir(DIR, "$cgidir/cataloguing/value_builder")) {
149             $cgidir = C4::Context->intranetdir;
150     }
151     do $cgidir."/kohaversion.pl" || die "NO $cgidir/kohaversion.pl";
152     return kohaversion();
153 }
154 =item read_config_file
155
156 =over 4
157
158 Reads the specified Koha config file. 
159
160 Returns an object containing the configuration variables. The object's
161 structure is a bit complex to the uninitiated ... take a look at the
162 koha.xml file as well as the XML::Simple documentation for details. Or,
163 here are a few examples that may give you what you need:
164
165 The simple elements nested within the <config> element:
166
167     my $pass = $koha->{'config'}->{'pass'};
168
169 The <listen> elements:
170
171     my $listen = $koha->{'listen'}->{'biblioserver'}->{'content'};
172
173 The elements nested within the <server> element:
174
175     my $ccl2rpn = $koha->{'server'}->{'biblioserver'}->{'cql2rpn'};
176
177 Returns undef in case of error.
178
179 =back
180
181 =cut
182
183 sub read_config_file {
184     my $fname = shift;    # Config file to read
185     my $retval = {};    # Return value: ref-to-hash holding the configuration
186     my $koha = XMLin($fname, keyattr => ['id'],forcearray => ['listen', 'server', 'serverinfo']);
187     return $koha;
188 }
189
190 # db_scheme2dbi
191 # Translates the full text name of a database into de appropiate dbi name
192
193 sub db_scheme2dbi {
194     my $name = shift;
195
196     for ($name) {
197 # FIXME - Should have other databases. 
198         if (/mysql/i) { return("mysql"); }
199         if (/Postgres|Pg|PostgresSQL/) { return("Pg"); }
200         if (/oracle/i) { return("Oracle"); }
201     }
202     return undef;         # Just in case
203 }
204
205 sub import {
206     my $package = shift;
207     my $conf_fname = shift;        # Config file name
208     my $context;
209
210     # Create a new context from the given config file name, if
211     # any, then set it as the current context.
212     $context = new C4::Context($conf_fname);
213     return undef if !defined($context);
214     $context->set_context;
215 }
216
217 =item new
218
219   $context = new C4::Context;
220   $context = new C4::Context("/path/to/koha.xml");
221
222 Allocates a new context. Initializes the context from the specified
223 file, which defaults to either the file given by the C<$KOHA_CONF>
224 environment variable, or F</etc/koha.xml>.
225
226 C<&new> does not set this context as the new default context; for
227 that, use C<&set_context>.
228
229 =cut
230
231 #'
232 # Revision History:
233 # 2004-08-10 A. Tarallo: Added check if the conf file is not empty
234 sub new {
235     my $class = shift;
236     my $conf_fname = shift;        # Config file to load
237     my $self = {};
238
239     # check that the specified config file exists and is not empty
240     undef $conf_fname unless 
241         (defined $conf_fname && -e $conf_fname && -s $conf_fname);
242     # Figure out a good config file to load if none was specified.
243     if (!defined($conf_fname))
244     {
245         # If the $KOHA_CONF environment variable is set, use
246         # that. Otherwise, use the built-in default.
247         $conf_fname = $ENV{"KOHA_CONF"} || CONFIG_FNAME;
248     }
249         # Load the desired config file.
250     $self = read_config_file($conf_fname);
251     $self->{"config_file"} = $conf_fname;
252     
253     warn "read_config_file($conf_fname) returned undef" if !defined($self->{"config"});
254     return undef if !defined($self->{"config"});
255
256     $self->{"dbh"} = undef;        # Database handle
257     $self->{"Zconn"} = undef;    # Zebra Connections
258     $self->{"stopwords"} = undef; # stopwords list
259     $self->{"marcfromkohafield"} = undef; # the hash with relations between koha table fields and MARC field/subfield
260     $self->{"userenv"} = undef;        # User env
261     $self->{"activeuser"} = undef;        # current active user
262
263     bless $self, $class;
264     return $self;
265 }
266
267 =item set_context
268
269   $context = new C4::Context;
270   $context->set_context();
271 or
272   set_context C4::Context $context;
273
274   ...
275   restore_context C4::Context;
276
277 In some cases, it might be necessary for a script to use multiple
278 contexts. C<&set_context> saves the current context on a stack, then
279 sets the context to C<$context>, which will be used in future
280 operations. To restore the previous context, use C<&restore_context>.
281
282 =cut
283
284 #'
285 sub set_context
286 {
287     my $self = shift;
288     my $new_context;    # The context to set
289
290     # Figure out whether this is a class or instance method call.
291     #
292     # We're going to make the assumption that control got here
293     # through valid means, i.e., that the caller used an instance
294     # or class method call, and that control got here through the
295     # usual inheritance mechanisms. The caller can, of course,
296     # break this assumption by playing silly buggers, but that's
297     # harder to do than doing it properly, and harder to check
298     # for.
299     if (ref($self) eq "")
300     {
301         # Class method. The new context is the next argument.
302         $new_context = shift;
303     } else {
304         # Instance method. The new context is $self.
305         $new_context = $self;
306     }
307
308     # Save the old context, if any, on the stack
309     push @context_stack, $context if defined($context);
310
311     # Set the new context
312     $context = $new_context;
313 }
314
315 =item restore_context
316
317   &restore_context;
318
319 Restores the context set by C<&set_context>.
320
321 =cut
322
323 #'
324 sub restore_context
325 {
326     my $self = shift;
327
328     if ($#context_stack < 0)
329     {
330         # Stack underflow.
331         die "Context stack underflow";
332     }
333
334     # Pop the old context and set it.
335     $context = pop @context_stack;
336
337     # FIXME - Should this return something, like maybe the context
338     # that was current when this was called?
339 }
340
341 =item config
342
343   $value = C4::Context->config("config_variable");
344
345   $value = C4::Context->config_variable;
346
347 Returns the value of a variable specified in the configuration file
348 from which the current context was created.
349
350 The second form is more compact, but of course may conflict with
351 method names. If there is a configuration variable called "new", then
352 C<C4::Config-E<gt>new> will not return it.
353
354 =cut
355
356 #'
357 sub config
358 {
359     my $self = shift;
360     my $var = shift;        # The config variable to return
361
362     return undef if !defined($context->{"config"});
363             # Presumably $self->{config} might be
364             # undefined if the config file given to &new
365             # didn't exist, and the caller didn't bother
366             # to check the return value.
367
368     # Return the value of the requested config variable
369     return $context->{"config"}->{$var};
370 }
371
372 sub zebraconfig
373 {
374     my $self = shift;
375     my $var = shift;        # The config variable to return
376
377     return undef if !defined($context->{"server"});
378             # Presumably $self->{config} might be
379             # undefined if the config file given to &new
380             # didn't exist, and the caller didn't bother
381             # to check the return value.
382
383     # Return the value of the requested config variable
384     return $context->{"server"}->{$var};
385 }
386 sub ModZebrations
387 {
388     my $self = shift;
389     my $var = shift;        # The config variable to return
390
391     return undef if !defined($context->{"serverinfo"});
392             # Presumably $self->{config} might be
393             # undefined if the config file given to &new
394             # didn't exist, and the caller didn't bother
395             # to check the return value.
396
397     # Return the value of the requested config variable
398     return $context->{"serverinfo"}->{$var};
399 }
400 =item preference
401
402   $sys_preference = C4::Context->preference("some_variable");
403
404 Looks up the value of the given system preference in the
405 systempreferences table of the Koha database, and returns it. If the
406 variable is not set, or in case of error, returns the undefined value.
407
408 =cut
409
410 #'
411 # FIXME - The preferences aren't likely to change over the lifetime of
412 # the script (and things might break if they did change), so perhaps
413 # this function should cache the results it finds.
414 sub preference
415 {
416     my $self = shift;
417     my $var = shift;        # The system preference to return
418     my $retval;            # Return value
419     my $dbh = C4::Context->dbh;    # Database handle
420     if ($dbh){
421     my $sth;            # Database query handle
422
423     # Look up systempreferences.variable==$var
424     $retval = $dbh->selectrow_array(<<EOT);
425         SELECT    value
426         FROM    systempreferences
427         WHERE    variable='$var'
428         LIMIT    1
429 EOT
430     return $retval;
431     } else {
432       return 0
433     }
434 }
435
436 sub boolean_preference ($) {
437     my $self = shift;
438     my $var = shift;        # The system preference to return
439     my $it = preference($self, $var);
440     return defined($it)? C4::Boolean::true_p($it): undef;
441 }
442
443 # AUTOLOAD
444 # This implements C4::Config->foo, and simply returns
445 # C4::Context->config("foo"), as described in the documentation for
446 # &config, above.
447
448 # FIXME - Perhaps this should be extended to check &config first, and
449 # then &preference if that fails. OTOH, AUTOLOAD could lead to crappy
450 # code, so it'd probably be best to delete it altogether so as not to
451 # encourage people to use it.
452 sub AUTOLOAD
453 {
454     my $self = shift;
455
456     $AUTOLOAD =~ s/.*:://;        # Chop off the package name,
457                     # leaving only the function name.
458     return $self->config($AUTOLOAD);
459 }
460
461 =item Zconn
462
463 $Zconn = C4::Context->Zconn
464
465 Returns a connection to the Zebra database for the current
466 context. If no connection has yet been made, this method 
467 creates one and connects.
468
469 C<$self> 
470
471 C<$server> one of the servers defined in the koha.xml file
472
473 C<$async> whether this is a asynchronous connection
474
475 C<$auth> whether this connection has rw access (1) or just r access (0 or NULL)
476
477
478 =cut
479
480 sub Zconn {
481     my $self=shift;
482     my $server=shift;
483     my $async=shift;
484     my $auth=shift;
485     my $piggyback=shift;
486     my $syntax=shift;
487     if ( defined($context->{"Zconn"}->{$server}) ) {
488         return $context->{"Zconn"}->{$server};
489
490     # No connection object or it died. Create one.
491     }else {
492         $context->{"Zconn"}->{$server} = &_new_Zconn($server,$async,$auth,$piggyback,$syntax);
493         return $context->{"Zconn"}->{$server};
494     }
495 }
496
497 =item _new_Zconn
498
499 $context->{"Zconn"} = &_new_Zconn($server,$async);
500
501 Internal function. Creates a new database connection from the data given in the current context and returns it.
502
503 C<$server> one of the servers defined in the koha.xml file
504
505 C<$async> whether this is a asynchronous connection
506
507 C<$auth> whether this connection has rw access (1) or just r access (0 or NULL)
508
509 =cut
510
511 sub _new_Zconn {
512     my ($server,$async,$auth,$piggyback,$syntax) = @_;
513
514     my $tried=0; # first attempt
515     my $Zconn; # connection object
516     $server = "biblioserver" unless $server;
517     $syntax = "usmarc" unless $syntax;
518
519     my $host = $context->{'listen'}->{$server}->{'content'};
520     my $user = $context->{"serverinfo"}->{$server}->{"user"};
521     my $servername = $context->{"config"}->{$server};
522     my $password = $context->{"serverinfo"}->{$server}->{"password"};
523     retry:
524     eval {
525         # set options
526         my $o = new ZOOM::Options();
527         $o->option(async => 1) if $async;
528         $o->option(count => $piggyback) if $piggyback;
529         $o->option(cqlfile=> $context->{"server"}->{$server}->{"cql2rpn"});
530         $o->option(cclfile=> $context->{"serverinfo"}->{$server}->{"ccl2rpn"});
531         $o->option(preferredRecordSyntax => $syntax);
532         $o->option(elementSetName => "F"); # F for 'full' as opposed to B for 'brief'
533         $o->option(user=>$user) if $auth;
534         $o->option(password=>$password) if $auth;
535         $o->option(databaseName => ($servername?$servername:"biblios"));
536
537         # create a new connection object
538         $Zconn= create ZOOM::Connection($o);
539
540         # forge to server
541         $Zconn->connect($host, 0);
542
543         # check for errors and warn
544         if ($Zconn->errcode() !=0) {
545             warn "something wrong with the connection: ". $Zconn->errmsg();
546         }
547
548     };
549 #     if ($@) {
550 #         # Koha manages the Zebra server -- this doesn't work currently for me because of permissions issues
551 #         # Also, I'm skeptical about whether it's the best approach
552 #         warn "problem with Zebra";
553 #         if ( C4::Context->preference("ManageZebra") ) {
554 #             if ($@->code==10000 && $tried==0) { ##No connection try restarting Zebra
555 #                 $tried=1;
556 #                 warn "trying to restart Zebra";
557 #                 my $res=system("zebrasrv -f $ENV{'KOHA_CONF'} >/koha/log/zebra-error.log");
558 #                 goto "retry";
559 #             } else {
560 #                 warn "Error ", $@->code(), ": ", $@->message(), "\n";
561 #                 $Zconn="error";
562 #                 return $Zconn;
563 #             }
564 #         }
565 #     }
566     return $Zconn;
567 }
568
569 # _new_dbh
570 # Internal helper function (not a method!). This creates a new
571 # database connection from the data given in the current context, and
572 # returns it.
573 sub _new_dbh
574 {
575     ##correct name for db_schme        
576     my $db_driver;
577     if ($context->config("db_scheme")){
578     $db_driver=db_scheme2dbi($context->config("db_scheme"));
579     }else{
580     $db_driver="mysql";
581     }
582
583     my $db_name   = $context->config("database");
584     my $db_host   = $context->config("hostname");
585     my $db_user   = $context->config("user");
586     my $db_passwd = $context->config("pass");
587     my $dbh= DBI->connect("DBI:$db_driver:$db_name:$db_host",
588                 $db_user, $db_passwd);
589     # Koha 3.0 is utf-8, so force utf8 communication between mySQL and koha, whatever the mysql default config.
590     # this is better than modifying my.cnf (and forcing all communications to be in utf8)
591     $dbh->do("set NAMES 'utf8'") if ($dbh);
592     $dbh->{'mysql_enable_utf8'}=1; #enable
593     return $dbh;
594 }
595
596 =item dbh
597
598   $dbh = C4::Context->dbh;
599
600 Returns a database handle connected to the Koha database for the
601 current context. If no connection has yet been made, this method
602 creates one, and connects to the database.
603
604 This database handle is cached for future use: if you call
605 C<C4::Context-E<gt>dbh> twice, you will get the same handle both
606 times. If you need a second database handle, use C<&new_dbh> and
607 possibly C<&set_dbh>.
608
609 =cut
610
611 #'
612 sub dbh
613 {
614     my $self = shift;
615     my $sth;
616
617     if (defined($context->{"dbh"})) {
618         $sth=$context->{"dbh"}->prepare("select 1");
619         return $context->{"dbh"} if (defined($sth->execute));
620     }
621
622     # No database handle or it died . Create one.
623     $context->{"dbh"} = &_new_dbh();
624
625     return $context->{"dbh"};
626 }
627
628 =item new_dbh
629
630   $dbh = C4::Context->new_dbh;
631
632 Creates a new connection to the Koha database for the current context,
633 and returns the database handle (a C<DBI::db> object).
634
635 The handle is not saved anywhere: this method is strictly a
636 convenience function; the point is that it knows which database to
637 connect to so that the caller doesn't have to know.
638
639 =cut
640
641 #'
642 sub new_dbh
643 {
644     my $self = shift;
645
646     return &_new_dbh();
647 }
648
649 =item set_dbh
650
651   $my_dbh = C4::Connect->new_dbh;
652   C4::Connect->set_dbh($my_dbh);
653   ...
654   C4::Connect->restore_dbh;
655
656 C<&set_dbh> and C<&restore_dbh> work in a manner analogous to
657 C<&set_context> and C<&restore_context>.
658
659 C<&set_dbh> saves the current database handle on a stack, then sets
660 the current database handle to C<$my_dbh>.
661
662 C<$my_dbh> is assumed to be a good database handle.
663
664 =cut
665
666 #'
667 sub set_dbh
668 {
669     my $self = shift;
670     my $new_dbh = shift;
671
672     # Save the current database handle on the handle stack.
673     # We assume that $new_dbh is all good: if the caller wants to
674     # screw himself by passing an invalid handle, that's fine by
675     # us.
676     push @{$context->{"dbh_stack"}}, $context->{"dbh"};
677     $context->{"dbh"} = $new_dbh;
678 }
679
680 =item restore_dbh
681
682   C4::Context->restore_dbh;
683
684 Restores the database handle saved by an earlier call to
685 C<C4::Context-E<gt>set_dbh>.
686
687 =cut
688
689 #'
690 sub restore_dbh
691 {
692     my $self = shift;
693
694     if ($#{$context->{"dbh_stack"}} < 0)
695     {
696         # Stack underflow
697         die "DBH stack underflow";
698     }
699
700     # Pop the old database handle and set it.
701     $context->{"dbh"} = pop @{$context->{"dbh_stack"}};
702
703     # FIXME - If it is determined that restore_context should
704     # return something, then this function should, too.
705 }
706
707 =item marcfromkohafield
708
709   $dbh = C4::Context->marcfromkohafield;
710
711 Returns a hash with marcfromkohafield.
712
713 This hash is cached for future use: if you call
714 C<C4::Context-E<gt>marcfromkohafield> twice, you will get the same hash without real DB access
715
716 =cut
717
718 #'
719 sub marcfromkohafield
720 {
721     my $retval = {};
722
723     # If the hash already exists, return it.
724     return $context->{"marcfromkohafield"} if defined($context->{"marcfromkohafield"});
725
726     # No hash. Create one.
727     $context->{"marcfromkohafield"} = &_new_marcfromkohafield();
728
729     return $context->{"marcfromkohafield"};
730 }
731
732 # _new_marcfromkohafield
733 # Internal helper function (not a method!). This creates a new
734 # hash with stopwords
735 sub _new_marcfromkohafield
736 {
737     my $dbh = C4::Context->dbh;
738     my $marcfromkohafield;
739     my $sth = $dbh->prepare("select frameworkcode,kohafield,tagfield,tagsubfield from marc_subfield_structure where kohafield > ''");
740     $sth->execute;
741     while (my ($frameworkcode,$kohafield,$tagfield,$tagsubfield) = $sth->fetchrow) {
742         my $retval = {};
743         $marcfromkohafield->{$frameworkcode}->{$kohafield} = [$tagfield,$tagsubfield];
744     }
745     return $marcfromkohafield;
746 }
747
748 =item stopwords
749
750   $dbh = C4::Context->stopwords;
751
752 Returns a hash with stopwords.
753
754 This hash is cached for future use: if you call
755 C<C4::Context-E<gt>stopwords> twice, you will get the same hash without real DB access
756
757 =cut
758
759 #'
760 sub stopwords
761 {
762     my $retval = {};
763
764     # If the hash already exists, return it.
765     return $context->{"stopwords"} if defined($context->{"stopwords"});
766
767     # No hash. Create one.
768     $context->{"stopwords"} = &_new_stopwords();
769
770     return $context->{"stopwords"};
771 }
772
773 # _new_stopwords
774 # Internal helper function (not a method!). This creates a new
775 # hash with stopwords
776 sub _new_stopwords
777 {
778     my $dbh = C4::Context->dbh;
779     my $stopwordlist;
780     my $sth = $dbh->prepare("select word from stopwords");
781     $sth->execute;
782     while (my $stopword = $sth->fetchrow_array) {
783         my $retval = {};
784         $stopwordlist->{$stopword} = uc($stopword);
785     }
786     $stopwordlist->{A} = "A" unless $stopwordlist;
787     return $stopwordlist;
788 }
789
790 =item userenv
791
792   C4::Context->userenv;
793
794 Builds a hash for user environment variables.
795
796 This hash shall be cached for future use: if you call
797 C<C4::Context-E<gt>userenv> twice, you will get the same hash without real DB access
798
799 set_userenv is called in Auth.pm
800
801 =cut
802
803 #'
804 sub userenv
805 {
806     my $var = $context->{"activeuser"};
807     return $context->{"userenv"}->{$var} if (defined $context->{"userenv"}->{$var});
808     # insecure=1 management
809     if ($context->{"dbh"} && $context->preference('insecure')) {
810         my %insecure;
811         $insecure{flags} = '16382';
812         $insecure{branchname} ='Insecure',
813         $insecure{number} ='0';
814         $insecure{cardnumber} ='0';
815         $insecure{id} = 'insecure';
816         $insecure{branch} = 'INS';
817         $insecure{emailaddress} = 'test@mode.insecure.com';
818         return \%insecure;
819     } else {
820         return 0;
821     }
822 }
823
824 =item set_userenv
825
826   C4::Context->set_userenv($usernum, $userid, $usercnum, $userfirstname, $usersurname, $userbranch, $userflags, $emailaddress);
827
828 Informs a hash for user environment variables.
829
830 This hash shall be cached for future use: if you call
831 C<C4::Context-E<gt>userenv> twice, you will get the same hash without real DB access
832
833 set_userenv is called in Auth.pm
834
835 =cut
836
837 #'
838 sub set_userenv{
839     my ($usernum, $userid, $usercnum, $userfirstname, $usersurname, $userbranch, $branchname, $userflags, $emailaddress, $branchprinter)= @_;
840     my $var=$context->{"activeuser"};
841     my $cell = {
842         "number"     => $usernum,
843         "id"         => $userid,
844         "cardnumber" => $usercnum,
845         "firstname"  => $userfirstname,
846         "surname"    => $usersurname,
847 #possibly a law problem
848         "branch"     => $userbranch,
849         "branchname" => $branchname,
850         "flags"      => $userflags,
851         "emailaddress"    => $emailaddress,
852                 "branchprinter"    => $branchprinter
853     };
854     $context->{userenv}->{$var} = $cell;
855     return $cell;
856 }
857
858 =item _new_userenv
859
860   C4::Context->_new_userenv($session);
861
862 Builds a hash for user environment variables.
863
864 This hash shall be cached for future use: if you call
865 C<C4::Context-E<gt>userenv> twice, you will get the same hash without real DB access
866
867 _new_userenv is called in Auth.pm
868
869 =cut
870
871 #'
872 sub _new_userenv
873 {
874     shift;
875     my ($sessionID)= @_;
876      $context->{"activeuser"}=$sessionID;
877 }
878
879 =item _unset_userenv
880
881   C4::Context->_unset_userenv;
882
883 Destroys the hash for activeuser user environment variables.
884
885 =cut
886
887 #'
888
889 sub _unset_userenv
890 {
891     my ($sessionID)= @_;
892     undef $context->{"activeuser"} if ($context->{"activeuser"} eq $sessionID);
893 }
894
895
896 =item get_versions
897
898   C4::Context->get_versions
899
900 Gets various version info, for core Koha packages, Currently called from carp handle_errors() sub, to send to browser if 'DebugLevel' syspref is set to '2'.
901
902 =cut
903
904 #'
905
906 # A little example sub to show more debugging info for CGI::Carp
907 sub get_versions {
908     my %versions;
909     $versions{kohaVersion}  = C4::Context->config("kohaversion");
910     $versions{osVersion} = `uname -a`;
911     $versions{perlVersion} = $];
912     $versions{mysqlVersion} = `mysql -V`;
913     $versions{apacheVersion} =  `httpd -v`;
914     $versions{apacheVersion} =  `httpd2 -v`            unless  $versions{apacheVersion} ;
915     $versions{apacheVersion} =  `apache2 -v`           unless  $versions{apacheVersion} ;
916     $versions{apacheVersion} =  `/usr/sbin/apache2 -v` unless  $versions{apacheVersion} ;
917     return %versions;
918 }
919
920
921 1;
922 __END__
923
924 =back
925
926 =head1 ENVIRONMENT
927
928 =over 4
929
930 =item C<KOHA_CONF>
931
932 Specifies the configuration file to read.
933
934 =back
935
936 =head1 SEE ALSO
937
938 =head1 AUTHORS
939
940 Andrew Arensburger <arensb at ooblick dot com>
941
942 Joshua Ferraro <jmf at liblime dot com>
943
944 =cut
945
946 # Revision 1.57  2007/05/22 09:13:55  tipaul
947 # Bugfixes & improvements (various and minor) :
948 # - updating templates to have tmpl_process3.pl running without any errors
949 # - adding a drupal-like css for prog templates (with 3 small images)
950 # - fixing some bugs in circulation & other scripts
951 # - updating french translation
952 # - fixing some typos in templates
953 #
954 # Revision 1.56  2007/04/23 15:21:17  tipaul
955 # renaming currenttransfers to transferstoreceive
956 #
957 # Revision 1.55  2007/04/17 08:48:00  tipaul
958 # circulation cleaning continued: bufixing
959 #
960 # Revision 1.54  2007/03/29 16:45:53  tipaul
961 # Code cleaning of Biblio.pm (continued)
962 #
963 # All subs have be cleaned :
964 # - removed useless
965 # - merged some
966 # - reordering Biblio.pm completly
967 # - using only naming conventions
968 #
969 # Seems to have broken nothing, but it still has to be heavily tested.
970 # Note that Biblio.pm is now much more efficient than previously & probably more reliable as well.
971 #
972 # Revision 1.53  2007/03/29 13:30:31  tipaul
973 # Code cleaning :
974 # == Biblio.pm cleaning (useless) ==
975 # * some sub declaration dropped
976 # * removed modbiblio sub
977 # * removed moditem sub
978 # * removed newitems. It was used only in finishrecieve. Replaced by a TransformKohaToMarc+AddItem, that is better.
979 # * removed MARCkoha2marcItem
980 # * removed MARCdelsubfield declaration
981 # * removed MARCkoha2marcBiblio
982 #
983 # == Biblio.pm cleaning (naming conventions) ==
984 # * MARCgettagslib renamed to GetMarcStructure
985 # * MARCgetitems renamed to GetMarcItem
986 # * MARCfind_frameworkcode renamed to GetFrameworkCode
987 # * MARCmarc2koha renamed to TransformMarcToKoha
988 # * MARChtml2marc renamed to TransformHtmlToMarc
989 # * MARChtml2xml renamed to TranformeHtmlToXml
990 # * zebraop renamed to ModZebra
991 #
992 # == MARC=OFF ==
993 # * removing MARC=OFF related scripts (in cataloguing directory)
994 # * removed checkitems (function related to MARC=off feature, that is completly broken in head. If someone want to reintroduce it, hard work coming...)
995 # * removed getitemsbybiblioitem (used only by MARC=OFF scripts, that is removed as well)
996 #
997 # Revision 1.52  2007/03/16 01:25:08  kados
998 # Using my precrash CVS copy I did the following:
999 #
1000 # cvs -z3 -d:ext:kados@cvs.savannah.nongnu.org:/sources/koha co -P koha
1001 # find koha.precrash -type d -name "CVS" -exec rm -v {} \;
1002 # cp -r koha.precrash/* koha/
1003 # cd koha/
1004 # cvs commit
1005 #
1006 # This should in theory put us right back where we were before the crash
1007 #
1008 # Revision 1.52  2007/03/12 21:17:05  rych
1009 # add server, serverinfo as arrays from config
1010 #
1011 # Revision 1.51  2007/03/09 14:31:47  tipaul
1012 # rel_3_0 moved to HEAD
1013 #
1014 # Revision 1.43.2.10  2007/02/09 17:17:56  hdl
1015 # Managing a little better database absence.
1016 # (preventing from BIG 550)
1017 #
1018 # Revision 1.43.2.9  2006/12/20 16:50:48  tipaul
1019 # improving "insecure" management
1020 #
1021 # WARNING KADOS :
1022 # you told me that you had some libraries with insecure=ON (behind a firewall).
1023 # In this commit, I created a "fake" user when insecure=ON. It has a fake branch. You may find better to have the 1st branch in branch table instead of a fake one.
1024 #
1025 # Revision 1.43.2.8  2006/12/19 16:48:16  alaurin
1026 # reident programs, and adding branchcode value in reserves
1027 #
1028 # Revision 1.43.2.7  2006/12/06 21:55:38  hdl
1029 # Adding ModZebrations for servers to get serverinfos in Context.pm
1030 # Using this function in rebuild_zebra.pl
1031 #
1032 # Revision 1.43.2.6  2006/11/24 21:18:31  kados
1033 # very minor changes, no functional ones, just comments, etc.
1034 #
1035 # Revision 1.43.2.5  2006/10/30 13:24:16  toins
1036 # fix some minor POD error.
1037 #
1038 # Revision 1.43.2.4  2006/10/12 21:42:49  hdl
1039 # Managing multiple zebra connections
1040 #
1041 # Revision 1.43.2.3  2006/10/11 14:27:26  tipaul
1042 # removing a warning
1043 #
1044 # Revision 1.43.2.2  2006/10/10 15:28:16  hdl
1045 # BUG FIXING : using database name in Zconn if defined and not hard coded value
1046 #
1047 # Revision 1.43.2.1  2006/10/06 13:47:28  toins
1048 # Synch with dev_week.
1049 #  /!\ WARNING :: Please now use the new version of koha.xml.
1050 #
1051 # Revision 1.18.2.5.2.14  2006/09/24 15:24:06  kados
1052 # remove Zebraauth routine, fold the functionality into Zconn
1053 # Zconn can now take several arguments ... this will probably
1054 # change soon as I'm not completely happy with the readability
1055 # of the current format ... see the POD for details.
1056 #
1057 # cleaning up Biblio.pm, removing unnecessary routines.
1058 #
1059 # DeleteBiblio - used to delete a biblio from zebra and koha tables
1060 #     -- checks to make sure there are no existing issues
1061 #     -- saves backups of biblio,biblioitems,items in deleted* tables
1062 #     -- does commit operation
1063 #
1064 # getRecord - used to retrieve one record from zebra in piggyback mode using biblionumber
1065 # brought back z3950_extended_services routine
1066 #
1067 # Lots of modifications to Context.pm, you can now store user and pass info for
1068 # multiple servers (for federated searching) using the <serverinfo> element.
1069 # I'll commit my koha.xml to demonstrate this or you can refer to the POD in
1070 # Context.pm (which I also expanded on).
1071 #
1072 # Revision 1.18.2.5.2.13  2006/08/10 02:10:21  kados
1073 # Turned warnings on, and running a search turned up lots of warnings.
1074 # Cleaned up those ...
1075 #
1076 # removed getitemtypes from Koha.pm (one in Search.pm looks newer)
1077 # removed itemcount from Biblio.pm
1078 #
1079 # made some local subs local with a _ prefix (as they were redefined
1080 # elsewhere)
1081 #
1082 # Add two new search subs to Search.pm the start of a new search API
1083 # that's a bit more scalable
1084 #
1085 # Revision 1.18.2.5.2.10  2006/07/21 17:50:51  kados
1086 # moving the *.properties files to intranetdir/etc dir
1087 #
1088 # Revision 1.18.2.5.2.9  2006/07/17 08:05:20  tipaul
1089 # there was a hardcoded link to /koha/etc/ I replaced it with intranetdir config value
1090 #
1091 # Revision 1.18.2.5.2.8  2006/07/11 12:20:37  kados
1092 # adding ccl and cql files ... Tumer, if you want to fit these into the
1093 # config file by all means do.
1094 #
1095 # Revision 1.18.2.5.2.7  2006/06/04 22:50:33  tgarip1957
1096 # We do not hard code cql2rpn conversion file in context.pm our koha.xml configuration file already describes the path for this file.
1097 # At cql searching we use method CQL not CQL2RPN as the cql2rpn conversion file is defined at server level
1098 #
1099 # Revision 1.18.2.5.2.6  2006/06/02 23:11:24  kados
1100 # Committing my working dev_week. It's been tested only with
1101 # searching, and there's quite a lot of config stuff to set up
1102 # beforehand. As things get closer to a release, we'll be making
1103 # some scripts to do it for us
1104 #
1105 # Revision 1.18.2.5.2.5  2006/05/28 18:49:12  tgarip1957
1106 # This is an unusual commit. The main purpose is a working model of Zebra on a modified rel2_2.
1107 # Any questions regarding these commits should be asked to Joshua Ferraro unless you are Joshua whom I'll report to
1108 #
1109 # Revision 1.36  2006/05/09 13:28:08  tipaul
1110 # adding the branchname and the librarian name in every page :
1111 # - modified userenv to add branchname
1112 # - modifier menus.inc to have the librarian name & userenv displayed on every page. they are in a librarian_information div.
1113 #
1114 # Revision 1.35  2006/04/13 08:40:11  plg
1115 # bug fixed: typo on Zconnauth name
1116 #
1117 # Revision 1.34  2006/04/10 21:40:23  tgarip1957
1118 # A new handler defined for zebra Zconnauth with read/write permission. Zconnauth should only be called in biblio.pm where write operations are. Use of this handler will break things unless koha.conf contains new variables:
1119 # zebradb=localhost
1120 # zebraport=<your port>
1121 # zebrauser=<username>
1122 # zebrapass=<password>
1123 #
1124 # The zebra.cfg file should read:
1125 # perm.anonymous:r
1126 # perm.username:rw
1127 # passw.c:<yourpasswordfile>
1128 #
1129 # Password file should be prepared with Apaches htpasswd utility in encrypted mode and should exist in a folder zebra.cfg can read
1130 #
1131 # Revision 1.33  2006/03/15 11:21:56  plg
1132 # bug fixed: utf-8 data where not displayed correctly in screens. Supposing
1133 # your data are truely utf-8 encoded in your database, they should be
1134 # correctly displayed. "set names 'UTF8'" on mysql connection (C4/Context.pm)
1135 # is mandatory and "binmode" to utf8 (C4/Interface/CGI/Output.pm) seemed to
1136 # converted data twice, so it was removed.
1137 #
1138 # Revision 1.32  2006/03/03 17:25:01  hdl
1139 # Bug fixing : a line missed a comment sign.
1140 #
1141 # Revision 1.31  2006/03/03 16:45:36  kados
1142 # Remove the search that tests the Zconn -- warning, still no fault
1143 # tollerance
1144 #
1145 # Revision 1.30  2006/02/22 00:56:59  kados
1146 # First go at a connection object for Zebra. You can now get a
1147 # connection object by doing:
1148 #
1149 # my $Zconn = C4::Context->Zconn;
1150 #
1151 # My initial tests indicate that as soon as your funcion ends
1152 # (ie, when you're done doing something) the connection will be
1153 # closed automatically. There may be some other way to make the
1154 # connection more stateful, I'm not sure...
1155 #
1156 # Local Variables:
1157 # tab-width: 4
1158 # End: