#!/usr/bin/suidperl -T
#################################################################
#                                                               #
# Open WebMail - Provides a web interface to user mailboxes     #
#                                                               #
# Copyright (C) 2001-2003                                       #
# The Open Webmail Team                                         #
#                                                               #
# Copyright (C) 2000                                            #
# Ernie Miller  (original GPL project: Neomail)                 #
#                                                               #
# This program is distributed under GNU General Public License  #
#                                                               #
#################################################################

#
# openwebmail.pl - entry point of openwebmail
#
use vars qw($SCRIPT_DIR);
if ( $0 =~ m!^(.*?)/[\w\d\-\.]+\.pl! ) { $SCRIPT_DIR=$1; }
if (!$SCRIPT_DIR && open(F, '/etc/openwebmail_path.conf')) {
   $_=<F>; close(F); if ( $_=~/^([^\s]*)/) { $SCRIPT_DIR=$1; }
}
if (!$SCRIPT_DIR) { print "Content-type: text/html\n\nSCRIPT_DIR not set in /etc/openwebmail_path.conf !\n"; exit 0; }
push (@INC, $SCRIPT_DIR);

$ENV{PATH} = ""; # no PATH should be needed
$ENV{ENV} = "";      # no startup script for sh
$ENV{BASH_ENV} = ""; # no startup script for bash
umask(0002); # make sure the openwebmail group can write

use strict;
use Fcntl qw(:DEFAULT :flock);
use Socket;
use CGI qw(-private_tempfiles :standard);
use CGI::Carp qw(fatalsToBrowser carpout);

require "ow-shared.pl";
require "filelock.pl";

# common globals
use vars qw(%config %config_raw %default_config %default_config_raw);
use vars qw($thissession);
use vars qw($default_logindomain $loginname $logindomain $loginuser);
use vars qw($domain $user $userrealname $uuid $ugid $homedir);
use vars qw(%prefs %style);
use vars qw($folderdir);

# extern vars
use vars qw(@openwebmailrcitem);	# defined in ow-shared.pl
use vars qw(%lang_text %lang_err);	# defined in lang/xy

####################### MAIN ##########################
clearvars();

if (!defined(%default_config_raw)) {	# read default only once if persistent mode
   readconf(\%default_config, \%default_config_raw, "$SCRIPT_DIR/etc/openwebmail.conf.default");
}
%config=%default_config; %config_raw =%default_config_raw;
readconf(\%config, \%config_raw, "$SCRIPT_DIR/etc/openwebmail.conf") if (-f "$SCRIPT_DIR/etc/openwebmail.conf");
readlang($config{'default_language'});	# so %lang... can be used in error msg

# check & create mapping table for solar/lunar, b2g, g2b convertion
foreach my $table ('b2g', 'g2b', 'lunar') {
   if ( $config{$table.'_map'} ne 'none' &&
        ! -f "$config{'ow_etcdir'}/$table$config{'dbm_ext'}") {
      print qq|Content-type: text/html\n\n|.
            qq|Please execute '$config{'ow_cgidir'}/openwebmail-tool.pl --init' on server first!|; 
      exit 0;
   }
}

if ( ($config{'logfile'} ne 'no') ) {
   my $mailgid=getgrnam('mail');
   my ($fmode, $fuid, $fgid) = (stat($config{'logfile'}))[2,4,5];
   if ( !($fmode & 0100000) ) {
      open (LOGFILE,">>$config{'logfile'}") or
         openwebmailerror("$lang_err{'couldnt_open'} $lang_text{'file'} $config{'logfile'}! ($!)");
      close(LOGFILE);
   }
   chmod(0660, $config{'logfile'}) if (($fmode&0660)!=0660);
   chown($>, $mailgid, $config{'logfile'}) if ($fuid!=$>||$fgid!=$mailgid);
}

