#!/usr/bin/perl -T
$versions{'manager.cgi'} = '06.6.00.0005';

#######################################################################
#                   Manager Program for AgoraCart
#######################################################################

# Route 66 - Legacy Compatibility Version
#######################################################################
#
# AgoraCart and all associated files, except where noted, are
# Copyright 2001 to Present jointly by K-Factor Technologies, Inc.
# and by C E Mayo (aka Mister Ed) at AgoraCart.com & K-Factor.net
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This copyright notice may not be removed or altered in any way.
#
#######################################################################

$ENV{'PATH'} = '/bin:/usr/bin';  # set minimal path
$ENV{'IFS'}  = '';
delete @ENV{qw/CDPATH ENV BASH_ENV/};

# Loads perl modules relative to manager.cgi location.
BEGIN {  unshift( @INC, './system66/perl_modules' ); }
use lib '../system66/perl_modules';

# cPanel only - loads perl modules local to the users account.
eval('use cPanelUserConfig;');

use CGI::Simple::Standard qw(:cgi-lib :core :misc :cookie -autoload); # inside ../system66/perl_modules
use LWP::UserAgent;
use LWP::Simple qw(!head);  #getstore or get
use File::Copy;
use Encode;
use AgoraCart::Base64;

%store_settings;
%in;
$scm_orderStatusDropList = q{};
$ip_file = q{};
$mc_session_id = q{};
$mc_login_err = q{};
$mc_no_login = q{};
$mgr_loaded_libs = ''; # for file/dir list building for dev purposes
$imageURLthingy = 'images';
$manager_program_running = 'yes';
$mgrdirname = 'manager';
$mgrdir = "./$mgrdirname";
$mgrlibdir = "./$mgrdirname/ext_libs";
$mgrcoredir = "./$mgrdirname/core";
$mgrconfdir = "./$mgrdirname/config";
$mgr_user_settings_path = './user_config66/cart/agora_user_lib.pl';
$mgr_setup_path = './system66/library/agora_setup.pl';
$mgr_miscmain = "$mgrconfdir/mgr_miscmain.pl";
$mgr_HTMLjsCSS_includes_builder = "$mgrcoredir/htmlcssjs_includes_builder.pl";
$mgr_misc_html_code_lib_path = './system66/view/agora_misc_html_code.inc';
$mgr_install_source_file_path = '';

# Doesn't work in image upload area. Moved here.
# 6MB max - Most cameras store pics at less than 4MB on HD modes.  -1 = infinite size upload
$CGI::Simple::POST_MAX = 1024 * 6000;
$CGI::Simple::DISABLE_UPLOADS = 0; # uploads enabled.

chdir('..');   # run in the same directory as agora.cgi

require_supporting_libraries( __FILE__, __LINE__,
    "$mgr_user_settings_path",
    "$mgr_setup_path", "$mgr_miscmain"
);

if ( $sc_lang_path eq '' ) { $sc_lang_path = 'eng_us'; }
if ( $sc_html_lang eq '' ) { $sc_html_lang = 'en'; }
if ( $sc_lang_dir eq '' ) { $sc_lang_dir = './language'; }

manager_setup_variables();

require_supporting_libraries( __FILE__, __LINE__,
    "$mgrcoredir/dates_mgr.pl",
    "$sc_lang_dir/$sc_lang_path/manager_messages.pl",
    "$mgrcoredir/headers_footers_mgr.pl",
    "$mgrcoredir/errors_mgr.pl",
    "$mgr_misc_html_code_lib_path"
);

ReadParse(*in);

$mgr_seshun = make_random_chars();

if ( $in{'mgr_seshun'} eq '' ) { $in{'mgr_seshun'} = "$mgr_seshun"; }

require_supporting_libraries( __FILE__, __LINE__,
    "$mgrcoredir/store_admin_html.pl"
);

# removed legacy - call to the serve_picture sub, both removed

require_supporting_libraries( __FILE__, __LINE__,
    "$sc_db_lib_path",   "$sc_ship_lib_path",
    "$mc_mgrpassfile", "$mgrcoredir/store_admin_actions.pl",
    "$mgr_HTMLjsCSS_includes_builder"
);

# default, load flatfile order logs - add others like mySQL later
if ( ( $sc_use_flatfile_orderlogs eq '' ) || ( $sc_use_flatfile_orderlogs =~ /yes/i ) ) {
    require_supporting_libraries( __FILE__, __LINE__, "$mgrcoredir/order_logs_textfiles.pl" );
}
else {
    # mySQL, etc here
    #require_supporting_libraries( __FILE__, __LINE__, "$mgrcoredir/.pl" );
}

# moved legacy - call to the load_store_settings sub moved to update_store_settings sub

load_custom( "$mgrlibdir",   '-ext_lib.pl' );
load_custom( "$mc_paygatesmgr_path", '-mgr_lib.pl' );

if ( ( $sc_self_serve_images =~ /yes/i ) || ( ${sc_path_for_cookie} =~ /^cgi/i ) ) {
    $imageURLthingy = qq|manager.cgi?picserve=|;
}

setup_login_check();

if ( $mc_file_upload_ok =~ /yes/ ) {  # allow images to be uploaded
    handle_uploaded_files();
}

# set image to name of one uploaded and resized, if upload1 used
if ($mc_product_image_name_holder) {
    $in{'image'} = $mc_product_image_name_holder;
}

# Initialize various things for Agora ...
&$menu_item_init();

if ( $in{'login'} ) {
    local ($continue) = q{};
    codehook('action-process-login-top');
    if ( $continue eq 'no' ) { return; }
    &$manager_process_login;
    codehook('action-process-login-bot');
}

