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