package Cpanel::Easy::Apache::UI::HTML::Config;

# cpanel - Config.pm                              Copyright(c) 2014 cPanel, Inc.
#                                                           All rights Reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited

use strict;
use Cpanel::Encoder                      ();
use Cpanel::Math                         ();
use Cpanel::LoadFile                     ();
use Cpanel::Easy::Utils::cPVers          ();
use Cpanel::Easy::Apache::Utils::Support ();
use Cpanel::Easy::PHP5                   ();
use JSON::Syck                           ();
require Cpanel::Easy::Apache::UI::HTML;

my $info_icon;
my $hide_icon;
my $docu_icon;
my $show_icon;
{
    no warnings 'once';
    $info_icon = $Cpanel::Easy::Apache::UI::HTML::info_icon;
    $hide_icon = $Cpanel::Easy::Apache::UI::HTML::hide_icon;
    $docu_icon = $Cpanel::Easy::Apache::UI::HTML::docu_icon;
    $show_icon = $Cpanel::Easy::Apache::UI::HTML::show_icon;
}

my $ENDOFLIFE    = $Cpanel::Easy::Apache::Utils::Support::ENDOFLIFE;
my $EXPERIMENTAL = $Cpanel::Easy::Apache::Utils::Support::EXPERIMENTAL;

my ( $show_det_class, $hide_det_class ) = ( "showDetail", "hideDetail" );

# This variable is a flag which tells if the current cPanel version is
# anything between 11.34 & 11.38 inclusive of both.
my $IS_1134_to_1138 = 0;

sub main {
    my ( $self, $easy, $profile, $profile_setup ) = @_;    # already calculated file, hashref of that file

    # Set the flag $IS_1134_to_1138
    $IS_1134_to_1138 = $self->pre_1140_version() && !$self->pre_1134_version();

    $easy->set_param( 'skip-cpanelsync', 1 );              # we've already done it so don't do it for each page 'session'

    my $zero        = 'easyapache.pl';                     # = $0; # $0 busted in 11.17.4-E20246, TODO: fix properly
    my $wizard_step = 0;

    # Increment the wizard step index if it is old profile page(cPanel&WHM < 11.40).
    # This had to be done since list profiles is part of wizard for pre 11.40 versions
    # and not a part of wizard from 11.40 version.
    $wizard_step = 1 if $self->pre_1140_version;

    my %wizard_steps = (
        'choose_apache' => {
            'short' => 'Apache Version',
            'order' => ++$wizard_step,
            'name'  => 'Please choose which apache to build',
            'icon'  => '/images/apache.gif',
        },
        'choose_php' => {
            'short' => 'PHP Version',
            'order' => ++$wizard_step,
            'name'  => 'Please choose which PHP version(s) to build',
            'icon'  => '/images/php.gif',
        },
        'show_basic_opts' => {
            'short' => 'Short Options List',
            'order' => ++$wizard_step,
            'name'  => 'Please choose specific options',
            'icon'  => '/images/Tool24.gif',
        },
        'show_all_opts' => {
            'short' => 'Exhaustive Options List',
            'order' => ++$wizard_step,
            'name'  => 'Please choose specific options',
            'icon'  => '/images/Tool24.gif',
        },    # save as [ text box ] && [X] save only ...
        'save_only' => {
            'short' => 'Save',
            'order' => ++$wizard_step,
            'name'  => 'Save Only',
            'icon'  => '/images/Tool24.gif',
        },
        'save_and_build' => {
            'short' => 'Build',
            'order' => ++$wizard_step,
            'name'  => 'Save Changes and Start Build',
            'icon'  => '/images/Tool24.gif',
        },
    );

    ##
    # List Profiles is part of the EA wizard only for old profile page.
    # Starting from 11.40, the new profile page is displayed where
    # it is no longer part of the wizard. When you click to customize
    # a profile, it starts a wizard from next page (i.e Apache selection page)
    ##
    if ( $self->pre_1140_version ) {
        $wizard_steps{'list_profiles'} = {
            'short' => 'Profile',
            'order' => 1,
            'name'  => 'Begin by selecting a profile to load',

            # DEPRECATED: Remove icon and post_hr
            'icon'    => '/images/configure.gif',
            'post_hr' => sub {
                return <<"END_POST_HR";
                <div style="margin-left: 20px;float:right;">
                  [<a href="$zero?help=1">Help</a>]
                  [<a href="$zero?skip-cpanelsync=1&action=_profile_upload">Upload Profile</a>]
                  [<a href="javascript:display_quickpopupbox('About Profiles','$Cpanel::Easy::Apache::UI::HTML::layover_safe_profile_details')">About Profiles</a>]
                  [<a href="easyapache.pl?action=_run_logs&skip-cpanelsync=1">Build History</a>]
                  [<a href="$zero?skip-cpanelsync=1&action=_build_logs">Build Log Manager</a>]
                  [<a href="$zero?skip-cpanelsync=1&action=_archive_ui">Archives/Backups</a>]
                </div>
END_POST_HR
            }
        };
    }

    if ( $easy->get_param('action') eq $easy->maketext(q{Save and build}) ) {
        $easy->set_param( 'action', 'save_and_build' );
    }

    if ( $easy->get_param('action') eq $easy->maketext(q{Save only (Do NOT build)}) ) {
        $easy->set_param( 'action', 'save_only' );
    }

    if ( $easy->get_param('save_and_build') ) {
        $easy->{'_'}{'from_profile'} = $easy->get_param('action') eq 'choose_apache' ? 1 : 0;
        $easy->set_param( 'action', 'save_and_build' );
    }

    my $method = exists $wizard_steps{ $easy->get_param('action') } ? $easy->get_param('action') : 'list_profiles';

    # Check if the current page is not part of the wizard.
    # In such case we by pass the wizard and call the page's template directly.
    if ( !exists $wizard_steps{$method} ) {
        print "Content-Type: text/html\n\n";

        # Call the corresponding method's '_tmpl' functions.
        my $tmpl_method = $method . "_tmpl";
        no strict 'refs';
        &$tmpl_method( $self, $easy, undef, $profile, $profile_setup, $zero );
        return;
    }

    ##
    # This is for php step.
    # If Turn off button is clicked to turn off the
    # old php version/ latest php version setting, then
    # direct the process to choose php step.
    # Direct to the next step (show basic options) otherwise.
    ##
    if (  !$self->pre_1134_version()
        && $easy->get_param('turn_off_old_new_php_setting') ) {

        $method = 'choose_php';
    }

    my $last_seen = $wizard_steps{$method}->{'order'} < $easy->get_param('last_seen') ? $easy->get_param('last_seen') : $wizard_steps{$method}->{'order'};
    $easy->set_param( 'last_seen', $last_seen );

    $self->{'breadcrumb_args'} = [ $zero, $method, \%wizard_steps, $last_seen, 1 ];

    ##
    #
    # DETOUR: The below if condition branches out to use new
    # template system to render the pages.
    #
    # Note: Old code is still kept (the code that follows the if condition) for
    # backward compatibility with 11.32.
    #
    ##

    # Check if requested web page is rendered through template
    if (
        !$self->pre_1134_version()
        && (   $method eq 'list_profiles'
            || $method eq 'choose_apache'
            || $method eq 'choose_php'
            || $method eq 'show_basic_opts'
            || $method eq 'show_all_opts' )
      ) {
        print "Content-Type: text/html\n\n";

        # Call the corresponding method's '_tmpl' functions.
        my $tmpl_method = $method . "_tmpl";
        no strict 'refs';
        &$tmpl_method( $self, $easy, $self->{'breadcrumb_args'}, $profile, $profile_setup );
        return;
    }

    # Render in old method if the web page is printed through perl.

    $self->{'name'} = qq{<span style="font-size:18px;font-weight: bold;">$wizard_steps{ $method }->{'name'}:</span>};

    my $icon = $wizard_steps{$method}->{'icon'} ? qq{<img src="$wizard_steps{ $method }->{'icon'}" align="absmiddle" /> } : '';

    my $pst_hr = exists $wizard_steps{$method}->{'post_hr'} ? $wizard_steps{$method}->{'post_hr'}->() : '';

    $self->_header($easy);
    print _breadcrumb( $self, $easy );
    print qq{<hr />$pst_hr<h3 style="font-size:24px;font-weight: bold;">$icon$wizard_steps{ $method }->{'short'}</h3>\n};
    print qq{<div style="margin-left: 20px;">\n};
    no strict 'refs';
    &{$method}( $self, $easy, $profile, $profile_setup, $zero );
    print qq{</div>\n};
    return;
}

sub __test_link {
    my ( $self, $easy, $zero, $next, $last_seen ) = @_;
    my $caller = ( caller(1) )[3];
    my ( $_form, $link ) = $self->get_html_hidden_state_minus( $easy, 'action', 'last_seen' );
    print qq{I am $caller(), goto <a href="$zero?action=$next&$link&last_seen=$last_seen">$next</a>()<br />\n};
}