# set 30 minute default for session times, if empty
if ( $mc_session_time_setting eq '' ) {
    $mc_session_time_setting = 30;
}

#my $session_compare_value = $mc_session_time_setting / 1440;
# now using stat(). Add 10% buffer to expire time, in seconds.
my $session_compare_value = $mc_session_time_setting * 60 * 1.1;

# If the login file exists, require it and check to see that
# ip of the client is the same as the ip set in the file, and/or the
# session ID is valid. otherwise, return an error
if ( -e "$ip_file" ) {

    eval('require "$ip_file";');
    @mtime = stat("$ip_file");

    # Check to see if login file is too old - now using perl's stat() function
    if ( (time - $mtime[9]) > $session_compare_value ) {
    #if ( -M "$ip_file" > $session_compare_value ) {
        unlink("$ip_file");
        $mgr_session_expire_error =~ s/\[\[mcsessiontimesetting\]\]/$mc_session_time_setting/;
        $mc_login_err = $mgr_session_expire_error;
    }    # End login file age check
    elsif ( $ok_ip ne $ENV{'REMOTE_ADDR'} ) {
        $mc_login_err = $mgr_session_ip_mismatch_error;
    }
    elsif (( $mc_session_id ne $in{'mgr_seshun'} )
        && ( $mc_prev_session_id   ne $in{'mgr_seshun'} )
        && ( $mc_2back_session_id  ne $in{'mgr_seshun'} )
        && ( $mc_3back_session_id  ne $in{'mgr_seshun'} )
        && ( $mc_4back_session_id  ne $in{'mgr_seshun'} )
        && ( $mc_5back_session_id  ne $in{'mgr_seshun'} )
        && ( $mc_6back_session_id  ne $in{'mgr_seshun'} )
        && ( $mc_7back_session_id  ne $in{'mgr_seshun'} )
        && ( $mc_8back_session_id  ne $in{'mgr_seshun'} )
        && ( $mc_9back_session_id  ne $in{'mgr_seshun'} )
        && ( $mc_10back_session_id ne $in{'mgr_seshun'} )
        && ( $mc_11back_session_id ne $in{'mgr_seshun'} )
        && ( $mc_12back_session_id ne $in{'mgr_seshun'} ) )

    {    # check previous sessions
        unlink("$ip_file");
        $mc_login_err = $mgr_session_id_mismatch_error;
    }
    else {  # recreate the file to reset the time
        update_ip_ok();
    }
}
# If the login file doesn't exist, you better log in
else {
    $mc_no_login = 1;
}

if ( ( $mc_login_err ) || ( $mc_no_login ) ) {
    require_supporting_libraries( __FILE__, __LINE__, "$mgrcoredir/login_page_mgr.pl" );
    display_login($mc_login_err);
    call_exit();
}


#load_custom( "$mgrdir/custom", '' );
load_approved_files('approved_plugins');

# for sales log managers
set_log_years_months();
( $scm_day, $scm_month, $scm_year ) = get_month_year();

# Process all the menu possibilities
foreach $menu_item ( sort( keys %menu_items ) ) {
    if ( ( $in{$menu_item} ) && ( $menu_item ne 'welcome_screen') ) {
        $menu_to_run = $menu_items{$menu_item};
        &$menu_to_run;
        call_exit();
    }
}

# If we get here, then no arguments given ... we most likely want the manager homepage
require_supporting_libraries( __FILE__, __LINE__, "$mc_mainpage_path" );

welcome_screen();
call_exit();

#######################################################################

sub update_version_status_file_routine {
    my $file = <<ENDOFTEXT;
\$mgr_current_versions_string = "$mgr_current_versions_string";
\$mgr_version_lastchecked_time = "$mgr_version_lastchecked_time";
1;
ENDOFTEXT
    open( UPDATEFILE, ">$mc_version_lastchecked_path" ) || my_die("Can't Open $mc_version_lastchecked_path");
    print( UPDATEFILE $file );
    close(UPDATEFILE);

}

#######################################################################
sub add_settings_choice {
    local ( $sortname, $displayname, $linkname ) = @_;
    local ($continue) = q{};
    if ( $continue eq 'no' ) { return; }
    $sortname =~ tr/A-Z/a-z/;
    $store_settings_name{$sortname} = $displayname;
    $store_settings_link{$sortname} = $linkname;
}

#######################################################################
sub add_merchtools_settings_choice {
    local ( $sortname, $displayname, $linkname ) = @_;
    local ($continue) = q{};
    if ( $continue eq 'no' ) { return; }
    $sortname =~ tr/A-Z/a-z/;
    $merchtools_settings_name{$sortname} = $displayname;
    $merchtools_settings_link{$sortname} = $linkname;
}

#######################################################################

sub add_ordermanage_settings_choice {
    local ( $sortname, $displayname, $linkname ) = @_;
    local ($continue) = q{};
    if ( $continue eq 'no' ) { return; }
    $sortname =~ tr/A-Z/a-z/;
    $ordermanage_settings_name{$sortname} = $displayname;
    $ordermanage_settings_link{$sortname} = $linkname;
}

#######################################################################

sub add_performance_metrics_choice {
    local ( $sortname, $displayname, $linkname ) = @_;
    local ($continue) = q{};
    if ( $continue eq 'no' ) { return; }
    $sortname =~ tr/A-Z/a-z/;
    $performance_metrics_name{$sortname} = $displayname;
    $performance_metrics_link{$sortname} = $linkname;
}