if ( $config{'forced_ssl_login'} &&	# check the forced use of SSL
     !($ENV{'HTTPS'}=~/on/i||$ENV{'SERVER_PORT'}==443) ) {
   my ($start_url, $refresh, $js);
   $start_url=$config{'start_url'};
   $start_url="https://$ENV{'HTTP_HOST'}$start_url" if ($start_url!~s!^https?://!https://!i);
   if ($ENV{'HTTP_USER_AGENT'}!~/MSIE.+Mac/) {
      # reload page with Refresh header only if not MSIE on Mac
      $refresh=qq|<meta http-equiv="refresh" content="5;URL=$start_url">|;
   } else {
      # reload page with java script if MSIE on Mac
      $js=qq|<script language="JavaScript">\n<!--\n|.
          qq|setTimeout("window.open('$start_url','_self')", 1*5000);\n|.
          qq|//-->\n</script>|;
   }
   print qq|Content-type: text/html\n\n|.
         qq|<html><head>$refresh</head><body>\n|.
         qq|Service is available over SSL only,<br>\n|.
         qq|you will be redirected to <a href="$start_url">SSL login</a> page in 5 seconds...\n|.
         qq|$js\n|.
         qq|</body></html>\n|; 
   exit 0;
}

if ( param('loginname') && param('password') ) {
   login();
} else {            # no action has been taken, display login page
   loginmenu();
}

# back to root if possible, required for setuid under persistent perl
$<=0; $>=0;
##################### END MAIN ########################

##################### LOGINMENU ######################
sub loginmenu {
   $logindomain=param('logindomain')||lc($ENV{'HTTP_HOST'});
   $logindomain=~s/:\d+$//;	# remove port number
   $logindomain=lc(safedomainname($logindomain));
   $logindomain=$config{'domainname_equiv'}{'map'}{$logindomain} if (defined($config{'domainname_equiv'}{'map'}{$logindomain}));
   if (!is_serverdomain_allowed($logindomain)) {
      openwebmailerror("Service is not available for domain  ' $logindomain '");
   }

   readconf(\%config, \%config_raw, "$config{'ow_sitesconfdir'}/$logindomain") if ( -f "$config{'ow_sitesconfdir'}/$logindomain");
   if ( $>!=0 &&	# setuid is required if spool is located in system dir
       ($config{'mailspooldir'} eq "/var/mail" || 
        $config{'mailspooldir'} eq "/var/spool/mail")) {
      print "Content-type: text/html\n\n'$0' must setuid to root"; exit 0;
   }

   %prefs = readprefs();
   %style = readstyle($prefs{'style'});
   readlang($prefs{'language'});

   my ($html, $temphtml);
   $html = readtemplate("login.template");
   $html = applystyle($html);

   $temphtml = startform(-action=>"$config{'ow_cgiurl'}/openwebmail.pl",
                         -name=>'login');
   if (defined(param('action'))) {
      $temphtml .= hidden("action", param('action'));
      $temphtml .= hidden("to", param('to')) if (defined(param('to')));
      $temphtml .= hidden("subject", param('subject')) if (defined(param('subject')));
   }
   $html =~ s/\@\@\@STARTFORM\@\@\@/$temphtml/;

   if (cookie("openwebmail-rememberme")) {
      $temphtml = textfield(-name=>'loginname',
                            -default=>cookie("openwebmail-loginname"),
                            -size=>'12',
                            -onChange=>'focuspwd()',
                            -override=>'1');
   } else {
      $temphtml = textfield(-name=>'loginname',
                            -default=>'' ,
                            -size=>'12',
                            -onChange=>'focuspwd()',
                            -override=>'1');
   }
   $html =~ s/\@\@\@LOGINNAMEFIELD\@\@\@/$temphtml/;

   $temphtml = password_field(-name=>'password',
                              -default=>'',
                              -size=>'12',
                              -onChange=>'focusloginbutton()',
                              -override=>'1');
   $html =~ s/\@\@\@PASSWORDFIELD\@\@\@/$temphtml/;

   $temphtml = checkbox(-name=>'rememberme',
                        -value=>'1',
                        -checked=>cookie("openwebmail-rememberme")||0,
                        -label=>'');
   $html =~ s/\@\@\@REMEMBERMECHECKBOX\@\@\@/$temphtml/;

   if ( $#{$config{'domainnames'}} >0 && $config{'enable_domainselectmenu'} ) {
      $temphtml = popup_menu(-name=>'logindomain',
                             -default=>$logindomain,
                             -values=>[@{$config{'domainselmenu_list'}}] );
      $html =~ s/\@\@\@DOMAINMENU\@\@\@/$temphtml/;
      $html =~ s/\@\@\@DOMAINSTART\@\@\@//;
      $html =~ s/\@\@\@DOMAINEND\@\@\@//;
   } else {
      $temphtml = hidden("logindomain", param('logindomain'));
      $html =~ s/\@\@\@DOMAINSTART\@\@\@/$temphtml<!--/;
      $html =~ s/\@\@\@DOMAINEND\@\@\@/-->/;
   }

   $temphtml = submit(-name =>"loginbutton",
		      -value=>"$lang_text{'login'}" );
   $html =~ s/\@\@\@LOGINBUTTON\@\@\@/$temphtml/;
   $temphtml = reset("$lang_text{'clear'}");
   $html =~ s/\@\@\@CLEARBUTTON\@\@\@/$temphtml/;
   $temphtml = end_form();
   $html =~ s/\@\@\@ENDFORM\@\@\@/$temphtml/;

   print htmlheader(), $html, htmlfooter(1);
}
################### END LOGINMENU ####################

####################### LOGIN ########################
sub login {
   $loginname=param('loginname');
   $default_logindomain=param('logindomain');

   ($logindomain, $loginuser)=login_name2domainuser($loginname, $default_logindomain);
   if (!is_serverdomain_allowed($logindomain)) {
      openwebmailerror("Service is not available for domain  ' $logindomain '");
   }

   readconf(\%config, \%config_raw, "$config{'ow_sitesconfdir'}/$logindomain") if ( -f "$config{'ow_sitesconfdir'}/$logindomain");
   if ( $>!=0 &&	# setuid is required if spool is located in system dir
       ($config{'mailspooldir'} eq "/var/mail" || 
        $config{'mailspooldir'} eq "/var/spool/mail")) {
      print "Content-type: text/html\n\n'$0' must setuid to root"; exit 0;
   }
   loadauth($config{'auth_module'});

   # create domain logfile
   if ( ($config{'logfile'} ne 'no') ) {
      my $mailgid=getgrnam('mail');
      my ($fmode, $fuid, $fgid) = (stat($config{'logfile'}))[2,4,5];
      if ( !($fmode & 0100000) ) {
         open (LOGFILE,">>$config{'logfile'}") or
            openwebmailerror("$lang_err{'couldnt_open'} $lang_text{'file'} $config{'logfile'}! ($!)");
         close(LOGFILE);
      }
      chmod(0660, $config{'logfile'}) if (($fmode&0660)!=0660);
      chown($>, $mailgid, $config{'logfile'}) if ($fuid!=$>||$fgid!=$mailgid);
   }

   # update virtusertable
   my $virtname=$config{'virtusertable'}; $virtname=~s!/!.!g; $virtname=~s/^\.+//;
   update_virtusertable("$config{'ow_etcdir'}/$virtname", $config{'virtusertable'});

   %prefs = readprefs();
   %style = readstyle($prefs{'style'});
   readlang($prefs{'language'});

   ($domain, $user, $userrealname, $uuid, $ugid, $homedir)
				=get_domain_user_userinfo($logindomain, $loginuser);
   if ($user eq "") {
      sleep $config{'loginerrordelay'};	# delayed response
      writelog("login error - no such user - loginname=$loginname ");

      # show 'pwd incorrect' instead of 'user not exist' for better security
      my $html = readtemplate("loginfailed.template");
      $html = applystyle($html);
      $html =~ s/\@\@\@ERRORMSG\@\@\@/$lang_err{'pwd_incorrect'}/;
      print htmlheader(), $html, htmlfooter(1);
      return;
   }
   if (! $config{'enable_rootlogin'}) {
      if ($user eq 'root' || $uuid==0) {
         sleep $config{'loginerrordelay'};	# delayed response
         writelog("login error - root login attempt");
         openwebmailerror ("$lang_err{'norootlogin'}");
      }
   }

   my $userconf="$config{'ow_usersconfdir'}/$user";
   $userconf="$config{'ow_usersconfdir'}/$domain/$user" if ($config{'auth_withdomain'});
   readconf(\%config, \%config_raw, "$userconf") if ( -f "$userconf");

   if ( !$config{'use_syshomedir'} ) {
      $homedir="$config{'ow_usersdir'}/$user";
      if ($config{'auth_withdomain'}) {
         my $domainhome="$config{'ow_usersdir'}/$domain";
         # mkdir domainhome so openwebmail.pl can create user homedir under this domainhome
         if (!-d $domainhome) {
            my $mailgid=getgrnam('mail');
            ($domainhome =~ /^(.+)$/) && ($domainhome = $1);	# untaint...
            mkdir($domainhome, 0750);
            openwebmailerror("Couldn't create domain homedir $domainhome") if (! -d $domainhome);
            chown($uuid, $mailgid, $domainhome);
         }
         $homedir = "$domainhome/$user";
      }
   }
   $folderdir = "$homedir/$config{'homedirfolderdirname'}";

   ($user =~ /^(.+)$/) && ($user = $1);		# untaint...
   ($uuid =~ /^(.+)$/) && ($uuid = $1);
   ($ugid =~ /^(.+)$/) && ($ugid = $1);
   ($homedir =~ /^(.+)$/) && ($homedir = $1);
   ($folderdir =~ /^(.+)$/) && ($folderdir = $1);


   # validate client ip
   my $clientip=get_clientip();
   if ($#{$config{'allowed_clientip'}}>=0) {
      my $allowed=0;
      foreach my $token (@{$config{'allowed_clientip'}}) {
         if (lc($token) eq 'all' || $clientip=~/^\Q$token\E/) {
            $allowed=1; last;
         } elsif (lc($token) eq 'none') {
            last;
         }
      }
      if (!$allowed) {
         openwebmailerror($lang_err{'disallowed_client'}." ( ip:$clientip )");
      }
   }
   # validate client domain
   if ($#{$config{'allowed_clientdomain'}}>=0) {
      my $clientdomain;
      my $allowed=0;
      foreach my $token (@{$config{'allowed_clientdomain'}}) {
         if (lc($token) eq 'all') {
            $allowed=1; last;
         } elsif (lc($token) eq 'none') {
            last;
         }
         $clientdomain=ip2hostname($clientip) if ($clientdomain eq "");
         if ($clientdomain=~/\Q$token\E$/ || # matched
             $clientdomain!~/\./) { 		# shortname in /etc/hosts
            $allowed=1; last;
         }
      }
      if (!$allowed) {
         openwebmailerror($lang_err{'disallowed_client'}." ( hotname:$clientdomain )");
      }
   }

   my ($errorcode, $errormsg);
   my $password = param('password') || '';
   if ($config{'auth_withdomain'}) {
      ($errorcode, $errormsg)=check_userpassword(\%config, "$user\@$domain", $password);
   } else {
      ($errorcode, $errormsg)=check_userpassword(\%config, $user, $password);
   }
   if ( $errorcode==0 ) {
      # search old alive session and deletes old expired sessionids
      $thissession = search_and_cleanoldsessions(cookie("$user-sessionid"), $uuid);
      if ($thissession eq "") {	# name the new sessionid
         $thissession = $loginname."*".$default_logindomain."-session-".rand(); 
      }
      $thissession =~ s!\.\.+!!g;  # remove ..
      if ($thissession =~ /^([\w\.\-\%\@]+\*[\w\.\-]*\-session\-0\.\d+)$/) {
         $thissession = $1; # untaint
      } else {
         openwebmailerror("Session ID $thissession $lang_err{'has_illegal_chars'}");
      }
      writelog("login - $thissession");

      if (!$config{'use_syshomedir'} && $config{'auth_withdomain'} &&
          !-d "$homedir" && -d "$config{'ow_usersdir'}/$user\@$domain") {
         # rename old homedir 
         my $olddir="$config{'ow_usersdir'}/$user\@$domain";
         ($olddir =~ /^(.+)$/) && ($olddir = $1);
         rename($olddir, $homedir) or
            openwebmailerror("$lang_text{'rename'} $olddir to $homedir $lang_text{'failed'} ($!)");
         writelog("release upgrade - rename $olddir to $homedir by 20030323");
      }

      # get user release date
      my $user_releasedate;
      my $releasedate_file="$folderdir/.release.date";
      $releasedate_file="$homedir/.release.date" if (! -f $releasedate_file);
      if (open(D, $releasedate_file)) {
         $user_releasedate=<D>; chomp($user_releasedate); close(D);
      }

      # change the owner of files under ow_usersdir/username from root to $uuid
      if ($user_releasedate lt "20030312") {
         if( !$config{'use_syshomedir'} && -d $homedir) {
            my $chown_bin;
            foreach ("/bin/chown", "/usr/bin/chown", "/sbin/chown", "/usr/sbin/chown") {
               $chown_bin=$_ if (-x $_);
            }
            system($chown_bin, '-R', $uuid, $homedir);
            writelog("release upgrade - chown -R $uuid $homedir/* by 20030312");
         }
      }

      # create the user's home directory if necessary.
      # this must be done before changing to the user's uid.
      if (($config{'create_syshomedir'} || !$config{'use_syshomedir'}) 
          && !-d $homedir ) {
         if (mkdir ("$homedir", oct(700)) && chown($uuid, $ugid, $homedir)) {
            writelog("create homedir - $homedir, uid=$uuid, gid=$ugid");
         } else {
            openwebmailerror("$lang_err{'cant_create_dir'} $homedir ($!)");
         }
      }

      umask(0077);
      if ( $>==0 ) {			# switch to uuid:mailgid if script is setuid root.
         my $mailgid=getgrnam('mail');	# for better compatibility with other mail progs
         set_euid_egids($uuid, $mailgid, $ugid); 
         if ( $) != $mailgid) {	# group mail doesn't exist?
            openwebmailerror("Set effective gid to mail($mailgid) failed!");
         }
      }

      # create folderdir if it doesn't exist
      if (! -d "$folderdir" ) {
         if (mkdir ("$folderdir", oct(700))) {
            writelog("create folderdir - $folderdir, euid=$>, egid=$)");
         } else {
            openwebmailerror("$lang_err{'cant_create_dir'} $folderdir ($!)");
         }

         # mv folders from $homedir to $folderdir($homedir/mail/) for old ow_usersdir
         if ($user_releasedate lt "20021218") {
            if ( !$config{'use_syshomedir'} &&
                 -f "$homedir/.openwebmailrc" && !-f "$folderdir/.openwebmailrc") {
               opendir (HOMEDIR, $homedir);
               my @files=readdir(HOMEDIR);
               closedir(HOMEDIR);
               foreach my $file (@files) {
                  next if ($file eq "." || $file eq ".." || $file eq $config{'homedirfolderdirname'});
                  ($file =~ /^(.+)$/) && ($file = $1);	# untaint ...
                  rename("$homedir/$file", "$folderdir/$file");
               }
               writelog("release upgrade - mv $homedir/* to $folderdir/* by 20021218");
            }
         }
      }

      loadstorage($config{'storage_module'});
      # create system spool file /var/mail/xxxx
      my ($spoolfile, $headerdb)=get_folderfile_headerdb($user, 'INBOX');
      if ( ! &storage_folder_exist($spoolfile) ) {
         ($spoolfile =~ /^(.+)$/) && ($spoolfile = $1); # untaint ...
		 &storage_create_folder($spoolfile);
         chown($uuid, $ugid, $spoolfile);
      }

      # create session file
      my $sessioncookie_value;
      if ( -f "$config{'ow_sessionsdir'}/$thissession" ) { # continue an old session?
         $sessioncookie_value = cookie("$user-sessionid");
      } else {						       # a brand new sesion?
         $sessioncookie_value = crypt(rand(),'OW');
      }
      open (SESSION, "> $config{'ow_sessionsdir'}/$thissession") or # create sessionid
         openwebmailerror("$lang_err{'couldnt_open'} $config{'ow_sessionsdir'}/$thissession! ($!)");
      print SESSION $sessioncookie_value, "\n";
      print SESSION get_clientip(), "\n";
      print SESSION join("\@\@\@", $domain, $user, $userrealname, $uuid, $ugid, $homedir), "\n";
      close (SESSION);
      writehistory("login - $thissession");

      # symbolic link ~/mbox to ~/mail/saved-messages
      if ( $config{'symboliclink_mbox'} &&
           ((lstat("$homedir/mbox"))[2] & 07770000) eq 0100000) { # regular file
         if (folderfilelock("$folderdir/saved-messages", LOCK_EX|LOCK_NB)) {
            writelog("symlink mbox - $homedir/mbox -> $folderdir/saved-messages");

            rename("$homedir/mbox", "$homedir/mbox.tmp.$$");
            symlink("$folderdir/saved-messages", "$homedir/mbox");

            open(T,"$homedir/mbox.tmp.$$");
            open(F,">>$folderdir/saved-messages");
            while(<T>) { print F $_; }
            close(F);
            close(T);

            unlink("$homedir/mbox.tmp.$$");
            folderfilelock("$folderdir/saved-messages", LOCK_UN);
         }
      }

      # check if releaseupgrade() is required
      if ($user_releasedate ne $config{'releasedate'}) {
         releaseupgrade($folderdir, $user_releasedate);
         open(D, ">$folderdir/.release.date");
         print D $config{'releasedate'};
         close(D);
      }

      # create authpop3 book if auth_pop3.pl  & getmail_from_pop3_authserver is yes
      if ($config{'auth_module'} eq 'auth_pop3.pl') {
         my $authpop3book="$folderdir/.authpop3.book";
         ($authpop3book =~ /^(.+)$/) && ($authpop3book = $1);  # untaint ...

         if ($config{'getmail_from_pop3_authserver'}) {
            my ($pop3host, $pop3user, $pop3pass, $pop3lastid, $pop3del, $enable);
            my $login=$user;
            $login .= "\@$domain" if ($config{'auth_withdomain'});

            if ( -f "$authpop3book") {
               open(F, "$authpop3book");
               $_=<F>; chomp;
               ($pop3host,$pop3user,$pop3pass,$pop3lastid,$pop3del,$enable)=split(/\@\@\@/, $_);
               close(F);
            }

            if ($pop3host ne $config{'pop3_authserver'} ||
                $pop3user ne $login ||
                $pop3pass ne $password) {
               if ($pop3host ne $config{'pop3_authserver'} || $pop3user ne $login) {
                  $pop3lastid="none";
                  $pop3del=$config{'delpop3mail_by_default'};
                  $enable=1;
               }
               open(F, ">$authpop3book");
               print F "$config{'pop3_authserver'}\@\@\@$login\@\@\@$password\@\@\@$pop3lastid\@\@\@$pop3del\@\@\@$enable";
               close(F);
            }
         } else {
            unlink("$authpop3book");
         }
      }

      # set cookie in header and redirect page to openwebmail-main
      my $action=param('action');
      my $url;
      if ( ! -f "$folderdir/.openwebmailrc" ) {
         $url="$config{'ow_cgiurl'}/openwebmail-prefs.pl?sessionid=$thissession&action=userfirsttime";
      } elsif ( $action eq 'composemessage' ) {
         my $to=param('to'); 
         $to =~ s!^mailto\:!!; # IE passes mailto: with mailaddr to mail client
         my $subject=param('subject');
         $url="$config{'ow_cgiurl'}/openwebmail-send.pl?sessionid=$thissession&action=composemessage&to=$to&subject=$subject";
      } elsif ( $action eq 'calyear' || $action eq 'calmonth' ||
                $action eq 'calweek' || $action eq 'calday' ) {
         $url="$config{'ow_cgiurl'}/openwebmail-cal.pl?sessionid=$thissession&action=$action";
      } elsif ( $action eq 'showdir' ) {
         $url="$config{'ow_cgiurl'}/openwebmail-webdisk.pl?sessionid=$thissession&action=$action";
      } else {
         $url="$config{'ow_cgiurl'}/openwebmail-main.pl?sessionid=$thissession&action=listmessages_afterlogin";
      }

      if ( !$config{'stay_ssl_afterlogin'} &&	# leave SSL
           ($ENV{'HTTPS'}=~/on/i || $ENV{'SERVER_PORT'}==443) ) {
         $url="http://$ENV{'HTTP_HOST'}$url" if ($url!~s!^https?://!http://!i);
      }

      my @headers=();
      push(@headers, -pragma=>'no-cache');

      # cookie for openwebmail to verify session, expired if browser closed
      my $cookie1 = cookie( -name  => "$user-sessionid",
                            -value => "$sessioncookie_value",
                            -path  => '/');
      # cookie for other ap to find openwebmail loginname, expired until 1 month later
      my $cookie2 = cookie( -name  => "openwebmail-loginname",
                            -value => "$loginname",
                            -path  => '/',
                            -expires => "+1M" );
      # cookie for remember loginname switch, expired until 1 month later
      my $cookie3 = cookie( -name  => "openwebmail-rememberme",
                            -value => param('rememberme')||'',
                            -path  => '/',
                            -expires => "+1M" );
      # cookie for ssl session, expired if not same session
      my $cookie4 = cookie( -name  => "openwebmail-ssl",
                            -value => ($ENV{'HTTPS'}=~/on/i ||
                                       $ENV{'SERVER_PORT'}==443 ||
                                       0),
                            -path  => '/');

      push(@headers, -cookie=>[$cookie1, $cookie2, $cookie3, $cookie4]);
      push(@headers, -charset=>$prefs{'charset'}) if ($CGI::VERSION>=2.57);
      print header(@headers);

      my ($refresh, $js)=('','');;
      if ($ENV{'HTTP_USER_AGENT'}!~/MSIE.+Mac/) {
         # reload page with Refresh header only if not MSIE on Mac
         $refresh=qq|<meta http-equiv="refresh" content="0;URL=$url">|;
      } else {
         # reload page with java script if MSIE on Mac
         $js=qq|<script language="JavaScript">\n<!--\n|.
             qq|setTimeout("window.open('$url','_self')", 1*1000);\n|.
             qq|//-->\n</script>|;
      }
      # display copyright. Don't touch it, please.
      my $repeatstr=($prefs{'bgrepeat'})?'repeat':'no-repeat';
      print	qq|<html>\n|,
		qq|<head><title>Copyright</title>$refresh</head>\n|,
		qq|<body bgcolor="#ffffff" background="$prefs{'bgurl'}">\n|,
		qq|<style type="text/css"><!--\n|,
		qq|body { background-image: url($prefs{'bgurl'}); background-repeat: $repeatstr; }\n|,
		qq|--></style>\n|,
                qq|<center><br><br><br>\n|,
                qq|<a href="$url" title="click to next page..." style="text-decoration: none">|,
		qq|<font color="#888888"> &nbsp; Loading . . .</font></a>\n|,
		qq|<br><br><br>\n\n|.
                qq|<a href="http://openwebmail.org/" title="click to home of $config{'name'}" style="text-decoration: none">\n|,
		qq|<font color="#cccccc" face="arial,helvetica,sans-serif" size=-1>\n|,
                qq|$config{'name'} $config{'version'} $config{'releasedate'}<br><br>\n|,
		qq|Copyright (C) 2001-2003<br>\n|,
		qq|Chung-Kie Tung, Nai-Jung Kuo, Chao-Chiu Wang, Emir Litric, Thomas Chung, Dattola Filippo, Bernd Bass<br><br>\n|,
		qq|Copyright (C) 2000<br>\n|,
		qq|Ernie Miller  (original GPL project: Neomail)<br><br>\n|,
		qq|</font></a>\n\n|,
                qq|<a href="http://openwebmail.org/openwebmail/download/doc/copyright.txt" title="click to see GPL version 2 licence" style="text-decoration: none">\n|,
		qq|<font color="#cccccc" face="arial,helvetica,sans-serif" size=-1>\n|,
		qq|This program is free software; you can redistribute it and/or modify<br>\n|,
		qq|it under the terms of the version 2 of GNU General Public License<br>\n|,
		qq|as published by the Free Software Foundation<br><br>\n|,
		qq|This program is distributed in the hope that it will be useful,<br>\n|,
		qq|but WITHOUT ANY WARRANTY; without even the implied warranty of<br>\n|,
		qq|MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.<br>\n|,
		qq|See the GNU General Public License for more details.<br><br>\n|,
		qq|Removal or change of this copyright is prohibited.\n|,
		qq|</font></a>\n|,
                qq|$js\n|,
                qq|</center></body></html>\n|;

   } else { # Password is INCORRECT
      writelog("login error - $config{'auth_module'}, ret $errorcode, $errormsg");
      umask(0077);
      if ( $>==0 ) {	# switch to uuid:mailgid if script is setuid root.
         my $mailgid=getgrnam('mail');
         set_euid_egids($uuid, $mailgid, $ugid);
      }
      if ( -d $folderdir) {
         if ( ! -f "$folderdir/.history.log" ) {
            open(HISTORYLOG, ">>$folderdir/.history.log");
            close(HISTORYLOG);
            chown($uuid, $ugid, "$folderdir/.history.log");
         }
         writehistory("login error - $config{'auth_module'}, ret $errorcode, $errormsg");
      }

      my $html = readtemplate("loginfailed.template");
      $html = applystyle($html);

      my $webmsg;
      if ($errorcode==-1) {
         $webmsg=$lang_err{'func_notsupported'};
      } elsif ($errorcode==-2) {
         $webmsg=$lang_err{'param_fmterr'};
      } elsif ($errorcode==-3) {
         $webmsg=$lang_err{'auth_syserr'};
      } elsif ($errorcode==-4) {
         $webmsg=$lang_err{'pwd_incorrect'};
      } else {
         $webmsg="Unknow error code $errorcode";
      }
      $html =~ s/\@\@\@ERRORMSG\@\@\@/$webmsg/;

      sleep $config{'loginerrordelay'};	# delayed response
      print htmlheader(), $html, htmlfooter(1);
   }
}

sub ip2hostname {
   my $ip=$_[0];
   my $hostname;
   eval {
      local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
      alarm 10; # timeout 10sec
      $hostname=gethostbyaddr(inet_aton($ip),AF_INET);
      alarm 0;
   };
   return($ip) if ($@);	# eval error, it means timeout
   return($hostname);
}
#################### END LOGIN #####################

############### IS_SERVERDOMAIN_ALLOWED ###################
sub is_serverdomain_allowed {
   my $domain=$_[0];
   if ($#{$config{'allowed_serverdomain'}}>=0) {
      foreach my $token (@{$config{'allowed_serverdomain'}}) {
         if (lc($token) eq 'all' || lc($domain) eq lc($token)) {
            return 1;
         } elsif (lc($token) eq 'none') {
            return 0;
         }
      }
      return 0;
   } else {
      return 1;
   }
}
############### END IS_SERVERDOMAIN_ALLOWED ###################

################ SEARCH_AND_CLEANOLDSESSIONS ##################
# delete expired session files and
# try to find old session that is still valid for the same user cookie
sub search_and_cleanoldsessions {
   my ($oldcookie, $owner_uid)=@_;
   my $oldsessionid="";
   my ($sessionid, $modifyage);
   my @delfiles;

   opendir (SESSIONSDIR, "$config{'ow_sessionsdir'}") or
      openwebmailerror("$lang_err{'couldnt_open'} $config{'ow_sessionsdir'}! ($!)");
   my $t=time();
   while (defined($sessionid = readdir(SESSIONSDIR))) {
      if ($sessionid =~ /^(.+\-session\-0.*)$/) {
         $sessionid = $1;
         $modifyage = $t-(stat("$config{'ow_sessionsdir'}/$sessionid"))[9];

         $sessionid =~ /^([\w\.\-\%\@]+)\*([\w\.\-]*)\-session\-(0\.\d+)$/;
         my ($sess_loginname, $sess_default_logindomain)=($1, $2); # param from sessionid

         if ($loginname eq $sess_loginname && 
             $default_logindomain eq $sess_default_logindomain) { 
            # remove user old session if timeout
            if ( $modifyage > $prefs{'sessiontimeout'}*60 ) {
               writelog("session cleanup - $sessionid");
               push(@delfiles, "$config{'ow_sessionsdir'}/$sessionid");
            } else {
               my ($cookie, $ip, $userinfo)=sessioninfo($sessionid);
               if ($oldcookie && $cookie eq $oldcookie && $ip eq get_clientip() && 
                   (stat("$config{'ow_sessionsdir'}/$sessionid"))[4] == $owner_uid ) {
                  $oldsessionid=$sessionid;
               } elsif (!$config{'session_multilogin'}) { # remove old session of this user
                  writelog("session cleanup - $sessionid");
                  push(@delfiles, "$config{'ow_sessionsdir'}/$sessionid");
               }
            }
         } else {	# remove old session of other user if more than 1 day
            if ( $modifyage > 86400 ) {
               writelog("session cleanup - $sessionid");
               push(@delfiles, "$config{'ow_sessionsdir'}/$sessionid");
            }
         }
      }
   }
   closedir (SESSIONSDIR);

   unlink(@delfiles) if ($#delfiles>=0);
   return($oldsessionid);
}
############## END SEARCH_AND_CLEANOLDSESSIONS ################

#################### RELEASEUPGRADE ####################
# convert file format from old release for backward compatibility
sub releaseupgrade {
   my ($folderdir, $user_releasedate)=@_;
   my $content;
   my ($_OFFSET, $_FROM, $_TO, $_DATE, $_SUBJECT, $_CONTENT_TYPE, $_STATUS, $_SIZE, $_REFERENCES, $_CHARSET)
       =(0,1,2,3,4,5,6,7,8,9);

   if ( $user_releasedate lt "20011101" ) {
      if ( -f "$folderdir/.filter.book" ) {
         $content="";
         filelock("$folderdir/.filter.book", LOCK_EX) or
            openwebmailerror("$lang_err{'couldnt_lock'} $folderdir/.filter.book");
         open(F, "$folderdir/.filter.book");
         while (<F>) {
            chomp;
            my ($priority, $rules, $include, $text, $op, $destination, $enable) = split(/\@\@\@/);
            if ( $enable eq '') {
               ($priority, $rules, $include, $text, $destination, $enable) = split(/\@\@\@/);
               $op='move';
            }
            $rules='textcontent' if ($rules eq 'body');
            $content.="$priority\@\@\@$rules\@\@\@$include\@\@\@$text\@\@\@$op\@\@\@$destination\@\@\@$enable\n";
         }
         close(F);
         if ($content ne "") {
            writehistory("release upgrade - $folderdir/.filter.book by 20011101");
            writelog("release upgrade - $folderdir/.filter.book by 20011101");
            open(F, ">$folderdir/.filter.book");
            print F $content;
            close(F);
         }
         filelock("$folderdir/.filter.book", LOCK_UN);
      }

      if ( -f "$folderdir/.pop3.book" ) {
         $content="";
         filelock("$folderdir/.pop3.book", LOCK_EX) or
            openwebmailerror("$lang_err{'couldnt_lock'} $folderdir/.pop3.book");
         open(F, "$folderdir/.pop3.book");
         while (<F>) {
            chomp;
            my @a=split(/:/);
            my ($pop3host, $pop3user, $pop3passwd, $pop3lastid, $pop3del, $enable);
            if ($#a==4) {
               ($pop3host, $pop3user, $pop3passwd, $pop3del, $pop3lastid) = @a;
               $enable=1;
            } elsif ($a[3]=~/\@/) {
               my $pop3email;
               ($pop3host, $pop3user, $pop3passwd, $pop3email, $pop3del, $pop3lastid) = @a;
               $enable=1;
            } else {
               ($pop3host, $pop3user, $pop3passwd, $pop3lastid, $pop3del, $enable) =@a;
            }
            $content.="$pop3host\@\@\@$pop3user\@\@\@$pop3passwd\@\@\@$pop3lastid\@\@\@$pop3del\@\@\@$enable\n";
         }
         close(F);
         if ($content ne "") {
            writehistory("release upgrade - $folderdir/.pop3.book by 20011101");
            writelog("release upgrade - $folderdir/.pop3.book by 20011101");
            open(F, ">$folderdir/.pop3.book");
            print F $content;
            close(F);
         }
         filelock("$folderdir/.pop3.book", LOCK_UN);
      }
   }

   if ( $user_releasedate lt "20011117" ) {
      for my $book (".from.book", ".address.book", ".pop3.book") {
         if ( -f "$folderdir/$book" ) {
            $content="";
            filelock("$folderdir/$book", LOCK_EX) or
               openwebmailerror("$lang_err{'couldnt_lock'} $folderdir/$book");
            open(F, "$folderdir/$book");
            while (<F>) {
               last if (/\@\@\@/);
               s/:/\@\@\@/g;
               $content.=$_
            }
            close(F);
            if ($content ne "") {
               writehistory("release upgrade - $folderdir/$book by 20011117");
               writelog("release upgrade - $folderdir/$book by 20011117");
               open(F, ">$folderdir/$book");
               print F $content;
               close(F);
            }
            filelock("$folderdir/$book", LOCK_UN);
         }
      }
   }

   if ( $user_releasedate lt "20011216" ) {
      my @cachefiles;
      my $file;
      opendir (FOLDERDIR, "$folderdir") or
         openwebmailerror("$lang_err{'couldnt_open'} $folderdir ($!)");
      while (defined($file = readdir(FOLDERDIR))) {
         if ($file=~/^(\..+\.cache)$/) {
            $file="$folderdir/$1";
            push(@cachefiles, $file);
         }
      }
      closedir (FOLDERDIR);
      if ($#cachefiles>=0) {
         writehistory("release upgrade - $folderdir/*.cache by 20011216");
         writelog("release upgrade - $folderdir/*.cache by 20011216");
         # remove old .cache since its format is not compatible with new one
         unlink(@cachefiles);
      }
   }

   if ( $user_releasedate lt "20020108.02" ) {
      my (@validfolders, $folderusage);
      getfolders(\@validfolders, \$folderusage);

      foreach my $foldername (@validfolders) {
         my ($folderfile, $headerdb)=get_folderfile_headerdb($user, $foldername);
         my (%HDB, @messageids, @attr);
         next if ( ! -f "$headerdb$config{'dbm_ext'}" || -z "$headerdb$config{'dbm_ext'}" );

         folderfilelock($folderfile, LOCK_SH) or
            openwebmailerror("$lang_err{'couldnt_locksh'} $folderfile");
         if (!$config{'dbmopen_haslock'}) {
            filelock("$headerdb$config{'dbm_ext'}", LOCK_EX) or
               openwebmailerror("$lang_err{'couldnt_lock'} $headerdb$config{'dbm_ext'}");
         }
         dbmopen (%HDB, "$headerdb$config{'dbmopen_ext'}", 0600);

         if ( $HDB{'METAINFO'} eq metainfo($folderfile) ) { # upgrade only if hdb is uptodate
            @messageids=keys %HDB;
            foreach my $id (@messageids) {
               next if ( $id eq 'METAINFO'
                || $id eq 'NEWMESSAGES'
                || $id eq 'INTERNALMESSAGES'
                || $id eq 'ALLMESSAGES'
                || $id eq "" );

               @attr=split( /@@@/, $HDB{$id} );

               next if ( ($attr[$_CONTENT_TYPE] eq '' ||
                          $attr[$_CONTENT_TYPE] eq 'N/A' ||
                          $attr[$_CONTENT_TYPE] =~ /^text/i)
                       && $attr[$_SIZE]<4096 );

               next if ($attr[$_STATUS] =~ /T/i);

               if ($attr[$_SIZE]>65536) { # assume message > 64k has attachments
                  $attr[$_STATUS].="T";
               } else {
                  my $buff=&storage_get_message_block_offset($attr[$_OFFSET],$attr[$_SIZE],$folderfile);
                  if ( $buff =~ /\ncontent\-type:.*;\s+name\s*=(.+?)\n/ims ||
                       $buff =~ /\n\s+name\s*=(.+?)\n/ims ||
                       $buff =~ /\ncontent\-disposition:.*;\s+filename\s*=(.+?)\n/ims ||
                       $buff =~ /\n\s+filename\s*=(.+?)\n/ims ||
                       $buff =~ /\nbegin [0-7][0-7][0-7][0-7]? [^\n\r]+\n/ims ) {
                     my $misc=$1;
                     if ($misc !~ /[\<\>]/ && $misc !~ /type=/i) {
                        $attr[$_STATUS].="T";
                     } else {
                        next;
                     }
                  } else {
                     next;
                  }
               }
               $HDB{$id}=join('@@@', @attr);
            }
         }
         dbmclose(%HDB);
         filelock("$headerdb$config{'dbm_ext'}", LOCK_UN) if (!$config{'dbmopen_haslock'});
         folderfilelock($folderfile, LOCK_UN);
      }
      writehistory("release upgrade - $folderdir/* by 20020108.02");
      writelog("release upgrade - $folderdir/* by 20020108.02");
   }

   if ( $user_releasedate lt "20020108.02" ) {
      my (@validfolders, $folderusage);
      getfolders(\@validfolders, \$folderusage);

      foreach my $foldername (@validfolders) {
         my ($folderfile, $headerdb)=get_folderfile_headerdb($user, $foldername);
         my (%HDB, @messageids, @attr);
         next if ( ! -f "$headerdb$config{'dbm_ext'}" || -z "$headerdb$config{'dbm_ext'}" );

         if (!$config{'dbmopen_haslock'}) {
            filelock("$headerdb$config{'dbm_ext'}", LOCK_EX) or
               openwebmailerror("$lang_err{'couldnt_lock'} $headerdb$config{'dbm_ext'}");
         }
         dbmopen (%HDB, "$headerdb$config{'dbmopen_ext'}", 0600);

         @messageids=keys %HDB;
         foreach my $id (@messageids) {
            next if ( $id eq 'METAINFO'
             || $id eq 'NEWMESSAGES'
             || $id eq 'INTERNALMESSAGES'
             || $id eq 'ALLMESSAGES'
             || $id eq "" );

            @attr=split( /@@@/, $HDB{$id} );
            next if ( $attr[$_DATE] !~ m!(\d+)/(\d+)/(\d\d+)\s+(\d+):(\d+):(\d+)! );
            my @d = ($1, $2, $3, $4, $5, $6);
            if ($d[2]<50) {
               $d[2]+=2000;
            } elsif ($d[2]<=1900) {
               $d[2]+=1900;
            }
            $attr[$_DATE]=sprintf("%4d%02d%02d%02d%02d%02d",
					$d[2],$d[0],$d[1], $d[3],$d[4],$d[5]);
            $HDB{$id}=join('@@@', @attr);
         }
         dbmclose(%HDB);
         filelock("$headerdb$config{'dbm_ext'}", LOCK_UN) if (!$config{'dbmopen_haslock'});

         my $cachefile="$headerdb.cache";
         ($cachefile =~ /^(.+)$/) && ($cachefile = $1);  # untaint ...
         unlink($cachefile); # remove cache possiblely for old dbm
      }
      writehistory("release upgrade - $folderdir/.*$config{'dbm_ext'} by 20020108.02");
      writelog("release upgrade - $folderdir/.*$config{'dbm_ext'} by 20020108.02");
   }

   if ( $user_releasedate lt "20020601" ) {
      my $timeoffset=gettimeoffset();
      my (@validfolders, $folderusage);
      getfolders(\@validfolders, \$folderusage);

      foreach my $foldername (@validfolders) {
         my ($folderfile, $headerdb)=get_folderfile_headerdb($user, $foldername);
         my (%HDB, @messageids, @attr);
         next if ( ! -f "$headerdb$config{'dbm_ext'}" || -z "$headerdb$config{'dbm_ext'}" );

         folderfilelock($folderfile, LOCK_SH) or
            openwebmailerror("$lang_err{'couldnt_locksh'} $folderfile");
         if (!$config{'dbmopen_haslock'}) {
            filelock("$headerdb$config{'dbm_ext'}", LOCK_EX) or
               openwebmailerror("$lang_err{'couldnt_lock'} $headerdb$config{'dbm_ext'}");
         }
         dbmopen (%HDB, "$headerdb$config{'dbmopen_ext'}", 0600);

         @messageids=keys %HDB;
         foreach my $id (@messageids) {
            next if ( $id eq 'METAINFO'
                   || $id eq 'NEWMESSAGES'
                   || $id eq 'INTERNALMESSAGES'
                   || $id eq 'ALLMESSAGES'
                   || $id eq "" );
            my ($buff, $delimiter, $datefield, $dateserial);
            @attr=split( /@@@/, $HDB{$id} );
			$buff=&storage_get_message_header_offset($attr[$_OFFSET],$folderfile);
            if ( $buff =~ /^From (.+?)\n/ims) {
               $delimiter=$1;
               if ( $buff =~ /\nDate: (.+?)\n/ims ) {
                  $datefield=$1;
               }
               my $dateserial=datefield2dateserial($datefield);
               my $deliserial=delimiter2dateserial($delimiter, $config{'deliver_use_GMT'}) ||
                              gmtime2dateserial();
               if ($dateserial eq "") {
                  $dateserial=$deliserial; 
               } elsif ($deliserial ne "") {
                   my $t=dateserial2gmtime($deliserial)-dateserial2gmtime($dateserial); 
                   if ($t>86400*7 || $t<-86400) { # msg transmission time
                      # use deliverytime in case sender host may have wrong time configuration
                      $dateserial=$deliserial; 
                   }
               }
               $attr[$_DATE]=$dateserial;
            } else {	# local -> gm
               $attr[$_DATE]=gmtime2dateserial(
			dateserial2gmtime($attr[$_DATE])-timeoffset2seconds($timeoffset));
            }
            $HDB{$id}=join('@@@', @attr);
         }
         dbmclose(%HDB);
         filelock("$headerdb$config{'dbm_ext'}", LOCK_UN) if (!$config{'dbmopen_haslock'});
         folderfilelock($folderfile, LOCK_UN);
      }
      writehistory("release upgrade - $folderdir/* by 20020601");
      writelog("release upgrade - $folderdir/* by 20020601");
   }

   if ( $user_releasedate lt "20021111" ) {
      my (@validfolders, $folderusage);
      getfolders(\@validfolders, \$folderusage);

      foreach my $foldername (@validfolders) {
         my ($folderfile, $headerdb)=get_folderfile_headerdb($user, $foldername);
         my (%HDB, @messageids, @attr);
         next if ( ! -f "$headerdb$config{'dbm_ext'}" || -z "$headerdb$config{'dbm_ext'}" );

         if (!$config{'dbmopen_haslock'}) {
            filelock("$headerdb$config{'dbm_ext'}", LOCK_EX) or
               openwebmailerror("$lang_err{'couldnt_lock'} $headerdb$config{'dbm_ext'}");
         }
         dbmopen (%HDB, "$headerdb$config{'dbmopen_ext'}", 0600);

         @messageids=keys %HDB;
         foreach my $id (@messageids) {
            next if ( $id eq 'METAINFO'
             || $id eq 'NEWMESSAGES'
             || $id eq 'INTERNALMESSAGES'
             || $id eq 'ALLMESSAGES'
             || $id eq "" );
            @attr=split( /@@@/, $HDB{$id} );
            if ( $attr[$_CHARSET] eq "" &&
                 $attr[$_CONTENT_TYPE]=~/charset="?([^\s"';]*)"?\s?/i) {
               $attr[$_CHARSET]=$1;
               $HDB{$id}=join('@@@', @attr);
            }
         }
         dbmclose(%HDB);
         filelock("$headerdb$config{'dbm_ext'}", LOCK_UN) if (!$config{'dbmopen_haslock'});
      }
      writehistory("release upgrade - $folderdir/.*$config{'dbm_ext'} by 20021111.02");
      writelog("release upgrade - $folderdir/.*$config{'dbm_ext'} by 20021111.02");
   }

   if ( $user_releasedate lt "20021201" ) {
      if ( -f "$folderdir/.calendar.book" ) {
         my $content='';
         filelock("$folderdir/.calendar.book", LOCK_EX) or
            openwebmailerror("$lang_err{'couldnt_lock'} $folderdir/.calendar.book");
         open(F, "$folderdir/.calendar.book");
         while (<F>) {
            next if (/^#/);
            chomp;
            # fields: idate, starthourmin, endhourmin, string, link, email, color
            my @a=split(/\@\@\@/, $_);
            if ($#a==7) {
               $content.=join('@@@', @a);
            } elsif ($#a==6) {
               $content.=join('@@@', @a, 'none');
            } elsif ($#a==5) {
               $content.=join('@@@', @a, ,'0', 'none');
            } elsif ($#a<5) {
               $content.=join('@@@', $a[0], $a[1], $a[2], '0', $a[3], $a[4], '0', 'none');
            }
            $content.="\n";
         }
         close(F);
         if ($content ne "") {
            writehistory("release upgrade - $folderdir/.calendar.book by 20021201");
            writelog("release upgrade - $folderdir/.calendar.book by 20021201");
            open(F, ">$folderdir/.calendar.book");
            print F $content;
            close(F);
         }
         filelock("$folderdir/.calendar.book", LOCK_UN);
      }
   }

   my $saverc=0;
   if (-f "$folderdir/.openwebmailrc") {
      %prefs = readprefs();				# load user old prefs + sys defaults
      $saverc=1 if ( $user_releasedate lt "20030408" );	# rc upgrade
   } else {
      $saverc=1 if ($config{'auto_createrc'});		# rc auto create
   }
   if ($saverc) {
      open (RC, ">$folderdir/.openwebmailrc") or 
         openwebmailerror("$lang_err{'couldnt_open'} $folderdir/.openwebmailrc! ($!)");
      foreach my $key (@openwebmailrcitem) {
         print RC "$key=$prefs{$key}\n";
      }
      close (RC) or openwebmailerror("$lang_err{'couldnt_close'} $folderdir/.openwebmailrc!");
   }

   return;
}
#################### END RELEASEUPGRADE ####################