sub _breadcrumb {
    my ( $self, $easy ) = @_;
    my ( $zero, $method, $methods_hr, $last_seen, $no_js ) = @{ $self->{'breadcrumb_args'} };
    return '' if $easy->get_param('action') eq 'save_and_build';

    my ( $_form, $link ) = $self->get_html_hidden_state_minus( $easy, 'action' );

    my @disp;
    my $form = <<"END_FORM";
<script language="JavaScript" type="text/javascript">
<!--
function gotonavstep ( selectedaction )
{
  document.navsteps.action.value = selectedaction ;
  document.navsteps.submit() ;
}
-->
</script>
<form name="navsteps" method="post" action="$zero">
$_form
END_FORM

    # left over from testing case 3626 idea, may be handy at some point
    my $box_left  = '';
    my $box_right = '';
    for my $func (
        sort { $methods_hr->{$a}{'order'} <=> $methods_hr->{$b}{'order'} }
        grep { exists $methods_hr->{$_}{'order'} }
        keys %{$methods_hr}
      ) {

        my $short = $methods_hr->{$func}{'order'} <= $last_seen ? 1 : 0;
        my $css_all = q{white-space:nowrap;list-style:none;display:inline;line-height:35px;padding: 5px;border-style: solid;border-width:1px;};
        if ( !$short ) {
            push @disp, qq{<li style="border-color:#CCCCCC;background-color:#E5E5E5;$css_all">$box_left$methods_hr->{ $func }{'order'}. $methods_hr->{ $func }{'short'}$box_right</li>};
        }
        elsif ( $func eq $method ) {
            push @disp, qq{<li style="border-color:#333333;color:#FFFFFF;background-color:#68818f;font-weight:bold;$css_all">$box_left$methods_hr->{ $func }{'order'}. $methods_hr->{ $func }{'short'}$box_right</li>};
        }
        else {
            if ($no_js) {
                push @disp, qq{<li style="border-color:#CCCCCC;background-color:#FAFAFA;$css_all"><a href="$zero?action=$func&$link">$box_left$methods_hr->{ $func }{'order'}. $methods_hr->{ $func }{'short'}</a>$box_right</li>};
            }
            else {
                push @disp, qq{<li style="border-color:#CCCCCC;background-color:#FAFAFA$css_all;"><a href="javascript:gotonavstep('$func')">$box_left$methods_hr->{ $func }{'order'}. $methods_hr->{ $func }{'short'}</a>$box_right</li>};
            }
        }
    }

    my $start = '<ul style="margin-left:15px;">';
    my $end   = "</ul>\n";
    my $sep   = q{<li style="list-style:none;display:inline;line-height:35px;"> &#8594; </li>};
    return $start . join( $sep, @disp ) . $end if $no_js;
    return $start . $form . join( $sep, @disp ) . '</form>' . $end;
}

sub _generate_form_part {
    my ( $easy, $profile_hr, $form_parts_hr, $params_ar, $form_parts_name, $bold_names ) = @_;
    $bold_names = 0 if !$bold_names;

    my @show;
    my %data;

    # prefs $params_ar is already in order
    for my $pns ( $form_parts_name eq 'prefs' ? @{$params_ar} : sort @{$params_ar} ) {
        if ( $form_parts_name ne 'prefs' ) {
            $data{$pns} = $easy->get_easyconfig_hr_from_ns_variations($pns);
            next if !$data{$pns} || !keys %{ $data{$pns} };
            push @show, $pns unless ( $data{$pns}->{'skip'} || $data{$pns}->{'display_hide'} );
        }
        else {
            $data{$pns} = $easy->{'prefs_details'}{$pns};
            $data{$pns}{'am_i_on'} = sub {
                my ( $easy, $name ) = @_;
                return $easy->{'_'}{'prefs'}{$name} ? 1 : 0;
            };
            push @show, $pns;
        }
    }

    return if !@show;

    my $options_table_class = qq{class="optionsList"} if $form_parts_name ne 'prefs';

    $form_parts_hr->{$form_parts_name} = <<"END_FORM";
     <table $options_table_class border="0">
       <tr valign="top">
         <td>
           <table border="0">
END_FORM
    my @verify_options;
    my $count = 0;
    for my $ns (@show) {
        $count++;

        my $url  = '';
        my $note = '';

        my $from_param = 0;
        my $on =
          ref $data{$ns}->{'am_i_on'} eq 'CODE'
          ? $data{$ns}->{'am_i_on'}->( $easy, $ns )
          : $easy->get_ns_value_from_profile( $ns, $profile_hr );

        if ( defined $easy->get_param($ns) ) {
            $from_param = 1;
            $on = $easy->get_param($ns) ? 1 : 0;
        }

        my $checked = $on ? ' checked="checked"' : '';
        if ( $data{$ns}->{'reverse'} && !$from_param ) {
            $checked = $on ? '' : ' checked="checked"';
        }

        $data{$ns}->{'name'} = $ns if !$data{$ns}->{'name'};

        if ( $data{$ns}->{'url'} ) {
            $url = $data{$ns}->{'url'};
            my $uri_vers = $easy->{'apache_uri_version_lookup'}{ $easy->{'working_profile'}{'Apache'}{'version'} };
            $url =~ s{\[\% apache_uri_version \%\]}{$uri_vers}g;
            $url = qq{[<a target="_blank" href="$url" style="font-weight:normal;">$docu_icon</a>]};
        }

        my $name =
          $data{$ns}->{'reverse'}
          ? qq(<span class="caution">$data{ $ns }->{'name'}</span>)
          : $data{$ns}->{'name'};

        $note = $data{$ns}->{'note'} if $data{$ns}->{'note'};

        # Verify the user indeed wants to select this option on of off
        if ( $data{$ns}->{'verify_on'} || $data{$ns}->{'verify_off'} ) {

            my %verify_option_cfg = build_verify_data( $easy, $data{$ns}, "$ns" );

            if ( scalar( keys %verify_option_cfg ) > 0 ) {
                push( @verify_options, \%verify_option_cfg );
            }
        }

        if ( $data{$ns}->{'support'} ) {
            my $gap  = '&nbsp;' x 3;
            my $deco = get_short_deco( $data{$ns}->{'support'} );
            $name .= "$gap<i>$deco</i>$gap";
        }

        $name .= " $url" if $url;
        $name .= _last_failed_html( $easy, $ns );
        my $name_style = $bold_names ? ' style="font-weight:bold;"' : '';

        $form_parts_hr->{$form_parts_name} .= <<"END_PARAM";
            <tr>
                <td>
                    <input type="checkbox" id="$ns" name="$ns" value="1"$checked />
                </td>
                <td$name_style>
                    <label for="$ns">
                        $name
                    </label>
                </td>
            </tr>
END_PARAM

        if ($note) {
            $form_parts_hr->{$form_parts_name} .= <<"END_PARAM_A";
            <tr>
              <td>&nbsp;</td>
              <td style="width:500px; font-style: italic;">$note</tr>
            </tr>
            <tr>
              <td colspan="2">&nbsp;</tr>
            </tr>
END_PARAM_A
        }
    }

    # Add the verify options list to form_parts
    $form_parts_hr->{"verify_options"} = \@verify_options;

    $form_parts_hr->{$form_parts_name} .= <<'END_FORM';
           </table>
         </td>
       </tr>
     </table>
END_FORM

}

sub _last_failed_html {
    my ( $easy, $ns ) = @_;
    return '' if !exists $easy->{'last_failed'}{$ns};
    return qq{ <a href="javascript:display_quickpopupbox('Issues last time','<iframe height=90% width=100% src=easyapache.pl?skip-cpanelsync=1&action=_last_run&ns=$ns />')"><img src="/images/reject.gif" border="0" /> click here for details</a>};
}

################### New TEMPLATE UTILITY methods ###################

# This function constructs data structure for the list of steps in
# the EA wizard.
sub get_wizard_steps {
    my ( $self, $easy, $nav_args ) = @_;
    my ( $page_url, $method, $methods_hr, $last_seen ) = @{$nav_args};
    return '' if $easy->get_param('action') eq 'save_and_build';

    my @wizard_steps;

    for my $func (
        sort { $methods_hr->{$a}{'order'} <=> $methods_hr->{$b}{'order'} }
        grep { exists $methods_hr->{$_}{'order'} }
        keys %{$methods_hr}
      ) {

        my $visited = $methods_hr->{$func}{'order'} <= $last_seen ? 1 : 0;

        my %step = (
            'stepKey'   => $func,
            'stepOrder' => $methods_hr->{$func}{'order'},
            'stepName'  => $methods_hr->{$func}{'short'},
            'isVisited' => $visited,
            'isCurrent' => $func eq $method
        );

        push @wizard_steps, \%step;
    }

    return \@wizard_steps;
}

sub old_list_profiles_tmpl {
    my ( $self, $easy, $wizard_nav_data, $profiles_hr, $order_ar, $args_for_tmpl ) = @_;
    my ($form_data) = $self->get_ea_config_data( $easy, qw( action profile) );

    # Construct the profile list hash
    my @profiles_list;
    my $chosen = exists $profiles_hr->{ $easy->get_param('profile') } ? $easy->get_param('profile') : $easy->{'profile_main'};

    # Filter to identify new profiles.
    my $new_profile_filter = "cpanel_centos|cpanel_cloud";

    for my $idx ( 0 .. scalar( @{$order_ar} - 1 ) ) {

        # Filter out new profiles.
        next if $order_ar->[$idx] =~ m{^$new_profile_filter};

        my %profile_data;

        my ( $is_selected, $is_custom ) = ( $order_ar->[$idx] eq $chosen ? 1 : 0, 0 );

        my $name = $profiles_hr->{ $order_ar->[$idx] }{'_meta'}{'name'};
        my $note = $profiles_hr->{ $order_ar->[$idx] }{'_meta'}{'note'};

        if ( $order_ar->[$idx] !~ m{^cpanel_} && $order_ar->[$idx] ne $easy->{'profile_main'} ) {
            $is_custom = 1;
        }

        # Fill in the profile hash with above collected data.
        %profile_data = (
            'index'       => $idx,
            'profileKey'  => $order_ar->[$idx],
            'profileName' => $name,
            'profileDesc' => $note,
            'isSelected'  => $is_selected,
            'isCustom'    => $is_custom
        );

        push @profiles_list, \%profile_data;
    }

    # get_wizard_nav_data
    my $wizard_steps = get_wizard_steps( $self, $easy, $wizard_nav_data );
    my ( $page_url, $step_key, $steps_hr ) = @{$wizard_nav_data}[ 0 .. 2 ];

    my $step_data = $steps_hr->{$step_key};

    my $tmpl_args = {
        'template_file' => 'list_profiles_old.tmpl',
        'data'          => {
            'wizard' => {
                'pageUrl'     => $page_url,
                'nextStepKey' => 'choose_apache',
                'formData'    => $form_data,
                'wizardSteps' => $wizard_steps,
            },

            'page' => {
                'header'    => $easy->{'powered_by_line'},
                'stepTitle' => $step_data->{'short'},
                'stepDesc'  => $step_data->{'name'},
                'eaHelpUrl' => 'http://go.cpanel.net/eaissues',
                'warnings'  => {
                    'doUpdate'     => $args_for_tmpl->{'cp_update'},
                    'updateUrl'    => $args_for_tmpl->{'upcp'},
                    'isOpenSslBug' => $args_for_tmpl->{'is_open_ssl_bug'},
                    'optOpenssl'   => $args_for_tmpl->{'opt_openssl'},
                },
                'profilesList'   => \@profiles_list,
                'showDetailText' => $show_icon,
                'hideDetailText' => $hide_icon,
                'aboutProfiles'  => $Cpanel::Easy::Apache::UI::HTML::layover_safe_profile_details,
            }
        }
    };

    Cpanel::Template::process_template(
        'whostmgr',
        $tmpl_args,
        { 'include_path' => "/var/cpanel/perl/easy/Cpanel/Easy/easy_apache_ui" }
    );
    return;
}

# This function gets all the required data for constructing and working
# with Profiles step in EA wizard.
sub list_profiles_tmpl {
    my ( $self, $easy, $wizard_nav_data, $profile, $profile_setup, $page_url ) = @_;

    $easy->set_state_of_spec_includes_from_system($profile_setup);

    my ( $cp_update, $is_open_ssl_bug, $opt_openssl ) = ( 0, 0, 0 );

    my $cpanel_version = $easy->get_cpanel_version();
    $cpanel_version = $cpanel_version =~ m{^(\d+([.]\d+)?).*} ? $1 : 0;

    my ( $eleven, $cpanel_version_sub, @others ) = split( /\./, $cpanel_version );

    my $upcp = $cpanel_version < 11.28 ? 'upcp' : 'upcp2';

    if ( $easy->{'_'}{'Cpanel::Easy::Utils::cPVers out of date'} ) {
        $cp_update = 1;
    }

    if ( $easy->openssl_bug_check() ) {
        $is_open_ssl_bug = 1;
    }

    if ( -d '/opt/openssl' ) {
        $opt_openssl = 1;
    }

    my $profiles_hr = $self->get_profiles_hashref($easy);
    my $order_ar    = $self->get_profiles_order_arrayref($easy);

    ##
    # Branch out to call old_list_profiles_tmpl, if cPanel version is
    # anywhere between 11.34 and 1138 inclusive of both.
    ##
    if ($IS_1134_to_1138) {
        my $args_for_tmpl = {
            'open_ssl'    => $is_open_ssl_bug,
            'opt_openssl' => $opt_openssl,
            'cp_update'   => $cp_update,
            'upcp'        => $upcp
        };
        old_list_profiles_tmpl( $self, $easy, $wizard_nav_data, $profiles_hr, $order_ar, $args_for_tmpl );
        return;
    }

    my $cloud_linux_installed = Cpanel::Easy::Utils::CloudLinux::has_cloudlinux_support();

    my $filter                  = $cloud_linux_installed ? "cloud" : "centos";
    my $profile_filter          = "cpanel_$filter";
    my $is_cloudlinux_supported = 1;
    my $is_centos7_plus         = 0;

    if ( !$cloud_linux_installed ) {
        $is_cloudlinux_supported = Cpanel::Easy::Utils::CloudLinux::is_cloudlinux_supported();

        # Check for cent os 7+ version for CentOS machines only if cloudlinux is not installed.
        $is_centos7_plus = ( $easy->is_redhat() && $easy->{'getos_releaseversion'} >= 7 );
    }

    # Construct the profile list hash
    my ( $defaultp, $standardp, $customp ) = $self->differentiate_profiles( $easy, $cloud_linux_installed );
    my @default_profile   = @{$defaultp};
    my @standard_profiles = @{$standardp};
    my @custom_profiles   = @{$customp};

    my $tmpl_args = {
        'template_file' => 'list_profiles.tmpl',
        'data'          => {
            'wizard' => {
                'pageUrl'     => $page_url,
                'nextStepKey' => 'choose_apache',

                # 'formData'    => $form_data,
            },

            'page' => {
                'header'                 => $easy->{'powered_by_line'},
                'isCloudLinux'           => $cloud_linux_installed,
                'isCloudLinuxSupported'  => $is_cloudlinux_supported,
                'is_centos7_plus'        => $is_centos7_plus,
                'eaHelpUrl'              => 'http://go.cpanel.net/eaissues',
                'purchaseCloudlinuxData' => $easy->{'purchase_cloudlinux_data'},
                'cpanel_version_sub'     => $cpanel_version_sub,
                'warnings'               => {
                    'doUpdate'     => $cp_update,
                    'updateUrl'    => $upcp,
                    'isOpenSslBug' => $is_open_ssl_bug,
                    'optOpenssl'   => $opt_openssl,
                },
                'profilesList' => {
                    'defaultProfile'      => \@default_profile,
                    'standardProfileList' => \@standard_profiles,
                    'customProfileList'   => \@custom_profiles,
                },
                'aboutProfiles' => $Cpanel::Easy::Apache::UI::HTML::layover_safe_profile_details,
            }
        }
    };

    Cpanel::Template::process_template(
        'whostmgr',
        $tmpl_args,
        { 'include_path' => "/var/cpanel/perl/easy/Cpanel/Easy/easy_apache_ui" }
    );
    return;
}

# This function gets all the required data for constructing and working
# with Apache step in EA wizard.
sub choose_apache_tmpl {
    my ( $self, $easy_apache, $wizard_nav_data, $profile, $profile_setup ) = @_;
    $self->merge_profile( $easy_apache, $profile, $profile_setup );

    # get_wizard_nav_data
    my $wizard_steps = get_wizard_steps( $self, $easy_apache, $wizard_nav_data );

    my ( $page_url, $step_key, $steps_hr ) = @{$wizard_nav_data}[ 0 .. 2 ];

    my $step_data = $steps_hr->{$step_key};

    my $form_data = $self->get_ea_config_data( $easy_apache, qw( action apache) );

    # Get available apache versions.
    my ( $apv_hr, $ord_ar, $current_version ) = $self->get_apache_hashref_order_and_current($easy_apache);

    # Get full version name of currently used version.
    $current_version = $easy_apache->_get_httpd_version();

    # Get full version name of the version in profile.
    my $profile_full_version = get_full_apache_version( $profile_setup->{'Apache'}{'version'}, $apv_hr );

    my ( $selected_apache_ver, $ea_sld_url ) = ( '', $Cpanel::Easy::Apache::Utils::Support::URL );

    my @verify_options;
    my @version_list;

    for my $version ( @{$ord_ar} ) {
        my %version_data;

        my $full_version = get_full_apache_version( $version, $apv_hr ) || $version;

        my $is_selected = $easy_apache->get_param('apache') eq $version ? 1 : 0;

        # Select the version from profile when this page is loaded first time during
        # the wizard process.
        if ( !exists $apv_hr->{ $easy_apache->get_param('apache') }
            && $profile_setup->{'Apache'}{'version'} eq $version ) {

            $is_selected = 1;
        }

        # Save the selected version to use it in js for verify functionality.
        if ($is_selected) {
            $selected_apache_ver = $version;
        }

        # Get the configuration for each version which tells if a
        # verification is needed to select/unselect it.
        my %verify_option_cfg = build_verify_data( $self, $apv_hr->{$version}, "apache_$version" );

        # If the current version should be verified, add
        # it to the verify list.
        if ( scalar( keys %verify_option_cfg ) > 0 ) {
            push( @verify_options, \%verify_option_cfg );
        }

        %version_data = (
            'versionKey'  => $version,
            'versionName' => $full_version,
            'versionDesc' => $apv_hr->{$version}{'note'},
            'isSelected'  => $is_selected,
            'isEOL'       => ( defined $apv_hr->{$version}{support} && $apv_hr->{$version}{support} == $ENDOFLIFE ? 1 : 0 ),    # Boolean value if the version of Apache is "End of Life" or not
        );

        push @version_list, \%version_data;
    }

    my $json_verify_versions = JSON::Syck::Dump( \@verify_options );

    my $tmpl_args = {
        'template_file' => 'list_apache.tmpl',
        'data'          => {
            'wizard' => {
                'pageUrl'     => $page_url,
                'wizardSteps' => $wizard_steps,
                'nextStepKey' => 'choose_php',
                'formData'    => $form_data,
            },

            'page' => {
                'header'          => $easy_apache->{'powered_by_line'},
                'stepTitle'       => $step_data->{'short'},
                'stepDesc'        => $step_data->{'name'},
                'showDetailText'  => $show_icon,
                'hideDetailText'  => $hide_icon,
                'eaSldUrl'        => $ea_sld_url,
                'usedVersion'     => $current_version,
                'profileVersion'  => $profile_full_version,
                'selectedVersion' => $selected_apache_ver,
                'versionList'     => \@version_list,
                'verifyVersions'  => $json_verify_versions,
            }
        }
    };

    Cpanel::Template::process_template(
        'whostmgr',
        $tmpl_args,
        { 'include_path' => "/var/cpanel/perl/easy/Cpanel/Easy/easy_apache_ui" }
    );
    return;
}

# This function gets all the required data for constructing and working
# with Php step in EA wizard.
sub choose_php_tmpl {
    my ( $self, $easy_apache, $wizard_nav_data, $profile, $profile_setup ) = @_;

    # get_wizard_nav_data
    my $wizard_steps = get_wizard_steps( $self, $easy_apache, $wizard_nav_data );

    my ( $page_url, $step_key, $steps_hr ) = @{$wizard_nav_data}[ 0 .. 2 ];

    my $step_data = $steps_hr->{$step_key};

    my $form_data = $self->get_ea_config_data( $easy_apache, qw( action php5 turn_off_old_new_php_setting) );

    # update working profile with version that has actually been selected
    $profile_setup->{Apache}->{version} = $form_data->{'apache'} if ( $form_data->{'apache'} =~ m/2_2|2_4/ );

    my $selected_version = '';
    my @installed;

    if ( @installed = $self->get_current_php_versions($easy_apache) ) {
        @installed = grep( s/^(\d).*/$1/, @installed );
    }

    my %old_new_php_settings;

    if ( $easy_apache->get_param('turn_off_old_new_php_setting') ) {
        $easy_apache->set_param( 'turn_off_old_new_php_setting', 0 );

        $easy_apache->{'_'}{'prefs'}{'always_do_the_latest_phps'} = 0;
        $easy_apache->set_param( 'always_do_the_latest_phps', 0 );
        $easy_apache->{'_'}{'prefs'}{'always_do_the_oldest_phps'} = 0;
        $easy_apache->set_param( 'always_do_the_oldest_phps', 0 );

        my $pr_hr = $easy_apache->deserialize( $easy_apache->{'prefs_file'} );
        $pr_hr->{'always_do_the_latest_phps'} = 0;
        $pr_hr->{'always_do_the_oldest_phps'} = 0;

        $easy_apache->serialize( $easy_apache->{'prefs_file'}, $pr_hr );
    }

    my @version_list;
    my %support_info;
    my $php_namespace = "Cpanel::Easy::PHP5";

    ##
    # $none_from_profile - Set to true if the selected profile to customize, has
    #                      "no php" option.
    ##
    my $none_from_profile = !$easy_apache->get_ns_value_from_profile( $php_namespace, $profile );

    if ( $easy_apache->{'_'}{'prefs'}{'always_do_the_oldest_phps'} || $easy_apache->{'_'}{'prefs'}{'always_do_the_latest_phps'} ) {
        eval qq{ require $php_namespace; };
        my $version_key = $easy_apache->{'_'}{'prefs'}{'always_do_the_latest_phps'} ? $php_namespace->latest_version() : $php_namespace->oldest_version();
        my $version_name = "5.$version_key";
        $version_name =~ s{\_}{.}g;

        my $selected = "";

        if ( !$none_from_profile ) {
            $selected = $version_key;
        }

        my ( $do_latest, $do_oldest ) = ( 0, 0 );

        if ( $easy_apache->{'_'}{'prefs'}{'always_do_the_latest_phps'} ) {
            $do_latest = 1;
        }
        else {
            $do_oldest = 1;
        }

        %old_new_php_settings = (
            "versionKey"      => $version_key,
            "selectedVersion" => $selected,
            "versionName"     => $version_name,
            "doOldest"        => $do_oldest,
            "doLatest"        => $do_latest,
            "supportText"     => Cpanel::Easy::PHP5::support_decoration($version_key),
        );

        my $support_level = Cpanel::Easy::PHP5::support_level($version_key);
        if ($support_level) {
            $support_info{$support_level} = '* ' . Cpanel::Easy::PHP5::support_text($version_key);
        }
    }
    else {

        my $cur_php = Cpanel::LoadFile::loadfile('/usr/local/apache/conf/php.version');
        chomp $cur_php;

        eval qq{ require $php_namespace; };

        ##
        # $none_from_param - Set to true if none is selected while
        #                    customizing the profile using wizard navigation.
        ##
        my ( $param_exists, $none_from_param, $php_param ) = ( 0, 0, "" );

        if ( grep( /^php5$/, $easy_apache->{'param_obj'}->param() ) ) {
            $param_exists    = 1;
            $php_param       = $easy_apache->get_param('php5');
            $none_from_param = $php_param eq "" ? 1 : 0;
        }

        my @versions = $php_namespace->versions();

        # Evaluate the selected PHP version.
        my $selected_version_set = 0;
        for my $version_key (@versions) {

            # Make sure the selected version is set only once
            if ( !$selected_version_set ) {

                # Check if a php version is selected during the wizard navigation.
                # Set a flag so to make sure nothing else is filled in $selected_version
                # if none(empty string) is selected.
                if ($param_exists) {    # An info msg will be helpful to display if this condition fails
                    if ( $php_param eq $version_key ) {
                        $selected_version     = $version_key;
                        $selected_version_set = 1;
                    }
                }
                elsif ( !$none_from_profile && $profile_setup->{ 'Cpanel::Easy::PHP5::' . $version_key } ) {
                    $selected_version     = $version_key;
                    $selected_version_set = 1;
                }
            }

            my %version_data;
            my $version_name = "5.$version_key";
            $version_name =~ s{\_}{\.}g;

            # Get the decoration string for the current php version
            # (i.e. Deprecated/EOL etc.)
            my $support_decoration = Cpanel::Easy::PHP5::support_decoration($version_key);

            %version_data = (
                'versionKey'        => $version_key,
                'versionName'       => $version_name,
                'supportDecoration' => Cpanel::Easy::PHP5::support_decoration($version_key)
            );

            my $support_level = Cpanel::Easy::PHP5::support_level($version_key);
            if ($support_level) {
                $support_info{$support_level} = '* ' . Cpanel::Easy::PHP5::support_text($version_key);
            }

            push @version_list, \%version_data;
        }

        # The latest php version is selected as a final fallback if:
        #   1. Php in profile is not supported by the current EA
        #   2. Php set in the param(some way other than the UI) is not supported by the current EA
        if ( !$none_from_param && !$none_from_profile && !$selected_version ) {
            $selected_version = $php_namespace->latest_version($profile_setup);
        }
    }

    my $cloud_linux_installed   = Cpanel::Easy::Utils::CloudLinux::has_cloudlinux_support();
    my $is_cloudlinux_supported = 1;

    if ( !$cloud_linux_installed ) {
        $is_cloudlinux_supported = Cpanel::Easy::Utils::CloudLinux::is_cloudlinux_supported();
    }

    my $tmpl_args = {
        'template_file' => 'list_php.tmpl',
        'data'          => {
            'wizard' => {
                'pageUrl'     => $page_url,
                'wizardSteps' => $wizard_steps,
                'nextStepKey' => 'show_basic_opts',
                'formData'    => $form_data,
            },

            'page' => {
                'header'                 => $easy_apache->{'powered_by_line'},
                'stepTitle'              => $step_data->{'short'},
                'stepDesc'               => $step_data->{'name'},
                'showDetailText'         => $show_icon,
                'hideDetailText'         => $hide_icon,
                'helpUrl'                => $Cpanel::Easy::Apache::Utils::Support::URL,
                'mainPhpVersion'         => $easy_apache->{'state'}{'optmods'}{$php_namespace}{'name'},
                'selectedVersion'        => $selected_version,
                'oldNewPhpSettings'      => \%old_new_php_settings,
                'versionList'            => \@version_list,
                'supportInfo'            => \%support_info,
                'installedVersionList'   => \@installed,
                'cloudLinuxInstalled'    => $cloud_linux_installed,
                'isCloudLinuxSupported'  => $is_cloudlinux_supported,
                'purchaseCloudlinuxData' => $easy_apache->{'purchase_cloudlinux_data'}
            }
        }
    };

    Cpanel::Template::process_template(
        'whostmgr',
        $tmpl_args,
        { 'include_path' => "/var/cpanel/perl/easy/Cpanel/Easy/easy_apache_ui" }
    );

    return;
}

# This function gets all the required data for optional modules
# for a specified software (apache, php etc).
sub get_optmods_data {
    my ( $easy, $profile_hr, $params_ar, $form_parts_name, $bold_names ) = @_;
    $bold_names = 0 if !$bold_names;

    my @show;
    my %data;

    # prefs $params_ar is already in order
    for my $pns ( $form_parts_name eq 'prefs' ? @{$params_ar} : sort @{$params_ar} ) {
        if ( $form_parts_name ne 'prefs' ) {
            $data{$pns} = $easy->get_easyconfig_hr_from_ns_variations($pns);
            next if !$data{$pns} || !keys %{ $data{$pns} };
            push @show, $pns unless ( $data{$pns}->{'skip'} || $data{$pns}->{'display_hide'} );
        }
        else {
            $data{$pns} = $easy->{'prefs_details'}{$pns};
            $data{$pns}{'am_i_on'} = sub {
                my ( $easy, $name ) = @_;
                return $easy->{'_'}{'prefs'}{$name} ? 1 : 0;
            };
            push @show, $pns;
        }

    }
    return if !@show;

    my ( @verify_options, @opt_mod_list );

    for my $ns (@show) {
        my ( $url, $opt_mod_desc, $from_param ) = ( "", "", 0 );

        my $on =
          ref $data{$ns}->{'am_i_on'} eq 'CODE'
          ? $data{$ns}->{'am_i_on'}->( $easy, $ns )
          : $easy->get_ns_value_from_profile( $ns, $profile_hr );

        if ( defined $easy->get_param($ns) ) {
            $from_param = 1;
            $on = $easy->get_param($ns) ? 1 : 0;
        }

        my $is_selected = $on ? 1 : 0;
        if ( $data{$ns}->{'reverse'} && !$from_param ) {
            $is_selected = $on ? 0 : 1;
        }

        my $is_reverse = $data{$ns}->{'reverse'};

        $data{$ns}->{'name'} = $ns if !$data{$ns}->{'name'};

        if ( $data{$ns}->{'url'} ) {
            $url = $data{$ns}->{'url'};
            my $uri_vers = $easy->{'apache_uri_version_lookup'}{ $easy->{'working_profile'}{'Apache'}{'version'} };

            $url =~ s{\[\% apache_uri_version \%\]}{$uri_vers}g;
        }

        # REFACTOR: $opt_mod_desc should return only description text.
        # Disable/Enable modules should be returned as its own list.
        $opt_mod_desc = $data{$ns}->{'note'} if $data{$ns}->{'note'};

        # Verify if the user indeed wants to select this option on or off
        if ( $data{$ns}->{'verify_on'} || $data{$ns}->{'verify_off'} ) {
            my %verify_option_cfg = build_verify_data( $easy, $data{$ns}, "$ns" );

            if ( scalar( keys %verify_option_cfg ) > 0 ) {
                push( @verify_options, \%verify_option_cfg );
            }
        }

        my $support_level = "";
        if ( $data{$ns}->{'support'} ) {
            my $gap = '&nbsp;' x 3;
            $support_level = get_short_deco( $data{$ns}->{'support'} );
        }

        my $last_run_failed = exists $easy->{'last_failed'}{$ns};
        my %opt_mod_cfg     = (
            "key"           => $ns,
            "name"          => $data{$ns}->{'name'},
            "url"           => $url,
            "isSelected"    => $is_selected,
            "isReverse"     => $is_reverse,
            "lastRunFailed" => $last_run_failed,
            "supportLevel"  => $support_level,
            "desc"          => $opt_mod_desc
        );

        # Add this cfg to opt mod list
        push( @opt_mod_list, \%opt_mod_cfg );
    }
    return ( \@opt_mod_list, \@verify_options );
}

# This function gets all the required data for constructing and working
# with Short options list in EA wizard.
sub show_basic_opts_tmpl {
    my ( $self, $easy_apache, $wizard_nav_data, $profile, $profile_setup ) = @_;
    $self->merge_profile( $easy_apache, $profile, $profile_setup );

    # get_wizard_nav_data
    my $wizard_steps = get_wizard_steps( $self, $easy_apache, $wizard_nav_data );

    my ( $page_url, $step_key, $steps_hr ) = @{$wizard_nav_data}[ 0 .. 2 ];

    my $step_data = $steps_hr->{$step_key};

    my @php_param;
    my $pns = 'Cpanel::Easy::PHP5';
    eval qq{require $pns;};
    my @versions = $pns->versions();

    # Remove old versions from profile
    foreach my $ns ( keys %$profile_setup ) {
        delete $profile_setup->{$ns} if ( $ns =~ /^\Q$pns\E::\d+_\d+$/ );
    }

    # Set current version so modself kicks off
    my $selected = $easy_apache->get_param('php5');

    my $found = 0;
    foreach my $ver (@versions) {
        my $subns = "${pns}::${ver}";
        $easy_apache->set_ns_value_in_profile( $subns, $profile_setup, ( $ver eq $selected ? 1 : 0 ) );
        $found = 1 if $ver eq $selected;
    }
    $easy_apache->set_ns_value_in_profile( $pns, $profile_setup, $found );
    push @php_param, '5' if $found;
    $easy_apache->set_param( 'php', @php_param );

    my $invalid_apache = 0;
    if ( !exists $easy_apache->{'state'}{'optmods'}{'Apache'}{'_main'}{ $easy_apache->get_param('apache') } ) {
        my $def = $profile_setup->{'Apache'}{'version'};
        $invalid_apache = 1;
        $easy_apache->set_param( 'apache', $def );
    }

    $profile_setup->{'Apache'}{'version'} = $easy_apache->get_param('apache');
    $easy_apache->{'working_profile'} = $profile_setup;

    my %form_parts;

    my ( $apache_ar, $php5_ar, $non_php_includes_ar, $prefs_ar ) = $self->get_opt_params_lists($easy_apache);

    my ( $opt_mod_list, $verify_option_list ) = get_optmods_data( $easy_apache, $profile_setup, [ @{$non_php_includes_ar}, @{ $easy_apache->{'apache_ns_mods_in_basic'} } ], 'apache_sepcial', 1 );

    my %js_config = (
        "optionsTableClass" => "optionsList",
        "verifyOptions"     => $verify_option_list
    );

    my $json_js_config = JSON::Syck::Dump( \%js_config );

    my %param_lookup;
    @param_lookup{ @{ $easy_apache->{'apache_ns_mods_in_basic'} }, @{$non_php_includes_ar} } = ();

    my %opt_mod_form_data;

  LIST:
    for my $ar ( $apache_ar, $php5_ar ) {
      ITEM:
        for my $opt ( @{$ar} ) {
            next ITEM if exists $param_lookup{$opt};
            my $setting = defined $easy_apache->get_param($opt) ? $easy_apache->get_param($opt) : $easy_apache->get_ns_value_from_profile( $opt, $profile_setup );
            $setting = $setting ? 1 : 0;

            my $ec = $easy_apache->get_easyconfig_hr_from_ns_via_state($opt);
            if ( $ec->{'reverse'} ) {
                $setting = $setting ? 0 : 1;
            }

            $opt_mod_form_data{$opt} = $setting;
        }
    }

    my $prefs = $easy_apache->deserialize( $easy_apache->{'prefs_file'} );

    my @params = ( "action", "turn_off_old_new_php_setting", @{$non_php_includes_ar}, @{ $easy_apache->{'apache_ns_mods_in_basic'} } );
    my $form_data = $self->get_ea_config_data( $easy_apache, @params );

    my $tmpl_args = {
        'template_file' => 'short_options.tmpl',
        'data'          => {
            'wizard' => {
                'pageUrl'     => $page_url,
                'wizardSteps' => $wizard_steps,
                'nextStepKey' => 'show_all_opts',
                'formData'    => $form_data,
            },

            'page' => {
                'header'         => $easy_apache->{'powered_by_line'},
                'stepTitle'      => $step_data->{'short'},
                'stepDesc'       => $step_data->{'name'},
                'invalidApache'  => $invalid_apache,
                'optModFormData' => \%opt_mod_form_data,
                "optModList"     => $opt_mod_list,
                'preferences'    => $prefs,
                'verifyOptions'  => $json_js_config,
            }
        }
    };

    Cpanel::Template::process_template(
        'whostmgr',
        $tmpl_args,
        { 'include_path' => "/var/cpanel/perl/easy/Cpanel/Easy/easy_apache_ui" }
    );
    return;    # false means no build yet
}

# This function gets all the required data for constructing and working
# with All options list in EA wizard.
sub show_all_opts_tmpl {
    my ( $self, $easy_apache, $wizard_nav_data, $profile, $profile_setup ) = @_;
    $self->merge_profile( $easy_apache, $profile, $profile_setup );

    # get_wizard_nav_data
    my $wizard_steps = get_wizard_steps( $self, $easy_apache, $wizard_nav_data );

    my ( $page_url, $step_key, $steps_hr ) = @{$wizard_nav_data}[ 0 .. 2 ];

    my $step_data = $steps_hr->{$step_key};

    ##
    # Set the selected PHP version in php step
    ##
    my $is_php5 = grep( /^5$/, $easy_apache->get_param('php') ) ? 1 : 0;
    my $php5_ns = 'Cpanel::Easy::PHP5';

    $easy_apache->set_ns_value_in_profile( $php5_ns, $profile_setup, $is_php5 );

    if ($is_php5) {

        # Remove old versions from profile
        foreach my $ns ( keys %$profile_setup ) {
            delete $profile_setup->{$ns} if ( $ns =~ /^\Q$php5_ns\E::\d+_\d+$/ );
        }

        # Set current version so modself kicks off
        my $selected = $easy_apache->get_param('php5');
        eval qq{require $php5_ns;};
        my @versions = $php5_ns->versions();

        # Turn on the correct PHP5 version in the profile and turn off the remaining versions.
        foreach my $ver (@versions) {
            my $subns = "${php5_ns}::${ver}";
            $easy_apache->set_ns_value_in_profile( $subns, $profile_setup, ( $ver eq $selected ? 1 : 0 ) );
        }
    }

    ##
    # Set the selected Apache version in apache step
    ##
    my $invalid_apache = 0;
    my $profile_apache = "";
    if ( !exists $easy_apache->{'state'}{'optmods'}{'Apache'}{'_main'}{ $easy_apache->get_param('apache') } ) {
        my $profile_apache = $profile_setup->{'Apache'}{'version'};
        $invalid_apache = 1;
        $easy_apache->set_param( 'apache', $profile_apache );
    }

    $profile_setup->{'Apache'}{'version'} = $easy_apache->get_param('apache');

    # set unchecked ones to zero
    for my $apo ( keys %{ $profile_setup->{'Apache'}{'optmods'} } ) {
        $profile_setup->{'Apache'}{'optmods'}{$apo} = $easy_apache->get_param( 'Cpanel::Easy::Apache::' . $apo ) ? 1 : 0;
    }

    for my $opt ( keys %{$profile_setup} ) {
        next if $opt eq 'Apache' || $opt eq '_meta' || !defined( $easy_apache->get_param($opt) );
        $profile_setup->{$opt} = $easy_apache->get_param($opt) ? 1 : 0;
    }

    my ( $apache_ar, $php5_ar, $non_php_includes_ar, $prefs_ar ) = $self->get_opt_params_lists($easy_apache);
    for my $opt ( @{$non_php_includes_ar} ) {
        $profile_setup->{$opt} = $easy_apache->get_param($opt) ? 1 : 0;
    }

    $easy_apache->{'working_profile'} = $profile_setup;

    # # ??? Add change profile menu here or leave it out, can do after release
    my ( @resultOptions, @verify_options );

    ##
    # $opt_mod_list: is used to hold the optional module list for each software (apache/php etc.)
    # $verify_option_list is used to hold list of options which require a confirm verification popup
    ##
    my @full_opt_list;
    my ( $opt_mod_list, $verify_option_list ) = get_optmods_data( $easy_apache, $profile_setup, $apache_ar, 'apache' );
    if ($opt_mod_list) {
        push @full_opt_list,
          {
            "sectionKey"  => "apache",
            "sectionData" => $opt_mod_list
          };

        if ($verify_option_list) {
            @resultOptions = @{$verify_option_list};
            push @verify_options, @resultOptions;
        }
    }

    ( $opt_mod_list, $verify_option_list ) = get_optmods_data( $easy_apache, $profile_setup, $non_php_includes_ar, 'non_php_includes' );
    if ($opt_mod_list) {
        push @full_opt_list,
          {
            "sectionKey"  => "non_php_includes",
            "sectionData" => $opt_mod_list
          };

        if ($verify_option_list) {
            @resultOptions = @{$verify_option_list};
            push @verify_options, @resultOptions;
        }
    }

    if ($is_php5) {
        ( $opt_mod_list, $verify_option_list ) = get_optmods_data( $easy_apache, $profile_setup, $php5_ar, 'php5' );
        if ($opt_mod_list) {
            push @full_opt_list,
              {
                "sectionKey"  => "php5",
                "sectionData" => $opt_mod_list
              };

            if ($verify_option_list) {
                @resultOptions = @{$verify_option_list};
                push @verify_options, @resultOptions;
            }
        }
    }

    ( $opt_mod_list, $verify_option_list ) = get_optmods_data( $easy_apache, $profile_setup, $prefs_ar, 'prefs' );
    if ($opt_mod_list) {
        push @full_opt_list,
          {
            "sectionKey"  => "prefs",
            "sectionData" => $opt_mod_list
          };

        if ($verify_option_list) {
            @resultOptions = @{$verify_option_list};
            push @verify_options, @resultOptions;
        }
    }

    my @nav_index = (
        {
            'name'   => 'Apache',
            'anchor' => 'apache',
        },
        {
            'name'   => 'Other',
            'anchor' => 'non_php_includes',
        },
    );

    my %save_as_form_data;

    if ( $profile ne $easy_apache->{'profile_main'} ) {
        %save_as_form_data = (
            'save_as_ident' => $easy_apache->get_param('profile') =~ m{^cpanel_} ? '' : Cpanel::Encoder::html_encode_str( $easy_apache->get_param('profile') ),
            'save_as_name'  => Cpanel::Encoder::html_encode_str( $profile_setup->{'_meta'}{'name'} ),
            'save_as_desc'  => Cpanel::Encoder::html_encode_str( $profile_setup->{'_meta'}{'note'} ),

        );
    }

    for my $key (qw( save_as_ident save_as_name save_as_desc )) {
        $save_as_form_data{$key} = Cpanel::Encoder::html_encode_str( $easy_apache->get_param($key) ) if $easy_apache->get_param($key);
    }

    my $php_full_version = "5.";
    eval qq{use $php5_ns;};
    my @vrs = $php5_ns->versions();

    $php_full_version .= $easy_apache->get_param('php5') || ( grep { $profile_setup->{ $php5_ns . '::' . $_ } } @vrs )[0] || 'x';
    $php_full_version =~ s{\_}{\.}g;

    if ($is_php5) {
        push @nav_index,
          {
            'name'   => "PHP 5",
            'anchor' => "php5",
          };
    }

    # REFACTOR: Both pref & save can be added in one push.
    push @nav_index,
      {
        'name'   => 'Preferences',
        'anchor' => "prefs",
      };

    push @nav_index,
      {
        'name'   => 'Save As',
        'anchor' => 'save',
      };

    my %js_config = (
        "optionsTableClass" => "optionsList",
        "verifyOptions"     => \@verify_options
    );

    my $json_js_config = JSON::Syck::Dump( \%js_config );

    my $rgx       = qr(::);
    my @params    = ( "action", "save_as_ident", "save_as_name", "save_as_desc", @{$prefs_ar}, $rgx );
    my $form_data = $self->get_ea_config_data( $easy_apache, @params );

    my $tmpl_args = {
        'template_file' => 'full_options.tmpl',
        'data'          => {
            'wizard' => {
                'pageUrl'     => $page_url,
                'wizardSteps' => $wizard_steps,
                'formData'    => $form_data,
            },

            'page' => {
                'header'         => $easy_apache->{'powered_by_line'},
                'stepTitle'      => $step_data->{'short'},
                'stepDesc'       => $step_data->{'name'},
                'invalidApache'  => $invalid_apache,
                'profileApache'  => $profile_apache,
                'isPhp5'         => $is_php5,
                'phpFullVersion' => $php_full_version,
                'navIndex'       => \@nav_index,
                'fullOptList'    => \@full_opt_list,
                'saveAsFormData' => \%save_as_form_data,
                'verifyOptions'  => $json_js_config,
            }
        }
    };

    Cpanel::Template::process_template(
        'whostmgr',
        $tmpl_args,
        { 'include_path' => "/var/cpanel/perl/easy/Cpanel/Easy/easy_apache_ui" }
    );
    return;    # false means no build yet
}
################### END New TEMPLATE UTILITY methods ###################

#### configure_profile() %methods ##

sub list_profiles {
    my ( $self, $easy, $profile, $profile_setup, $zero ) = @_;
    $easy->set_state_of_spec_includes_from_system($profile_setup);

    my ( $profiles_hr, $order_ar ) = $self->get_profiles_hashref_and_order_arrayref($easy);

    my $warning   = '';
    my $js_config = qq/{
                        profileClassName : "profile",/;

    my $cpanel_version = $easy->get_cpanel_version();
    $cpanel_version = $cpanel_version =~ m{^(\d+([.]\d+)?).*} ? $1 : 0;
    my $upcp = $cpanel_version < 11.28 ? 'upcp' : 'upcp2';

    if ( $easy->{'_'}{'Cpanel::Easy::Utils::cPVers out of date'} ) {
        $warning .= q{<h3>Update Notice</h3><p>Your build is out of date as per the red message at the top of the page.</p><br /><p>For best results, you should <a href=\"../scripts/} . $upcp . q{\">update</a> before running easy apache.</p>};
    }

    my $url = 'http://go.cpanel.net/eaissues';
    if ( $easy->openssl_bug_check() ) {

        $warning .=
          qq{<h3>OpenSSL Bug Notice</h3><p>Your server may be using a version of OpenSSL that contains a serious bug that can prevent Apache 2.x from running properly. Before proceeding further, we ask that you please read the information provided at the following URL and take the proper steps to correct this issue on your server.</p><p> <a target=\\"_blank\\" href=\\"$url\\">$url</a></p>};

        # ADD URL TO CONFIG
        $js_config .= qq/ openSSLBug : true, eaHelpUrl : "$url",/;
    }

    if ( -d '/opt/openssl' ) {
        $warning .= qq{<h3>/opt/openssl will be used as the openssl prefix</h3><p>If you experience problems or want to go back to your system openssl <a target=\\"_blank\\" href=\\"$url#noopt\\">read this<a/> first.</p>};
    }

    if ($warning) {

        # ADD WARNING TO CONFIG
        $js_config .= qq/ warning : "$warning",/;
    }

    my $icon = -e '/usr/local/cpanel/whostmgr/docroot/images/reject.gif' ? q{<img align="absmiddle" src="/images/reject.gif">&nbsp;} : '';
    print <<"END_EA3";
     <div class="info_box">
      <span style="font-size:larger">Welcome to $easy->{'powered_by_line'}</span><br /><br />
      This tool will guide you through the available options for updating your Apache web server, PHP, and optional modules. [<a target="_blank" href="http://go.cpanel.net/ea">Read the documentation for further information</a>]
     <p>[<a href="?action=quickreference_guide&skip-cpanelsync=1">EasyApache Quick Reference guide</a>]</p>
     <br /><br />
       <div style="color:#f00; text-weight: 900;">
        $icon Before using EasyApache please be sure to <a target="_blank" href="http://go.cpanel.net/ea">read over the documentation</a>.<br />
        To avoid losing custom modifications to your apache configuration, you will need to move them to include files that the new configuration system uses.
        For more specific information on includes <a href="http://go.cpanel.net/easyapachecustom" target="_blank">please visit this page</a>.
       </div>
     </div>
     <br />
END_EA3

    print $self->{'name'}, "<br />\n";

    print $self->get_form_start(
        $easy,
        {
            'hidden_minus' => [qw( action profile)],
            'form_action'  => $zero,
            'new_action'   => 'choose_apache',
        },
    );

    print qq{<div style="margin-left: 20px;">};    # indent form
    my $chosen = exists $profiles_hr->{ $easy->get_param('profile') } ? $easy->get_param('profile') : $easy->{'profile_main'};

    # Filter to identify new profiles.
    my $new_profile_filter = "cpanel_centos|cpanel_cloud";

    for my $idx ( 0 .. scalar( @{$order_ar} - 1 ) ) {

        # Filter out new profiles.
        next if $order_ar->[$idx] =~ m{^$new_profile_filter};

        my $checked = $order_ar->[$idx] eq $chosen ? ' checked' : '';

        my $name = Cpanel::Encoder::html_encode_str( $profiles_hr->{ $order_ar->[$idx] }{'_meta'}{'name'} );
        my $note = Cpanel::Encoder::html_encode_str( $profiles_hr->{ $order_ar->[$idx] }{'_meta'}{'note'} );

        if ( $order_ar->[$idx] !~ m{^cpanel_} && $order_ar->[$idx] ne $easy->{'profile_main'} ) {
            $name .= qq{ [<a href="$zero?action=_delete_profile&del_profile=$order_ar->[$idx]">Delete</a>]};
        }

        $note .= qq{<p>[<a href="javascript:display_quickpopupbox('Profile Details','<iframe height=90% width=100% src=easyapache.pl?skip-cpanelsync=1&action=_human_readable&profile=$order_ar->[$idx] />')">Click here to view details</a>]};
        $note .= qq{ [<a href="javascript:display_quickpopupbox('Profile Raw - $order_ar->[$idx]','<iframe height=90% width=100% src=easyapache.pl?skip-cpanelsync=1&action=_human_readable&profile=$order_ar->[$idx]&raw=1 />')">Raw</a>]};
        $note .= qq{ [<a href="easyapache.pl?skip-cpanelsync=1&action=_human_readable&profile=$order_ar->[$idx]&raw=1&download=1">Download profile</a>]};
        $note .= qq{ [<a href="javascript:display_quickpopupbox('About Profiles','$Cpanel::Easy::Apache::UI::HTML::layover_safe_profile_details')">About Profiles</a>]</p>};
        my ( $l, $r, $d, $detailClass ) = ( $idx == 0 || $checked ) ? ( $show_icon, $hide_icon, 'block', $hide_det_class ) : ( $hide_icon, $show_icon, 'none', $show_det_class );
        print qq{<div class="profile">
                <input type="radio" id="profile_$idx" name="profile"
                    value="$order_ar->[ $idx ]"$checked />
                <label for="profile_$idx"> $name </label>
                [<a style="text-decoration:none; font-weight: 900;"
                    id="seedetails$idx" href="javascript:void(0);" class="$detailClass">
                        $r
                </a>]
                <br />
                <div style="width:500px; display:$d" class="description" id="conf_info$idx">
                    &#8593; $note
                </div>
            </div>\n};

    }

    print qq{</div>};    # /indent form
    print qq{<p><input type="submit" class="btn-primary primary default input-button" id="save_and_build" name="save_and_build" value="Build Profile" onClick="return CPANEL.ea.confirmBuild(this);" /> or };

    $js_config .= qq/ descLinkIdSuffix: "seedetails", buildButtonId : "save_and_build" }/;
    print $self->get_form_end( $easy, { 'submit' => 'Customize Profile', 'no_p' => 1, } );
    print qq{</p>\n};

    print <<"END_JS";
        <script type="text/javascript">
          <!--
            EVENT.onDOMReady(function(){
                var listProfiles = new CPANEL.ea.ListProfiles($js_config);
            });

          -->
        </script>
END_JS
    return;    # zero means no build yet
}

# This sub builds a hash for each given option
# if it has requirement to verify when switched on or off.
sub build_verify_data {
    my $self        = shift;
    my $apv_hr      = shift;
    my ($option_id) = @_;

    my %option_cfg;

    if ( $apv_hr->{'verify_on'} || $apv_hr->{'verify_off'} ) {
        my $on_txt = $apv_hr->{'verify_on'} ? Cpanel::Encoder::html_encode_str( $apv_hr->{'verify_on'} ) : '';
        my $on_url = $apv_hr->{'verify_on_url'} ? sprintf( q{<a target=\\'ap_help\\' href=\\'%s\\'>%s</a>}, $apv_hr->{'verify_on_url'}, $apv_hr->{'verify_on_url'} ) : '';
        my $off_txt = $apv_hr->{'verify_off'} ? Cpanel::Encoder::html_encode_str( $apv_hr->{'verify_off'} ) : '';
        my $off_url = $apv_hr->{'verify_off_url'} ? sprintf( q{<a target=\\'ap_help\\' href=\\'%s\\'>%s</a>}, $apv_hr->{'verify_off_url'}, $apv_hr->{'verify_off_url'} ) : '';

        my ( %on_obj, %off_obj );

        # Start building the configuration hash for the
        # current option.
        $option_cfg{'id'} = "$option_id";

        if ( $on_txt || $on_url ) {
            %on_obj = (
                'text' => "$on_txt",
                'url'  => "$on_url"
            );

            # Add this to option configuration
            $option_cfg{'onObj'} = \%on_obj;
        }

        if ( $off_txt || $off_url ) {
            %off_obj = (
                'text' => "$off_txt",
                'url'  => "$off_url"
            );

            # Add this to option configuration
            $option_cfg{'offObj'} = \%off_obj;
        }
    }
    return %option_cfg;
}

sub choose_apache {
    my ( $self, $easy, $profile, $profile_setup, $zero ) = @_;
    $self->merge_profile( $easy, $profile, $profile_setup );

    print $self->get_form_start(
        $easy,
        {
            'hidden_minus' => [qw( action apache )],
            'form_action'  => $zero,
            'new_action'   => 'choose_php',
        },
    );

    my ( $apv_hr, $ord_ar, $current ) = $self->get_apache_hashref_order_and_current($easy);

    my ( $choices, $selected_apache_ver, $option_block_class ) = ( '', '', 'version' );

    my %js_config = ( 'versionBlockClass' => "$option_block_class", 'detLinkIdSuffix' => "seedetails" );

    my @verify_options;
    my $did_cur = 0;
    print qq{<div class="info_box">\n};

    $choices .= "<table>\n";

    for my $v ( @{$ord_ar} ) {
        my $pretty = $v;
        $pretty = get_full_apache_version( $pretty, $apv_hr );

        my ( $checked, $l, $r, $d, $detailClass ) = $easy->get_param('apache') eq $v ? ( ' checked', $show_icon, $hide_icon, 'block', $hide_det_class ) : ( '', $hide_icon, $show_icon, 'none', $show_det_class );

        if ( $profile_setup->{'Apache'}{'version'} eq $v ) {
            print "Your profile has <b>Apache $pretty</b> chosen to build.<br />\n";
            ( $checked, $l, $r, $d ) = ( ' checked', $show_icon, $hide_icon, 'block' )
              if !exists $apv_hr->{ $easy->get_param('apache') };
        }

        # save the current apache version to render as a hidden field. It's used
        # by js
        if ($checked) {
            $selected_apache_ver = $v;
        }

        if ( !$did_cur ) {
            if ( defined $current ) {
                if ( $current eq $v ) {
                    my $pretty_running = $easy->_get_httpd_version();
                    print "Your currently running apache is <b>Apache $pretty_running</b>.\n";
                    $did_cur++;
                }
            }
            else {
                print "Sorry, I could not determine the currently running apache version.\n";
                $did_cur++;
            }
        }
        my $url  = $Cpanel::Easy::Apache::Utils::Support::URL;
        my $link = " See also <a href='$url'>$url</a><br>\n";

        my $full = get_full_apache_version( $v, $apv_hr );

        # Verify if the user indeed wants to select this option on or off.
        # Add updateSelectedVersion() method call to apache versions that do not
        # need to verify using a popup.
        my $option_id = "apache_$v";
        my %verify_option_cfg = build_verify_data( $self, $apv_hr->{$v}, "$option_id" );

        if ( scalar( keys %verify_option_cfg ) > 0 ) {
            push( @verify_options, \%verify_option_cfg );
        }

        $choices .= qq{
                <tr class="$option_block_class" valign='top'>
                 <td>
                    <input type="radio" id="$option_id" name="apache"
                        value="$v"$checked />
                 </td>
                 <td>
                    <label for="apache_$v">
                        Apache $full
                    </label>
                 </td>
                 <td>
                    [<a style="text-decoration:none; font-weight: 900;"
                        id="seedetails$v" href="javascript:void(0);" class="$detailClass">
                        $r
                    </a>]
                    <br />
                    <div style="width:500px; display:$d" class="description" id="conf_info$v">
                        &#8593; $apv_hr->{ $v }{'note'}
                    </div>
                    \n
                 </td>
                 </tr>
        };

    }
    $choices .= "</table>\n";

    print "</div>\n<br />\n";    # info box
    print $self->{'name'}, "<br />\n";
    print qq{<div style="margin-left: 20px;">};    # indent form
    print $choices;
    print qq{</div>};                              # /indent form

    $js_config{'verifyOptions'} = \@verify_options;

    # Add the selected apache version to render as a hidden field. It's used
    # by js
    print qq{<input type="hidden" id="selectedOption" value="$selected_apache_ver" />\n};

    $js_config{'selectedOptionId'} = "selectedOption";

    my $json_js_config = JSON::Syck::Dump( \%js_config );

    print <<"JS";

        <script type="text/javascript">
          <!--
            EVENT.onDOMReady(function(){
                var listApache = new CPANEL.ea.ListApache($json_js_config);
            });

          -->
        </script>
JS

    print $self->get_form_end();

    return;    # false means no build yet
}

sub choose_php {
    my ( $self, $easy, $profile, $profile_setup, $zero ) = @_;

    print qq{<div class="info_box">For more information about PHP configuration, capabilities, and limitations please see <a target="_blank" href="http://www.php.net">http://www.php.net</a>.\n};

    if ( my @installed = $self->get_current_php_versions($easy) ) {
        @installed = grep( s/^(\d).*/$1/, @installed );
        print '<br /><br />You currently have PHP <b>' . join( '</b> and <b>', @installed ) . '</b> installed.';
    }
    print qq{</div>\n<br />\n};

    print <<"END_PHP";
    <div class="info_box">
      You can customize how PHP pages are served after the build by running the /usr/local/cpanel/bin/rebuild_phpconf script or in the WebHostManager under Service Configuration &gt;&gt; <a href="../scripts2/phpandsuexecconf">Configure PHP and Suexec</a>
    </div>
    <br />
END_PHP

    print $self->{'name'}, "<br />\n";
    print qq{<div style="margin-left: 20px;">};    # indent form

    if ( $easy->get_param('turn_off_always_do_the_oldest_latest_phps') ) {
        $easy->set_param( 'turn_off_always_do_the_oldest_latest_phps', 0 );

        $easy->{'_'}{'prefs'}{'always_do_the_latest_phps'} = 0;
        $easy->set_param( 'always_do_the_latest_phps', 0 );
        $easy->{'_'}{'prefs'}{'always_do_the_oldest_phps'} = 0;
        $easy->set_param( 'always_do_the_oldest_phps', 0 );

        my $pr_hr = $easy->deserialize( $easy->{'prefs_file'} );
        $pr_hr->{'always_do_the_latest_phps'} = 0;
        $pr_hr->{'always_do_the_oldest_phps'} = 0;

        $easy->serialize( $easy->{'prefs_file'}, $pr_hr );
    }

    my %support_info;

    if ( $easy->{'_'}{'prefs'}{'always_do_the_oldest_phps'} || $easy->{'_'}{'prefs'}{'always_do_the_latest_phps'} ) {
        my $ns = "Cpanel::Easy::PHP5";

        eval qq{ require $ns; };
        my $current = $easy->{'_'}{'prefs'}{'always_do_the_latest_phps'} ? $ns->latest_version() : $ns->oldest_version();
        $current = "5.$current";
        $current =~ s{\_}{.}g;

        if ( $easy->{'_'}{'prefs'}{'always_do_the_latest_phps'} ) {
            print <<"END_FYI";
You have chosen to always use the newest minor version of any major versions of PHP you have chosen.<br /><br />
Currently you'll get: $current<br /><br />
To re-enable the ability to choose the minor versions simply turn off the preference using the button below.<br /><br />
END_FYI
        }
        else {
            print <<"END_FYI";
You have chosen to always use the oldest minor version of any major versions of PHP you have chosen.<br /><br />
Currently you'll get: $current<br /><br />
To re-enable the ability to choose the minor versions simply turn off the preference using the button below.<br /><br />
END_FYI
        }

        print $self->get_form_start(
            $easy,
            {
                'hidden_minus' => [qw( action )],
                'form_action'  => $zero,
                'new_action'   => 'choose_php',
            },
        );

        print <<'END_TURNITOFF';
      <input type="hidden" name="turn_off_always_do_the_oldest_latest_phps" value="1" />
      <input type="submit" class="btn-primary primary default input-button" value="Turn off this preference" />
    </form>
END_TURNITOFF

        print $self->get_form_start(
            $easy,
            {
                'hidden_minus' => [qw( action php5 )],
                'form_action'  => $zero,
                'new_action'   => 'show_basic_opts',
            },
        );

        my $pns = "Cpanel::Easy::PHP5";
        eval qq{require $pns;};
        my $latest = $easy->{'_'}{'prefs'}{'always_do_the_latest_phps'} ? $pns->latest_version($profile_setup) : $pns->oldest_version();
        my $selected = "";

        if ( $easy->get_param('php5') ) {
            $selected = $easy->get_param('php5');
        }
        elsif ( $easy->get_ns_value_from_profile( $pns, $profile ) ) {
            $selected = $latest;
        }

        print qq{<h3>$easy->{'state'}{'optmods'}{$pns}{'name'} [<a target="_blank" href="http://www.php.net/ChangeLog-5.php">$docu_icon</a>]</h3>\n};

        print "<table>\n";
        print "<tr>\n";
        print "<td>\n";
        my $checked = $selected ? '' : 'checked="checked"';
        print qq{ &nbsp; &nbsp; &nbsp; <input type="radio" id="php5_none" name="php5" value="" $checked /> <label for="php5_none"> None </label>\n};
        print "</td>\n";
        print "<td>&nbsp;</td><td>&nbsp;</td>\n";
        print "</tr>\n";

        my $label = "5.$latest";
        $label =~ s{\_}{\.}g;

        $checked = $selected ? 'checked="checked"' : '';

        print "<tr>\n";
        print "<td>\n";
        print qq{ &nbsp; &nbsp; &nbsp;
            <input type="radio" id="php5_$latest" name="php5" value="$latest" $checked />
            <label for="php5_$latest">
                $label
            </label>
                \n};
        print "</td>\n";

        my $support_decoration = Cpanel::Easy::PHP5::support_decoration($latest);
        if ($support_decoration) {

            # print "<td>&nbsp;</td>\n";
            print "<td>&nbsp;<label for='php5_$latest'><i>$support_decoration</i></label></td>\n";
        }
        print "</tr>\n";

        print "</table>\n";

        my $support_level = Cpanel::Easy::PHP5::support_level($latest);
        if ($support_level) {
            $support_info{$support_level} = '* ' . Cpanel::Easy::PHP5::support_text($latest);
        }
    }
    else {
        print $self->get_form_start(
            $easy,
            {
                'hidden_minus' => [qw( action php5 )],
                'form_action'  => $zero,
                'new_action'   => 'show_basic_opts',
            },
        );

        my $cur_php = Cpanel::LoadFile::loadfile('/usr/local/apache/conf/php.version');
        chomp $cur_php;

        my ( $main, @sub ) = split( /\./, $cur_php );
        my $subv = join( '_', @sub );

        # this will make the version be whats installed not whats in the profile: Case 3054:
        # $easy->set_param( 'php' . $main, $subv ) if !$easy->get_param( 'php' . $main );

        my $pns = 'Cpanel::Easy::PHP5';
        eval qq{require $pns;};
        print qq{<h3>$easy->{'state'}{'optmods'}{$pns}{'name'} [<a target="_blank" href="http://www.php.net/ChangeLog-5.php">$docu_icon</a>]</h3>\n};

        my $pns_enabled = $easy->get_ns_value_from_profile( $pns, $profile );
        my @versions    = $pns->versions();
        my $selected    = '';

        for my $sub (@versions) {
            for my $php_param ( $easy->get_param('php5') ) {
                if ( $php_param eq $sub ) {
                    $selected = $sub;
                    last;
                }
            }

            if ( $pns_enabled && !$selected && $profile_setup->{ 'Cpanel::Easy::PHP5::' . $sub } ) {
                $selected = $sub;
            }
        }

        if ( $pns_enabled && !$selected ) {
            $selected = $pns->latest_version($profile_setup);
        }

        my @php_param = ( grep /^5/, $easy->get_param('php5') );

        print "<table>\n";

        my $checked = $selected ? '' : 'checked="checked"';
        print "<tr>\n";
        print "<td>&nbsp;</td>\n";
        print qq{<td><input type="radio" id="php5_none" name="php5" value="" $checked /></td>\n};
        print "<td><label for='php5_none'>None</label></td>\n";
        print "</tr>\n";

        for my $sub (@versions) {
            my $label = "5.$sub";
            $label =~ s{\_}{\.}g;

            my $checked = $selected eq $sub ? 'checked="checked"' : '';

            print "<tr>\n";
            print "<td>&nbsp;</td>\n";
            print qq{<td><input type="radio" id="php5_$sub" name="php5" value="$sub" $checked /></td>\n};
            print "<td><label for='php5_$sub'>$label</label></td>\n";

            my $support_decoration = Cpanel::Easy::PHP5::support_decoration($sub);
            if ($support_decoration) {

                # print "<td>&nbsp;</td>\n";
                print "<td>&nbsp;<label for='php5_$sub'><i>$support_decoration</i></label></td>\n";
            }
            print "</tr>\n";

            my $support_level = Cpanel::Easy::PHP5::support_level($sub);
            if ($support_level) {
                $support_info{$support_level} = '* ' . Cpanel::Easy::PHP5::support_text($sub);
            }
        }
        print "</table>\n";
    }

    if ( keys %support_info ) {
        print "<br>\n";
        for my $k ( sort keys %support_info ) {
            print "* $support_info{ $k }<br>\n";
        }
        my $url = $Cpanel::Easy::Apache::Utils::Support::URL;
        print "See also <a href='$url'>$url</a><br>\n";
    }

    print qq{</div>};    # /indent form
    print $self->get_form_end();

    return;              # false means no build yet
}

sub show_basic_opts {
    my ( $self, $easy, $profile, $profile_setup, $zero ) = @_;
    $self->merge_profile( $easy, $profile, $profile_setup );

    my %js_config = ( "optionsTableClass" => "optionsList" );

    my @php_param;
    my $pns = 'Cpanel::Easy::PHP5';
    eval qq{require $pns;};
    my @versions = $pns->versions();

    # Remove old versions from profile
    foreach my $ns ( keys %$profile_setup ) {
        delete $profile_setup->{$ns} if ( $ns =~ /^\Q$pns\E::\d+_\d+$/ );
    }

    # Set current version so modself kicks off
    my $selected = $easy->get_param('php5');

    my $found = 0;
    foreach my $ver (@versions) {
        my $subns = "${pns}::${ver}";
        $easy->set_ns_value_in_profile( $subns, $profile_setup, ( $ver eq $selected ? 1 : 0 ) );
        $found = 1 if $ver eq $selected;
    }
    $easy->set_ns_value_in_profile( $pns, $profile_setup, $found );
    push @php_param, '5' if $found;
    $easy->set_param( 'php', @php_param );

    if ( !exists $easy->{'state'}{'optmods'}{'Apache'}{'_main'}{ $easy->get_param('apache') } ) {
        my $def = $profile_setup->{'Apache'}{'version'};
        print "<p>Invalid apache version, using <b>$def</b>.</p>";
        $easy->set_param( 'apache', $def );
    }

    $profile_setup->{'Apache'}{'version'} = $easy->get_param('apache');
    $easy->{'working_profile'} = $profile_setup;

    print $self->{'name'}, "<br />\n";

    my %form_parts;

    my ( $apache_ar, $php5_ar, $non_php_includes_ar, $prefs_ar ) = $self->get_opt_params_lists($easy);

    print $self->get_form_start(
        $easy,
        {
            'hidden_minus' => [ 'action', 'turn_off_old_new_php_setting', @{$non_php_includes_ar}, @{ $easy->{'apache_ns_mods_in_basic'} } ],
            'form_action'  => $zero,
            'new_action'   => 'show_all_opts',
        },
    );

    _generate_form_part( $easy, $profile_setup, \%form_parts, [ @{$non_php_includes_ar}, @{ $easy->{'apache_ns_mods_in_basic'} } ], 'apache_sepcial', 1 );

    my %param_lookup;
    @param_lookup{ @{ $easy->{'apache_ns_mods_in_basic'} }, @{$non_php_includes_ar} } = ();

    # use Data::Dumper::HTML qw(dumper_html);print dumper_html( $non_php_includes_ar ); #\%param_lookup );

  LIST:
    for my $ar ( $apache_ar, $php5_ar ) {
      ITEM:
        for my $opt ( @{$ar} ) {
            next ITEM if exists $param_lookup{$opt};
            my $setting = defined $easy->get_param($opt) ? $easy->get_param($opt) : $easy->get_ns_value_from_profile( $opt, $profile_setup );
            $setting = $setting ? 1 : 0;

            my $ec = $easy->get_easyconfig_hr_from_ns_via_state($opt);
            if ( $ec->{'reverse'} ) {
                $setting = $setting ? 0 : 1;
            }

            print qq{<input type="hidden" name="$opt" value="$setting" />\n};
        }
    }

    print qq{<div style="margin-left: 20px;">};    # indent form
    print $form_parts{'apache_sepcial'} . "\n" . $form_parts{'non_php_includes'};
    print qq{</div>};                              # /indent form

    print qq{<p><input type="submit" name="save_and_build" class="btn-primary primary default input-button" value="Save and Build" onClick="return CPANEL.ea.confirmBuild(this);" /> or };

    if ( $form_parts{"verify_options"} ) {
        $js_config{'verifyOptions'} = $form_parts{"verify_options"};
    }

    my $json_js_config = JSON::Syck::Dump( \%js_config );

    print <<"JS";

        <script type="text/javascript">
          <!--
            EVENT.onDOMReady(function(){
                var listAllOptions = new CPANEL.ea.ListAllOptions($json_js_config);
            });

          -->
        </script>
JS

    print $self->get_form_end( $easy, { 'submit' => 'Exhaustive Options List', 'no_p' => 1, } );
    print qq{</p>\n};

    return;    # false means no build yet
}

sub show_all_opts {
    my ( $self, $easy, $profile, $profile_setup, $zero ) = @_;
    $self->merge_profile( $easy, $profile, $profile_setup );

    my %js_config = ( "optionsTableClass" => "optionsList" );

    my @verify_options;

    my $val = grep( /^5$/, $easy->get_param('php') ) ? 1 : 0;
    my $pns = 'Cpanel::Easy::PHP5';
    $easy->set_ns_value_in_profile( $pns, $profile_setup, $val );
    if ($val) {

        # Remove old versions from profile
        foreach my $ns ( keys %$profile_setup ) {
            delete $profile_setup->{$ns} if ( $ns =~ /^\Q$pns\E::\d+_\d+$/ );
        }

        # Set current version so modself kicks off
        my $selected = $easy->get_param('php5');
        eval qq{require $pns;};
        my @versions = $pns->versions();
        foreach my $ver (@versions) {
            my $subns = "${pns}::${ver}";
            $easy->set_ns_value_in_profile( $subns, $profile_setup, ( $ver eq $selected ? 1 : 0 ) );
        }
    }

    if ( !exists $easy->{'state'}{'optmods'}{'Apache'}{'_main'}{ $easy->get_param('apache') } ) {
        my $def = $profile_setup->{'Apache'}{'version'};
        print "<p>Invalid apache version, using <b>$def</b>.</p>";
        $easy->set_param( 'apache', $def );
    }

    $profile_setup->{'Apache'}{'version'} = $easy->get_param('apache');

    # set unchecked ones to zero
    for my $apo ( keys %{ $profile_setup->{'Apache'}{'optmods'} } ) {
        $profile_setup->{'Apache'}{'optmods'}{$apo} = $easy->get_param( 'Cpanel::Easy::Apache::' . $apo ) ? 1 : 0;
    }
    for my $opt ( keys %{$profile_setup} ) {
        next if $opt eq 'Apache' || $opt eq '_meta' || !defined( $easy->get_param($opt) );
        $profile_setup->{$opt} = $easy->get_param($opt) ? 1 : 0;
    }

    my ( $apache_ar, $php5_ar, $non_php_includes_ar, $prefs_ar ) = $self->get_opt_params_lists($easy);
    for my $opt ( @{$non_php_includes_ar} ) {
        $profile_setup->{$opt} = $easy->get_param($opt) ? 1 : 0;
    }

    $easy->{'working_profile'} = $profile_setup;

    # ??? Add change profile menu here or leave it out, can do after release

    my %form_parts = (
        'non_php_includes' => '[None]',
        'apache'           => '[None]',
        'php5'             => '[None]',
        'prefs'            => '[None]',
    );

    ( $apache_ar, $php5_ar, $non_php_includes_ar, $prefs_ar ) = $self->get_opt_params_lists($easy);

    my @resultOptions;
    _generate_form_part( $easy, $profile_setup, \%form_parts, $apache_ar, 'apache' );
    if ( $form_parts{"verify_options"} ) {
        @resultOptions = @{ $form_parts{"verify_options"} };
        push @verify_options, @resultOptions;
    }

    if ( grep( /^5$/, $easy->get_param('php') ) ) {
        _generate_form_part( $easy, $profile_setup, \%form_parts, $php5_ar, 'php5' );
        if ( $form_parts{"verify_options"} ) {
            @resultOptions = @{ $form_parts{"verify_options"} };
            push @verify_options, @resultOptions;
        }

    }

    _generate_form_part( $easy, $profile_setup, \%form_parts, $non_php_includes_ar, 'non_php_includes' );
    if ( $form_parts{"verify_options"} ) {
        @resultOptions = @{ $form_parts{"verify_options"} };
        push @verify_options, @resultOptions;
    }

    _generate_form_part( $easy, $profile_setup, \%form_parts, $prefs_ar, 'prefs' );
    if ( $form_parts{"verify_options"} ) {
        @resultOptions = @{ $form_parts{"verify_options"} };
        push @verify_options, @resultOptions;
    }

    my @nav_index = (
        {
            'name'   => 'Apache',
            'anchor' => 'apache',
        },
        {
            'name'   => 'Other',
            'anchor' => 'other',
        },
    );

    my %save_as;

    if ( $profile ne $easy->{'profile_main'} ) {
        %save_as = (
            'save_as_ident' => $easy->get_param('profile') =~ m{^cpanel_} ? '' : Cpanel::Encoder::html_encode_str( $easy->get_param('profile') ),
            'save_as_name'  => Cpanel::Encoder::html_encode_str( $profile_setup->{'_meta'}{'name'} ),
            'save_as_desc'  => Cpanel::Encoder::html_encode_str( $profile_setup->{'_meta'}{'note'} ),

        );
    }

    for my $key (qw( save_as_ident save_as_name save_as_desc )) {
        $save_as{$key} = Cpanel::Encoder::html_encode_str( $easy->get_param($key) ) if $easy->get_param($key);
    }

    $form_parts{'save_as'} = <<"END_SAVEAS";
    <br /><b>Tip:</b>
    <blockquote class="info_box" align="justify">
    When you "save" your choices in this interface it is referred to as the "Previously Saved Config". Here, you can additionally "Save As" a specific name for reuse.
    </blockquote>
    <table border="0">
     <tr valign="top"><td><label for="save_as_ident">File name</label></td><td><input size="32" maxlength="64" type="text" id="save_as_ident" name="save_as_ident" value="$save_as{'save_as_ident'}" /> <b>(Maximum 64 letters, numbers, and underscores only)</b></td></tr>
     <tr valign="top"><td><label for="save_as_name">Display Name</label></td><td><input size="32" maxlength="128" type="text" id="save_as_name" name="save_as_name" value="$save_as{'save_as_name'}" /></td></tr>
     <tr valign="top"><td><label for="save_as_desc">Description</label></td><td><textarea cols="32" rows="3" id="save_as_desc" name="save_as_desc">$save_as{'save_as_desc'}</textarea></td></tr>
     <!--
     <tr valign="top"><td>Save As</td><td><b>TODO (after release): NON-CPANEL PROFILE MENU HERE (changes fields above)</b></td></tr>
     -->
    </table>
END_SAVEAS

    my $php_form = '';
    my $pretty   = "5.";
    my $par_ns   = qq{Cpanel::Easy::PHP5};
    eval qq{use $par_ns;};
    my @vrs = $par_ns->versions();

    $pretty .= $easy->get_param('php5') || ( grep { $profile_setup->{ $par_ns . '::' . $_ } } @vrs )[0] || 'x';
    $pretty =~ s{\_}{\.}g;

    my $checked = grep( /^5$/, $easy->get_param('php') ) ? ' checked="checked"' : '';
    if ($checked) {
        push @nav_index,
          {
            'name'   => "PHP 5",
            'anchor' => "php5",
          };
        $php_form .= <<"END_PHP";
      <fieldset style="margin-left: 20px;width:75%;border: 1px solid #C0C0C0;">
        <legend style="font-size:14px;font-weight: bold;"><a name="php5" border="0">PHP $pretty (Be sure to <a target="_blank" href="http://go.cpanel.net/hardeningphp">"harden" your PHP</a> since PHP has many security issues)</a></legend>
              <blockquote class="info_box" align="justify">
                For more information about PHP configuration, capabilities, and limitations please see <a target="_blank" href="http://www.php.net">http://www.php.net</a>.
              </blockquote>
              <blockquote class="info_box_transparent" align="justify">
                Options in <span class="caution">this color</span> are enabled by default in php $pretty. That means that you won't see anything added to php's configure line unless it is unchecked.
              </blockquote>
$form_parts{ 'php5' }
      <div style="float:right;"><a href="#top">Back to top</a></div><br />
      </fieldset><br /><br />
END_PHP
    }

    my $rgx = qr(::);

    push @nav_index,
      {
        'name'   => 'Preferences',
        'anchor' => "pref",
      };

    push @nav_index,
      {
        'name'   => 'Save As',
        'anchor' => 'save',
      };

    my $nav_index = join ' | ', map { qq(<a style="font-size:14px;" href="#$_->{anchor}" border="0">$_->{name}</a>) } @nav_index;
    print <<"END_BQ";
<span style="font-size:12px;"><a name="top">Jump to</a>: </span><span style="font-size:14px;">$nav_index</span>
<blockquote class="info_box" align="justify">
  If you need more information about specific apache modules, their capabilities, or uses please see <a target="_blank" href="http://httpd.apache.org/">http://httpd.apache.org</a>.
</blockquote>
END_BQ

    print $self->{'name'}, "<br /><br />\n";
    print $self->get_form_start(
        $easy,
        {
            'hidden_minus' => [ @{$prefs_ar}, qw( action save_as_ident save_as_name save_as_desc ), $rgx ],
            'form_action'  => $zero,
        },
    );

    my $save_only      = $easy->maketext(q{Save only (Do NOT build)});
    my $save_and_build = $easy->maketext(q{Save and build});

    print <<"END_APACHE";
     <fieldset style="margin-left: 20px;width:75%;border: 1px solid #C0C0C0;">
       <legend style="font-size:14px;font-weight: bold;"><a name="apache" border="0">Apache Built-in Modules</a></legend>
            <blockquote class="info_box_transparent" style="align:justify">
              Options in <span class="caution">this color</span> are enabled by default in Apache. That means that you won't see anything added to Apache's configure line unless it is unchecked.
            </blockquote>
$form_parts{ 'apache' }
     <div style="float:right;"><a href="#top">Back to top</a></div><br />
     </fieldset><br /><br />
     <fieldset style="margin-left: 20px;width:75%;border: 1px solid #C0C0C0;">
       <legend style="font-size:14px;font-weight: bold;"><a name="other" border="0">Other Modules</a></legend>
$form_parts{ 'non_php_includes' }
     <div style="float:right;"><a href="#top">Back to top</a></div><br />
     </fieldset><br /><br />
$php_form
     <fieldset style="margin-left: 20px;width:75%;border: 1px solid #C0C0C0;">
       <legend style="font-size:14px;font-weight: bold;"><a name="pref" border="0">Preferences</a></legend>
$form_parts{ 'prefs' }
      <div style="float:right;"><a href="#top">Back to top</a></div><br />
      </fieldset><br /><br />
      <fieldset style="margin-left: 20px;width:75%;border: 1px solid #C0C0C0;">
        <legend style="font-size:14px;font-weight: bold;"><a name="save" border="0">Save selections as custom profile (optional)</a></legend>
$form_parts{ 'save_as' }
      <div style="float:right;"><a href="#top">Back to top</a></div><br />
      </fieldset><br /><br />
      <p>
        <input type="submit" name="action" class="btn-primary primary default input-button" value="$save_only" />
            or
        <input type="submit" name="action" class="btn-primary primary default input-button" value="$save_and_build" onClick="return CPANEL.ea.confirmBuild(this);" /></p>
      </form>
END_APACHE

    $js_config{'verifyOptions'} = \@verify_options;

    my $json_js_config = JSON::Syck::Dump( \%js_config );
    print <<"JS";

        <script type="text/javascript">
          <!--
            EVENT.onDOMReady(function(){
                var listExhaustiveOptions = new CPANEL.ea.ListAllOptions($json_js_config);
            });

          -->
        </script>
JS

    return;    # false means no build yet
}

sub save_only {
    my ( $self, $easy, $profile, $profile_setup, $zero ) = @_;

    if ( !exists $easy->{'state'}{'optmods'}{'Apache'}{'_main'}{ $easy->get_param('apache') } ) {
        my $def = $profile_setup->{'Apache'}{'version'};
        print "<p>Invalid apache version, using <b>$def</b>.</p>";
        $easy->set_param( 'apache', $def );
    }
    $profile_setup->{'Apache'}{'version'} = $easy->get_param('apache');

    for my $ar ( $self->get_opt_params_lists($easy) ) {
        for my $opt ( @{$ar} ) {
            next if exists $easy->{'_'}{'prefs'}{$opt};
            $easy->set_param( $opt, 0 ) if !defined $easy->get_param($opt);
            my $setting = $easy->get_param($opt) ? 1 : 0;
            my $ec = $easy->get_easyconfig_hr_from_ns_via_state($opt);
            if ( $ec->{'reverse'} ) {
                $setting = $setting ? 0 : 1;
            }
            $easy->set_ns_value_in_profile( $opt, $profile_setup, $setting );
        }
    }

    my %avail_ver;
    @avail_ver{ @{ $easy->{'state_config'}{'main_vers'} } } = ();
    if ( exists $avail_ver{ $easy->get_param('apache') } ) {
        $profile_setup->{'Apache'}{'version'} = $easy->get_param('apache');
    }

    my $val = grep( /^5$/, $easy->get_param('php') ) ? 1 : 0;
    my $pns = 'Cpanel::Easy::PHP5';
    $easy->set_ns_value_in_profile( $pns, $profile_setup, $val );
    if ($val) {

        # Remove old versions from profile
        foreach my $ns ( keys %$profile_setup ) {
            delete $profile_setup->{$ns} if ( $ns =~ /^\Q$pns\E::\d+_\d+$/ );
        }

        # Set current version so modself kicks off
        my $selected = $easy->get_param('php5');
        eval qq{require $pns;};
        my @versions = $pns->versions();
        foreach my $ver (@versions) {
            my $subns = "${pns}::${ver}";
            $easy->set_ns_value_in_profile( $subns, $profile_setup, ( $ver eq $selected ? 1 : 0 ) );
        }
    }

    my %prefs;

    for my $pref ( keys %{ $easy->{'prefs_details'} } ) {
        my @prefs = $easy->get_param($pref);
        $prefs{$pref} = 0;
        $prefs{$pref} = join ',', @prefs if @prefs;
    }
    $easy->serialize( $easy->{'prefs_file'}, \%prefs );

    my ( $changed_hr, $loop_hr ) = $easy->apply_one_pass_implies_logic($profile_setup);

    my @arg_copy = @_;
    my $code_ref = \&show_all_opts;
    $easy->handle_one_pass_hashes(
        $changed_hr,
        $loop_hr,
        sub { my ($text) = @_; print qq{<div class="info_box"><b>Info:</b><br />$text</div><br />\n}; },
        sub { my ($text) = @_; print qq{<p class="errors">$text</p>\n}; },
        sub {
            my ($text) = @_;
            print qq{<p class="errors">$text</p>\n};
            no strict 'refs';
            $code_ref->(@arg_copy);
            return;    # don't change me from 'return;'!!
        },
    );

    # require Data::Dumper::HTML;print Data::Dumper::HTML::DumperHTML( $profile_setup );

    # make sure the intent of reverse optmods are faithfully recorded the file saving the updated profile
    my $status = $easy->check_and_fix_reverse_optmods( 'profile_ref' => $profile_setup, 'wanted_apache' => $profile_setup->{'Apache'}->{'version'} );

    if ( !_profile_is_valid( $self, $easy, $profile_setup ) ) {
        no strict 'refs';
        &{'show_all_opts'}(@_);
        return;    # don't change me from 'return;'!!
    }

    print "Saving...<br />\n";

    if ( !_profile_saved_ok( $self, $easy, $profile_setup ) ) {
        no strict 'refs';
        &{'show_all_opts'}(@_);
        return;    # don't change me from 'return;'!!
    }

    print "Done!";

    my ($form) = $self->get_html_hidden_state_minus( $easy, qw(profile php apache php5 build action), qr{save_as}, qr{Cpanel[:][:]Easy} );
    my $build_form = <<"END_BUILD_FORM";
    <p>
    <table border="0">
      <tr>
        <td>
          <form method="post" name="save_only' action="$zero">
            $form
            <input type="submit" class="btn-primary primary default input-button" value="Build profile I just saved" onClick="return CPANEL.ea.confirmBuild(this);" />
            <input type="hidden" name="build" value="1" />
          </form>
       </td>
       <td valign="top">or</td>
       <td>
         <form method="post" name="save_only' action="$zero">
           $form
           <input type="submit" class="btn-primary primary default input-button" value="Go back to profile screen" />
           <input type="hidden" name="action" value="_pre_cpanel_sync_screen" />
        </form>
       </td>
      </tr>
    </table>
    </p>
END_BUILD_FORM

    my $who = ( caller(1) )[3];
    print $build_form
      if $who ne 'Cpanel::Easy::Apache::UI::HTML::Config::save_and_build'
      && $who ne 'save_and_build';

    return 0;    # false means no build yet, don't change me from 'return 0;'!!
}

sub save_and_build {
    my ( $self, $easy, $profile, $profile_setup, $zero ) = @_;
    no strict 'refs';
    if ( $easy->{'_'}{'from_profile'} ) {
        my $prof = $easy->determine_profile();
        if ( $prof ne $easy->{'profile_main'} ) {
            File::Copy::Recursive::fcopy( $prof, $easy->{'profile_main'}, )
              or $easy->print_alert( q{fcopy '[_1]', [_2] failed: [_3]}, $prof, $easy->{'profile_main'}, $! );
        }
    }
    else {
        my $rc = &{'save_only'}(@_);
        return if $rc ne '0';
    }

    my ( $form, $link ) = $self->get_html_hidden_state_minus( $easy, qw(profile php apache php5 build action), qr{save_as}, qr{Cpanel[:][:]Easy} );
    my $build_url = "$zero?build=1&$link";

    for my $pref ( keys %{ $easy->{'prefs_details'} } ) {
        if ( $easy->{'prefs_details'}{$pref}{'no_save'} ) {
            $build_url .= "&$pref=$easy->{'_'}{'prefs'}{$pref}";
        }
    }

    print <<"END_REDIRECT";
    <meta http-equiv="refresh" content="5;url=$build_url">
    <p>Click <a href="$build_url">here</a> if your build does not begin within 5 seconds.</p>
END_REDIRECT

    return;
}

#### save_only() utils ##

sub _profile_is_valid {
    my ( $self, $easy, $profile_hr ) = @_;

    # depends, dryruns, changing to 1s and 2s, outputting erros along the way
    local $easy->{'working_profile'} = $profile_hr;

    my $ok = 1;
    my %in_state;
    @in_state{ @{ $easy->{'state'}{'order'} } } = ();

    my %avail_ver;
    @avail_ver{ @{ $easy->{'state_config'}{'main_vers'} } } = ();

    if ( !exists $avail_ver{ $profile_hr->{'Apache'}{'version'} } ) {
        print qq{<p class="errors">Invalid apache version.</p>\n};
        $ok = 0;
    }

  KEY:
    for my $ent ( keys %{$profile_hr} ) {
        next if $ent eq '_meta';

        if ( $ent !~ m{::} && $ent ne 'Apache' ) {
            print qq{<p class="errors">Removing unknown profile entry.</p>\n};
            delete $profile_hr->{$ent};
            next KEY;
        }

        if ( $ent eq 'Apache' ) {
            for my $op ( keys %{ $profile_hr->{'Apache'}{'optmods'} } ) {
                $ok = 0 if !__ent_is_ok( $easy, 'Cpanel::Easy::Apache::' . $op, \%in_state );
            }
        }
        else {
            $ok = 0 if !__ent_is_ok( $easy, $ent, \%in_state );
        }
    }
    return 1 if $ok;
    print qq{<p class="errors">... Profile validation failed.</p>\n};
    return;
}

sub __ent_is_ok {
    my ( $easy, $ns, $in_state_hr ) = @_;

    if ( !$easy->is_namespace($ns) ) {
        print qq{<p class="errors">Entry passed to save into profile is invalid.</p>\n};
        return;
    }

    return 1 if $easy->ns_is_include_kid_and_parent_is_off( $ns, $easy->{'working_profile'} );
    return 1 if !$easy->get_ns_value_from_profile( $ns, $easy->{'working_profile'} );

    if ( !exists $in_state_hr->{$ns} ) {

        # it may be a custom opt mod that was removed and could be reintroduced later so... (case 1119)
        # if its not really a namespace then its already return()ed so no need to encode $ns
        print <<"END_UNK";
<div class="info_box">
<b>Info:</b><br /> Profile entry '$ns' does not exist so will be ignored.<br />
That simply means that this option was available at one time and is now no longer available.<br />
Easy::Apache does not automatically remove it for you as its possible its a module that could be re-added later (custom mod or different tree) and your previous setting for it will remain intact.<br />
You can simply ignore this message or remove it from the profile it is in.
</div>
<br />
END_UNK

    }

    my $opt = $easy->get_easyconfig_hr_from_ns_variations($ns);
    return 1 if ( $opt->{'skip'} || $opt->{'display_hide'} );

    # my ( $dry_rc, @dry_text ) = $self->dry_run_ok($opt, $ns);

    my ( $depends_rc, @depends_text ) = $easy->dependency_ok( $opt, $ns, 1 );
    if ( !$depends_rc ) {
        print qq{<p class="errors">} . $easy->maketext(@depends_text) . qq{</p>\n};
        return;
    }

    return 1;
}

sub _profile_saved_ok {
    my ( $self, $easy, $profile_hr ) = @_;

    # save based on 'profile' and 'save_as_ident' (64 letters, numbers, and underscores)
    # _meta->name = save_as_name _meta->note = save_as_desc if saving custom

    my $save_as = $easy->get_param('save_as_ident');
    $save_as = '' if $save_as =~ m{^cpanel};

    if ( !$save_as ) {
        $save_as = $easy->get_param('profile')
          if $easy->get_param('profile') !~ m{/}
          && $easy->get_param('profile') !~ m{^cpanel};
    }

    my $long = '';

    if ($save_as) {
        $save_as =~ s{\W+}{}g;
        if ( !$save_as ) {
            print qq{<p class="errors">'Profile' to save as contained no valid characters.</p>\n};
            return;
        }

        if ( length($save_as) > 64 ) {
            print qq{<p class="errors">'Profile' to save has more than 64 letters, numbers, or underscores.</p>\n};
            return;
        }

        if ( !$easy->get_param('save_as_name') ) {
            print qq{<p class="errors">'Profile' Label needs specified.</p>\n};
            return;
        }

        if ( !$easy->get_param('save_as_desc') ) {
            print qq{<p class="errors">'Profile' Description needs specified.</p>\n};
            return;
        }

        # HTML Encode the name & descriptions of the profile to prevent XSS attacks.
        my $profile_name = Cpanel::Encoder::html_encode_str( $easy->get_param('save_as_name') );
        my $profile_desc = Cpanel::Encoder::html_encode_str( $easy->get_param('save_as_desc') );

        $profile_hr->{'_meta'} = {
            %{ $profile_hr->{'_meta'} },
            'name' => $profile_name,
            'note' => $profile_desc,
        };

        $long = $easy->{'profile_custom_dir'} . '/' . $save_as . '.yaml';
    }

    $easy->profile_revision_check( $profile_hr, $long );

    if ($long) {
        if ( !$easy->save_profile( $profile_hr, $long ) ) {
            print qq{<p class="errors">Could not save profile as '$save_as'</p>\n};
        }
    }

    # do last saved
    rename $easy->{'profile_main'}, $easy->{'profile_prev'};
    return 1 if $easy->serialize( $easy->{'profile_main'}, $profile_hr );

    print qq{<p class="errors">Could not save profile as last saved.</p>\n};
    return;
}

sub get_full_apache_version {
    my $xy        = shift;
    my $apache_hr = shift;

    if ( $apache_hr->{$xy}->{'version'} ) {
        return $apache_hr->{$xy}->{'version'};
    }

    if ( $apache_hr->{$xy}->{'src_cd2'} ) {
        my $xyz = $apache_hr->{$xy}->{'src_cd2'};
        $xyz =~ s/^(apache|httpd)[_-]//i;
        return $xyz;
    }

    return $xy;
}

sub get_short_deco {
    my $support_level = shift;
    Cpanel::Easy::Apache::Utils::Support::get_short_deco($support_level);
}

sub get_long_deco {
    my $support_level = shift;
    Cpanel::Easy::Apache::Utils::Support::get_long_deco($support_level);
}

1;