#######################################################################

sub require_supporting_libraries {

    # The libraries are required by us,so exit if loading error
    local ( $file, $line, @require_files ) = @_;
    local ($require_file);
    request_supporting_libraries( "warn exit", $file, $line, @require_files );
}

#######################################################################

sub request_supporting_libraries {

    # The incoming file and line arguments are split into
    # the local variables $file and $line while the file list
    # is assigned to the local list array @require_files.
    #
    # $require_file which will just be a temporary holder
    # variable for our foreach processing is also defined as a
    # local variable.

    local ( $what_to_do_on_error, $file, $line, @require_files ) = @_;
    local ($require_file);

    # Next, the script checks to see if every file in the
    # @require_files list array exists (-e) and is readable by
    # it (-r). If so, the script goes ahead and requires it.

    foreach $require_file (@require_files) {
        # file is there, now try to require it.
        # require it in a not-fatal way.
        if (  -e "$require_file" && -r "$require_file" ) {
            $result = eval('require "$require_file"');
            if ($@) {
                if ( $what_to_do_on_error =~ /warn/i ) {
                    if ( $error_header_done ne 'yes' ) {
                        $error_header_done = 'yes';
                        print "Content-type: text/html\n\n";
                    }
                    print "<div><table width=500><tr><td>\n";
                    print
                      "Error loading library $require_file:<br><br>\n  $@\n";
                    print "<br><br>Please fix the error and try again.<br>\n";
                    print "</td></tr></table></div>\n";
                }
                if ( $what_to_do_on_error =~ /exit/i ) {
                    call_exit();
                }
            }
        }

        # If not, the scripts sends back an error message that
        # will help the admin isolate the problem with the script.

        else {

            if ( $what_to_do_on_error =~ /warn/i ) {
                if ( $error_header_done ne 'yes' ) {
                    $error_header_done = 'yes';
                    print "Content-type: text/html\n\n";
                }
                print
                  "I am sorry but I was unable to require $require_file at line
$line in $file.  <br>\nWould you please make sure that you have the
path correct and that the permissions are set so that I have
read access?  Thank you.";
            }

            if ( $what_to_do_on_error =~ /exit/i ) {
                call_exit();
            }
        }

    }    # End of foreach $require_file (@require_files)
}

########################################################################

sub handle_uploaded_files {

    my $imageuploadcounter = 1;
    my $upfiletag    = 'upfile1';
    ## end of july 2010 adds
    $save_umask_value = umask;
    if ($original_umask) { umask $original_umask; }
    codehook('mgr_upload_files_prep');

    # only handles 12 image uploads
    while ( ( $imageuploadcounter < 13 ) && ( $in{$upfiletag} ) ) {
        handle_uploaded_single_file( "$upfiletag", $imageuploadcounter );
        $imageuploadcounter++;
        $upfiletag = 'upfile' . $imageuploadcounter;
    }
    umask $save_umask_value;
}

########################################################################

sub handle_uploaded_single_file {
    local ( $zname, $imageuploadcounter ) = @_;
    local ( $imageToScale, $my_img_file, $junk, $tempImgRead ) = q{};
    local ($file_has_contents, $err_code, $imagedata) = q{};

    $upload_filehandle = upload($in{$zname});

    if ( $upload_filehandle > 10 ) {
        $file_has_contents = 1;
    } else {
        return ();
    }

    # Pull out current p_id to use later for image folder name and image name
    my $sku = "$in{'new_sku'}";
    $sku =~ /([\w\-\_\.\+\/]+)/; # untaint

    # Define new image directory name based on p_id
    $my_img_pid = "$1";

    # Create final product img directory based on p_id
    if ( !( -d "$mc_images_dir/$my_img_pid" ) && ($file_has_contents) ) {
        mkdir "$mc_images_dir/$my_img_pid";
        open( INDXFILE, ">$mc_images_dir/$my_img_pid/index.html" )
          || my_die("Can't Open $mc_images_dir/$my_img_pid/index.html");
        print( INDXFILE "Restricted Area" );
        close(INDXFILE);
    }

    #$my_img_file = last_part_of_filename( $in{$zname} );
    $my_img_file = param("$zname");
    $my_img_file =~ /([\w\-\_\.\+\/]+)/;
    $my_img_file = $1;
    my ( $imagename, $imageextension ) = split( /\./, $my_img_file );

    # setup all 3 image renames & save-to locations.
    # main catalog image
    $my_img_file =
      "$mc_images_dir/$my_img_pid/$imagename" . "_cat." . $imageextension;

    # catalog thumbnail
    $my_img_file_small =
      "$mc_images_dir/$my_img_pid/$imagename" . "_sm.$imageextension";

    # original image
    $my_img_file_orig = "$mc_images_dir/$imagename.$imageextension";

    # automagically change default image for one in upfile1
    # also update thumbnail in userField One
    if ( ( $zname eq 'upfile1' ) && ( defined $upload_filehandle ) ) {
        $my_img_file_orig = "$mc_images_dir/$my_img_pid/$imagename"
          . "_orig.$imageextension";
        $mc_product_image_name_holder = "$imagename" . "_cat.$imageextension";
        $mc_product_image_thumb_holder =
          '[[IMG]]' . "$my_img_pid/" . $mc_product_image_name_holder;
        $mc_product_image_thumb_holder =~ s/_cat/_sm/;
    }

    if ( ($file_has_contents) && ( defined $upload_filehandle ) ) {

        open( OUTFILE, '>', "$my_img_file_orig" );
        while ( read( $upload_filehandle, $buffer, 1024 ) ) {
            binmode(OUTFILE);
            print OUTFILE $buffer;
        }
        close OUTFILE;

        if ( $mc_chmod_uploaded_images =~ /yes/i ) {
            system("chmod 644 $my_img_file_orig");
        }
    }
    else {
        $fup_msg =
            "no file name for image given $zname" . '### '
          . $zname
          . ' ### $zname ###'
          . " $my_img_file <br>$zname con=$file_has_contents<br>\n";
    }

    #use GD;
    eval("use GD;");
    $err_code = $@;
    if ($err_code) {    # GD module error of some kind
        update_error_log( "GD Perl Module Error: $err_code", 'manager.cgi', 'handle_uploaded_single_file sub-routine at: use GD' );
    }
    if ( !( $err_code ) && ( $file_has_contents ) && ( $zname eq 'upfile1' ) ) {
        # the nuts & bolts of resizing and saving images.
        GD::Image->trueColor(1);
        $imageToScale = GD::Image->new("$my_img_file_orig");    # read in the picture. must already be stored.

        # resize pic for catalog display on first box of image upload only
        if ( $sc_store_image_geometry eq '' ) {
            $sc_store_image_geometry = '150x150';
        }
        ( $width, $height ) = split( /x/, $sc_store_image_geometry );

        # Scale vs original size for main product image
        {
            my $k_h = $height / $imageToScale->height;
            my $k_w = $width / $imageToScale->width;
            my $k   = ( $k_h < $k_w ? $k_h : $k_w );
            $height = int( $imageToScale->height * $k );
            $width  = int( $imageToScale->width * $k );
        }

        if ( $imageextension =~ /jpg|jpeg/i ) {
            my $image = GD::Image->new( $width, $height );
            $image->alphaBlending(0);
            $image->saveAlpha(1);
            $image->copyResampled( $imageToScale, 0, 0, 0, 0, $width, $height,
                $imageToScale->width, $imageToScale->height );
            open( FH, ">$my_img_file" );
            binmode FH;
            print FH $image->jpeg(100);
            close(FH);
        }

        # does not handle transparent backgrounds, becomes white
        elsif ( $imageextension =~ /gif/i ) {
            my $image = GD::Image->new( $width, $height );
            $image->alphaBlending(0);
            $image->saveAlpha(1);
            $image->copyResampled( $imageToScale, 0, 0, 0, 0, $width, $height,
                $imageToScale->width, $imageToScale->height );
            open( FH, ">$my_img_file" );
            binmode FH;
            print FH $image->gif();
            close(FH);
        }
        elsif ( $imageextension =~ /png/i ) {
            my $image = GD::Image->new( $width, $height );
            $image->alphaBlending(0);
            $image->saveAlpha(1);
            $image->copyResampled( $imageToScale, 0, 0, 0, 0, $width, $height,
                $imageToScale->width, $imageToScale->height );
            open( FH, ">$my_img_file" );
            binmode FH;
            print FH $image->png();
            close(FH);
        }

        # resize pic for thumbnail
        if ( $sc_store_thumb_geometry eq '' ) {
            $sc_store_thumb_geometry = '65x65';
        }
        ( $width, $height ) = split( /x/, $sc_store_thumb_geometry );

        # Scale vs original size for thumbnail
        {
            my $k_h = $height / $imageToScale->height;
            my $k_w = $width / $imageToScale->width;
            my $k   = ( $k_h < $k_w ? $k_h : $k_w );
            $height = int( $imageToScale->height * $k );
            $width  = int( $imageToScale->width * $k );
        }

        if ( $imageextension =~ /jpg|jpeg/i ) {
            my $image = GD::Image->new( $width, $height );
            $image->alphaBlending(0);
            $image->saveAlpha(1);
            $image->copyResampled( $imageToScale, 0, 0, 0, 0, $width, $height,
                $imageToScale->width, $imageToScale->height );
            open( FH, ">$my_img_file_small" );
            binmode FH;
            print FH $image->jpeg(100);
            close(FH);
        }

        # does not handle transparent backgrounds, becomes white
        elsif ( $imageextension =~ /gif/i ) {
            my $image = GD::Image->new( $width, $height );
            $image->alphaBlending(0);
            $image->saveAlpha(1);
            $image->copyResampled( $imageToScale, 0, 0, 0, 0, $width, $height,
                $imageToScale->width, $imageToScale->height );
            open( FH, ">$my_img_file_small" );
            binmode FH;
            print FH $image->gif();
            close(FH);
        }
        elsif ( $imageextension =~ /png/i ) {
            my $image = GD::Image->new( $width, $height );
            $image->alphaBlending(0);
            $image->saveAlpha(1);
            $image->copyResampled( $imageToScale, 0, 0, 0, 0, $width, $height,
                $imageToScale->width, $imageToScale->height );
            open( FH, ">$my_img_file_small" );
            binmode FH;
            print FH $image->png();
            close(FH);
        }
        undef $imageToScale;
    }
    # end use GD

}

########################################################################
# Potential problem here if the \ is part of an "escaped" filename
# so do not use "interesting" filenames, stick to letters, numbers,
# '_' and '-' and all will be well!
########################################################################

sub last_part_of_filename {
    local ($name) = @_;
    local (@my_items);
    $name =~ s/\\/\//g;    # make all slashes be the / variety
    @my_items = split( /\//, $name );
    return $my_items[$#my_items];
}

#######################################################################
# For running codehooks at various places
#######################################################################

sub codehook {
    local ($hookname) = @_;
    local ( $codehook, $err_code, @hooklist );
    if ( $codehooks{$hookname} ) {
        @hooklist = split( /\|/, $codehooks{$hookname} );
        foreach $codehook (@hooklist) {
            eval("&$codehook;");
            $err_code = $@;
            if ($err_code) {    #script died, error of some kind
                update_error_log( "code-hook $hookname $codehook $err_code", '', '' );
            }
        }
    }
}

#######################################################################
# For adding codehooks to the list for later execution
#######################################################################

sub add_codehook {
    local ( $hookname, $sub_name ) = @_;
    local ( $codehook, $err_code, @hooklist );
    if ( $sub_name eq '' ) { return; }
    if ( $codehooks{$hookname} eq '' ) {
        $codehooks{$hookname} = $sub_name;
    }
    else {
        $codehooks{$hookname} .= '|' . $sub_name;
    }
}

#######################################################################

sub load_custom {
    local ( $zdir, $ztext ) = @_;
    local ( $zlib, @mylibs, $lib );
    opendir( USER_LIBS, "$zdir" );
    @mylibs = sort( readdir(USER_LIBS) );
    closedir(USER_LIBS);

    foreach $zlib (@mylibs) {
        $lib = $zlib;
        $lib =~ /([\w\-\=\+]+)(\.pl)/i;
        $zfile = "$1$2";
        if (   ( $ztext eq '' )
            || ( ($ztext) && ( $zfile =~ /$ztext/i ) ) )
        {
            if ( ( -f "$zdir/$lib" ) && ( $lib eq $zfile ) ) {
                $lib =~ /([^\n|;]+)/;
                $lib = $1;
                require_supporting_libraries( __FILE__, __LINE__, "$zdir/$lib" );
                # $mgr_loaded_libs .= "\'$zdir/$lib\',"; # to build lists of loaded libs
            }
        }
    }
}

#######################################################################

sub load_approved_files {
    local $zlistname = shift;
    my ( $zlib );

    foreach $lib (@$zlistname) {
        if ( -f "$lib" ) {
            require_supporting_libraries( __FILE__, __LINE__, "$lib" );
        }
    }
}

#######################################################################

sub read_templatedirs {
    my ( $zdir, $ztext ) = @_;
    my ( $zlib, @myplates, $optionString ) = q{};
    opendir( TEMPLATE_FILES, "$zdir" );
    @myplates = sort( readdir(TEMPLATE_FILES) );
    closedir(TEMPLATE_FILES);

    foreach $zlib (@myplates) {
        $zlib =~ /([\w\-\=\+]+)(\.inc)/i;
        $zfile = "$1$2";
        if ( ( $ztext eq '' ) || ( ($ztext) && ( $zfile =~ /^$ztext/i ) ) ) {
            if ( ( -f "$zdir/$zlib" ) && ( $zlib eq $zfile ) ) {
                $zlib =~ /([^\n|;]+)/;
                $zlib = $1;
                $optionString .= qq~<option value="$zlib">$zlib</option>\n~;
            }
        }
    }
    return $optionString;
}

#######################################################################

sub setup_login_check {
    $ip_file_dir        = "$mgrdir/files";
    $mc_path_for_cookie = $sc_path_for_cookie . "/$mgrdirname";
    local ( $cookie_secure_status, $cookie ) = q{};
    my $cookie_filling = q{};
    my $newTime = time;
    my $newTime2 = 0;

    if ( $mc_domain_name_for_cookie eq '' ) {
        $mc_domain_name_for_cookie = $sc_domain_name_for_cookie;
    }

    if ( $mc_use_cookie_login =~ /yes/ ) {
        $cookie_filling = cookie('agoramgr');
        # set expire time attached to cookie value
        $newTime2 = ($newTime + ( $mc_session_time_setting * 60 * 1.2) );

        $cookie_filling =~ /([^\xFF]*)/;
        $cookie_filling = "$1";
        ( $cookie_filling, $cookieTime ) = split( /\./, $cookie_filling, 2 );

        $cookieTime = $cookieTime +1; # force it to a number, some servers have prob don't see it as a number

        # check for cookie time and if login being submitted.
        # If so, lets flush old cookies and delete old login files.
        #if ( ( ( $cookieTime < $newTime ) && ( $cookieTime ) && ( $cookie_filling ) ) || ( $in{'login'} ) ) {
        if ( ( $cookieTime < $newTime ) && ( $cookieTime ) && ( $cookie_filling ) ) {
            # delete login file
            unlink("$ip_file_dir/$cookie_filling.login");
            # forget local cookie value
            $cookie_filling = q{};
        }

        if ( $cookie_filling ) {
            $mc_have_cookie = 'yes';
            $cookie{'agoramgr'} = $cookie_filling . '.' . $newTime2;
        }
        # make new cookie value & time to expire.
        else {
            $mc_have_cookie  = 'no';
            $cookie_filling = make_random_chars();
            $cookie{'agoramgr'} = $cookie_filling . '.' . $newTime2;
        }

        if ( $ENV{HTTPS} eq 'on' ) {
            $mc_domain_name_for_cookie = $sc_secure_domain_name_for_cookie;
            $cookie_secure_status = '1';
        }
        else {
            $cookie_secure_status = '0';
        }

        $cookie = cookie(
            -name=>'agoramgr',
            -value=>"$cookie{'agoramgr'}",
            -expires=>'+20h',
            -path=>"$mc_path_for_cookie",
            -domain  => "$mc_domain_name_for_cookie",
            -httponly => 1,
            -secure=>"$cookie_secure_status"
        );
        $ip_file = "$ip_file_dir/$cookie_filling.login";

        if ( $mgr_header_status =~ /404|400|401|403|405|410/ ) {
            print header(-cookie=>$cookie, -status=>"$mgr_header_status", -X_Robots_Tag=>'noindex, nofollow, noarchive');
        }
        else {
            # print header(-cookie=>[$cookie,$cookie2]); # multiple cookies
            print header(-cookie=>$cookie, -X_Robots_Tag=>'noindex, nofollow, noarchive');
        }
    }
    else {
        print header(-X_Robots_Tag=>'noindex, nofollow, noarchive');
        $ip_file = "$ip_file_dir/$a_unique_name.login";
    }

}

###############################################################################

sub make_random_chars {

    # name says it all
    local ( $part1, $part2, $valid_chars, $chars, $inx );
    $part1 = 'abcdefghijklmnopqrstuvwxyz';
    $part2 = $part1;
    $part2 =~ tr/a-z/A-Z/;
    $valid_chars = $part1 . $part2 . '0123456789';
    $chars       = q{};
    for ( $inx = 0 ; ( $inx < 8 ) ; $inx++ ) {
        $chars .= substr( $valid_chars, rand( length($valid_chars) ), 1 );
    }
    return $chars;
}

#######################################################################

sub category_list_builder_for_store {

    local (
        $sku,  $category, $myset,
        $subcategory,   $sc_categories_with_subcats,
        $sc_categories_no_subcats, $sc_categories_bots_with_subcats,
        $sc_categories_bots_no_subcats
    ) = q{};
    my ( $catnumber, $catnumber2, $category, $category2, $category3 ) =  q{};
    local ( %db_ele, %subcatarray ) = ();
    my ( $supercats ) = './add_ons/supercats.pl';

    if ( $mgr_skip_category_list_builder eq 'yes' ) {
        $myset .= "\$sc_categories_no_subcats = qq||;\n";
        $myset .= "\$sc_categories_bots_no_subcats = qq||;\n";
        update_store_settings( 'CATEGORYLIST', $myset );
        return;
    }

    if ( !( $sc_db_lib_was_loaded =~ /yes/i ) ) {
        require_supporting_libraries( __FILE__, __LINE__, "$sc_db_lib_path" );
    }

    if ( $sc_use_database_subcats =~ /yes/i ) {
        get_prod_db_element( $db{"product"}, *db_ele );
        # Custom sub-category menu builder override and/or SuperCats Version 6.0000  (or higher)  use
        if ( ( -e $supercats ) || ( $sc_use_custom_cat_menu =~ /yes/i ) ) {

        }
        else {
            foreach $sku ( sort ( keys %db_ele ) ) {
                $catnumber = q{};
                $category  = $db_ele{$sku};
                $category2 = $category;
                $category2 =~ s/\s+/-/g;
                %subcatarray = %{ $db_ele{$category} };

                if ( $sc_count_database_cats =~ /yes/i ) {
                    $catnumber = '(' . $db_ele2{$category} . ')';
                }

                # if SEO mod_rewrite, build friendlier links
                if ( $sc_seo_friendly =~ /yes/i ) {
                    $sc_categories_with_subcats .= <<ENDOFTEXT;
<li><a class="$custom_sc_main_category_css_class" href="$sc_store_base_URL$category2" title="$category">$category</a>$catnumber</li>\n
ENDOFTEXT
                    $sc_categories_bots_with_subcats .= <<ENDOFTEXT;
<li><a class="$custom_sc_main_category_css_class" href="$sc_store_base_URL$category2" title="$category">$subcategoryarray</a>$catnumber</li>
ENDOFTEXT
                }
                else {
                    $sc_categories_with_subcats .= qq|<li><a class="$custom_sc_main_category_css_class" href="$sc_store_base_URL|; #"
                    $sc_categories_with_subcats .= qq|agora.cgi?product=$category2&amp;xm=on" title="$category">$category</a>$catnumber</li>\n|; #"
                    $sc_categories_bots_with_subcats .= qq|<li><a class="$custom_sc_main_category_css_class" href="$sc_store_base_URL|; #"
                    $sc_categories_bots_with_subcats .= qq|agora.cgi?product=$category2&amp;xm=on" title="$category">$category</a>$catnumber</li>|; #"
                }

                foreach $subcategoryarray ( sort( keys %subcatarray ) ) {
                    $category3 = $subcategoryarray;

                    if ( $sc_count_database_cats =~ /yes/i ) {
                        $catnumber2 =
                          '(' . $db_ele{$category}->{$subcategoryarray} . ')';
                    }

                    # if SEO mod_rewrite, build friendlier links
                    if ( $sc_seo_friendly =~ /yes/i ) {
                        $category4 = $category3;
                        $category4 =~ s/ \> /-grthan-/g;
                        $category4 =~ s/\s+/-/g;
                        $sc_categories_with_subcats .= qq|<li><a class="$custom_sc_sub_category_css_class" href="$sc_store_base_URL$category2,$category4" title="$category3">$category3</a>$catnumber</li>\n|;
                        $sc_categories_bots_with_subcats .= qq|<li><a class="$custom_sc_sub_category_css_class" href="$sc_store_base_URL$category2,$category4" title="$category - $category3">$subcategoryarray</a>$catnumber</li>\n|;
                    }
                    else {
                        $category4 = $category3;
                        $category4 =~ s/ \> /-grthan-/g;
                        $category4 =~ s/\s+/-/g;
                        $sc_categories_with_subcats .= qq|<li><a class="$custom_sc_sub_category_css_class" href="$sc_store_base_URL|;
                        $sc_categories_with_subcats .= qq|agora.cgi?product=$category2&amp;$sc_subcat_index_field=$category4&amp;xm=on" title="$category3">$category3</a>$catnumber</li>\n|;
                        $sc_categories_bots_with_subcats .= qq|<li><a class="$custom_sc_sub_category_css_class" href="$sc_store_base_URL|;
                        $sc_categories_bots_with_subcats .= qq|agora.cgi?product=$category2&amp;$sc_subcat_index_field=$category4&amp;xm=on" title="$category - $category3">$subcategoryarray</a>$catnumber</li>\n|;
                    }

                }
            }
        }
        $myset .= "\$sc_categories_with_subcats = qq|$sc_categories_with_subcats|;\n";
        $myset .= "\$sc_categories_bots_with_subcats = qq|$sc_categories_bots_with_subcats|;\n";

    }
    else {
        get_prod_db_element( $db{'product'}, *db_ele );
        foreach $sku ( keys %db_ele ) {
            $category = $db_ele{$sku};
            $category_list{$category}++;
        }
        foreach $category ( sort( keys %category_list ) ) {
            $category2 = $category;
            if ($sc_convert_product_token_underlines) {
                $category2 =~ s/$sc_convert_product_token_underlines/\-/g;
            }
            $category2 =~ s/\s+/-/g;
            if ( $sc_seo_friendly =~ /yes/i ) {
                $sc_categories_with_subcats .= qq|<li><a class="$custom_sc_main_category_css_class" href="$sc_store_base_URL|; #"
                $sc_categories_with_subcats .= qq|$category2" title="$category">$category</a>$catnumber</li>\n|; #"
                $sc_categories_bots_with_subcats .= qq|<li><a class="$custom_sc_main_category_css_class" href="$sc_store_base_URL|; #"
                $sc_categories_bots_with_subcats .= qq|$category2" title="$category">$category</a>$catnumber</li>\n|; #"
            }
            else {
                $sc_categories_with_subcats .= qq|<li><a class="$custom_sc_main_category_css_class" href="$sc_store_base_URL|; #"
                $sc_categories_with_subcats .= qq|agora.cgi?product=$category2&amp;cart_id=[[cart_id]]&amp;xm=on" title="$category">$category</a>$catnumber</li>\n|; #"
                $sc_categories_bots_with_subcats .= qq|<li><a class="$custom_sc_main_category_css_class" href="$sc_store_base_URL|; #"
                $sc_categories_bots_with_subcats .= qq|agora.cgi?product=$category2&amp;xm=on" title="$category">$category</a>$catnumber</li>\n|; #"
            }
        }
        $myset .= "\$sc_categories_no_subcats = qq|$sc_categories_no_subcats|;\n";
        $myset .= "\$sc_categories_bots_no_subcats = qq|$sc_categories_bots_no_subcats|;\n";
    }

    codehook('over-ride-category-list');

    update_store_settings( 'CATEGORYLIST', $myset );

}

#######################################################################
#                        Delete Old Carts
#######################################################################
# delete_old_carts is a subroutine which is used to prune
# the carts directory, cleaning out all the old carts
# after some time interval defined in the manager settings (aved in the user
# settings file).  It takes no arguments and is called with the following
# syntax:
#
# delete_old_carts();

sub check_cart_expiry {
    check_cart_type_file_expiry("$sc_cart_path");
    check_cart_type_file_expiry("$sc_verify_order_path");
    check_cart_type_file_expiry("$sc_server_cookie_path");
}

#############

sub check_cart_type_file_expiry {
    local ($cart_type_file_path) = @_;
    if ( -M "$cart_type_file_path" > $sc_number_days_keep_old_carts ) {
        if ( $cart_type_file_path =~ /cart/i ) {
            codehook('delete-cart');
            if ( ( $sc_db_index_for_inventory ) && ( $sc_inventory_subtract_at_add_to_cart =~ /yes/i ) && ( $mc_mgr_plugins_enabled =~ /inventory_control/ ) ) {
                open( CART, "$cart_type_file_path" )
                || errorcode( __FILE__, __LINE__,  "$sc_cart_path", "$!", 'ignore', 'FILE OPEN ERROR', '0' );
                require_supporting_libraries( __FILE__, __LINE__, "$sc_plugin_lib_dir/inventory_control.pl" );
                while (<CART>) {
                    my @row = split( /\|/, $_ );
                    add_inventory( $row[1], $row[0] );
                }
                close(CART);
            }
        }
        else {
            codehook('delete-non-cart');
        }
        unlink("$cart_type_file_path");
    }
}

#############

sub delete_old_carts {

    # The subroutine begins by grabbing a listing of all of
    # the client created shoppping carts in the User_carts
    # directory.
    #
    # It then opens the directory and reads the contents using
    # grep to grab every file with the extension _cart. Then
    # it closes the directory.
    #
    # If the script has any trouble opening the directory,
    # it will output an error message using the
    # file_open_error subroutine discussed later.  To the
    # subroutine, it will pass the name of the file which had
    # trouble, as well as the current routine in the script
    # having trouble , the filename and the current line
    # number.

    opendir( USER_CARTS, "$sc_user_carts_directory_path" ) || file_open_error(
        "$sc_user_carts_directory_path", 'Delete Old Carts', __FILE__, __LINE__ );
    @carts = grep( /\.[0-9]/, readdir(USER_CARTS) );  # must have . followed by digits
    closedir(USER_CARTS);

    # Now, for every cart in the directory, delete the cart if
    # it is older than half a day.  The -M file test returns
    # the number of days since the file was last modified.
    # Since the result is in terms of days, if the value is
    # greater than the value of $sc_number_days_keep_old_carts
    # set in main manager settings, we'll delete the file.

    foreach $cart (@carts) {

        # code below deletes carts and other files in this directory that have expired
        $sc_cart_path = "$sc_user_carts_directory_path/$cart";
        $sc_cart_path =~ /([\w\-\=\+\/\.]+)/;
        $sc_cart_path = "$1";
        $sc_cart_path = q{} if ( $sc_cart_path eq '.' );
        $sc_cart_path =~ s/^\/+//;    # Get rid of any residual / prefix
        check_cart_type_file_expiry("$sc_cart_path");
    }

}

#######################################################################
# Contains variables and defaults for starting up store manager
# This routine is run early so libraries can "hook" in
#######################################################################

sub manager_setup_variables {

    $sysname = $ENV{'SERVER_NAME'};
    $mc_gateways = q{};      # Names are added by -mgr_lib.pl type files
    $mc_file_upload_ok = 'yes';    # allow images to be uploaded
    $mc_assign_final_sku_at_update = 'yes';    # helpful for adding new products
    $mc_product_image_name_holder = q{};
    $mc_product_image_thumb_holder = q{};
    $other_welcome_message = q{};
    $mc_standard_body_tag  = q{};
    $mc_mgrpassfile = "$mgrconfdir/mgr_pass.pl";
    $mgr_edge_tier_status = ' disabled'; # blank to enable
    $mgr_current_tier_status = '';
    $mgr_perms_mode = 0644;
    $mgr_versions_URL = 'https://agoracart.com/misc_info/route66c_versions.txt';

    # for sales log managers
    $scm_order_logpath = $sc_data_file_dir . '/log_files/order_logs';

    # location to load the payment gateway manager files
    $mc_paygatesmgr_path = "$sc_paygates_dir/managers";

    # for store manager main page
    $mc_mainpage_path = "$mgrcoredir/main_page_mgr.pl";

    # for access control lists (ACL)
    $mc_aclprofile_path = "$mgrconfdir/mgr_acl_profiles.pl";

    # Version check status file - to prevent from checing every time loaded
    $mc_version_lastchecked_path = "$mgrconfdir/mgr_version_status.pl";

    $sc_userfieldsfile = "$mgrconfdir/userfields.pl";
    $mc_shipfilename = "$sc_data_file_dir/db/shipping_dimensions.file";
    $mc_css_mgr_settings = "$mgrconfdir/mgr_css.pl";

    $commando_ok = 'no';  # say "yes" to turn it on without the commando.ok file
    if ( -f "$mgrdir/commando.ok" ) {
        $commando_ok = 'yes'; # say "yes" if file is in this directory
    }

    $manager_process_login  = 'std_action_process_login';

    if ( $mc_mgr_template eq 'dashboard66' ) {
        $manager_page_header = 'dash66_manager_header_code';
        $manager_page_footer = 'dash66_manager_footer_code';
        $manager_welcome_screen = 'dash66_welcome_screen';
    }
    else { # legacy - standard header
        $manager_page_header = 'std_manager_header_code';
        $manager_page_footer = 'std_manager_footer_code';
        $manager_welcome_screen = 'std_welcome_screen';
    }

    # sub to init menu, doubles as hook to replace main manager logic
    # could be used to put in secured multi-user manager for example
    $menu_item_init = 'init_convert_menu_item';

    ## Define the routines to run the various processes
    ## Display Screen Logic
    $menu_items{'welcome_screen'} = 'welcome_screen';
    $menu_items{'error_log'} = 'display_error_log';
    $menu_items{'clear_error_log'} = 'clear_error_log';
    $menu_items{'clear_access_log'} = 'clear_access_log';
    $menu_items{'order_log'} = 'display_order_log';
    $menu_items{'change_settings_screen'} = 'change_settings_screen';
    $menu_items{'order_management_settings_screen'} =  'order_management_settings_screen';
    $menu_items{'content_management_settings_screen'} = 'content_management_settings_screen';
    $menu_items{'store_performance_metrics'} = 'store_performance_metrics';
    $menu_items{'htaccess_screen'} = 'setup_htaccess_screen';
    ## End Of Display Screen Logic

    # if store accesses logging is enabled in main settings, add to metrics menu
    if ($sc_shall_i_log_accesses =~ /yes/i) {
        add_performance_metrics_choice(
            'Visitor Access Logs',
            ' Visitor Access Logs ',
            'visitor_access_display'
        );
        require_supporting_libraries( __FILE__, __LINE__, "$mgrcoredir/accesslogs_mgr.pl" );
    }

    ## Admin Action Logic
    $menu_items{'htaccessSettings'} = 'action_htaccess_settings';
    $menu_items{'log_out'} = 'log_out';

    if ( $sc_userfields_available =~ /10|20/ ) {
        $user10_thingy = qq~
<option>User 6</option>
<option>User 7</option>
<option>User 8</option>
<option>User 9</option>
<option>User 10</option>
~;
    }

    if ( $sc_userfields_available =~ /10|20/ ) {
        $user10_option_thingy = qq~
<option value="user6">user6</option>
<option value="user7">user7</option>
<option value="user8">user8</option>
<option value="user9">user9</option>
<option value="user10">user10</option>
~;
    }

}

#######################################################################
# For cleanup purposes such as closing files, removing locks, etc.
#######################################################################

sub call_exit {
    codehook('cleanup_before_exit');
    undef(%store_settings);
    exit;
}
