<?php
define("AJAXHELPER", 1);
require_once(dirname(__FILE__) . '/includes/base.inc.php');

route_request();

function route_request() {

    $cmd = grab_request_var('cmd');
    $opts = json_decode(grab_request_var('opts'), true);
    switch ($cmd) {

        case 'paged_table':
            ah_paged_table($opts);
            break;

        case 'test_server':
            ah_test_server($opts);
            break;

        case 'dashletize':
            ah_dashletize($opts);
            break;

        case 'update_dashlet':
            ah_update_dashlet($opts);
            break;

        case 'system_alert':
            ah_system_alert($opts);
            break;

        case 'fused_servers';
            ah_fused_server_alerts($opts);
            break;

        case 'set_session_vars':
            ah_set_session_vars($opts);
            break;

        case 'set_user_meta':
            ah_set_user_meta($opts);
            break;

        case 'get_user_meta':
            ah_get_user_meta($opts);
            break;

        case 'get_feedback_sending':
            ah_get_feedback_sending();
            break;

        case 'get_feedback_success':
            ah_get_feedback_success();
            break;

        case 'get_feedback_error':
            ah_get_feedback_error();
            break;

        case 'get_permalink_form':
            ah_get_permalink_form($opts);
            break;

        case 'get_add_to_views_form':
            ah_get_add_to_views_form($opts);
            break;

        case 'get_add_to_views_submitting':
            ah_get_add_to_views_submitting();
            break;

        case 'get_add_to_views_success':
            ah_get_add_to_views_success();
            break;

        case 'get_add_to_views_error':
            ah_get_add_to_views_error();
            break;

        case 'add_view':
            $url = grab_request_var('url');
            $title = grab_request_var('title');
            if (empty($url) || empty($title)) {
                header('X-PHP-Response-Code: 500', true, 500);
                exit();
            }
            ah_add_view($url, $title);
            break;

        case 'update_view_order':
            ah_update_view_order($opts);
            break;

        case 'get_my_views_menu':
            ah_get_my_views_menu();
            break;

        case 'get_views_text':
            ah_get_views_text($opts);
            break;

        case 'truncate_polling_locks':
            truncate_polling_locks();
            break;

        case 'authenticate_auto_login':
            authenticate_auto_login($opts);
            break;
            
        case 'get_source_bw_data':
            get_source_bw_data($opts);
            break;
            
        case 'check_auth':
            ah_check_auth($opts);
            break;

        case 'update_status_pages_refresh':
            ah_update_status_pages_refresh($opts);
            break;

        case 'get_25_year_celebration_license_popup':
            ah_get_25_year_celebration_license_popup($opts);
            break;

        case 'check_25_year_celebration_license':
            ah_check_25_year_celebration_license($opts);
            break;

        case 'get_fused_server_users':
            ah_get_fused_server_users($opts);
            break;

        case 'test_push_users':
            ah_test_push_users($opts);
            break;
    }

    exit();
}

function ah_get_fused_server_users($opts) {
    $server_id = grab_request_var('server_id', '');
    $server_data = get_server($server_id);
    
    // get the server url from the server data
    $server_data_url = '';
    if (isset($server_data['url'])) {
        $server_data_url = rtrim($server_data['url'], '/');
    }

    $users_api_url = $server_data_url . '/api/v1/system/user';
    $api_params = array(
        'apikey' => $server_data['fusekey'],
        'pretty' => 1,
        'full' => 1,
    );
    $users_api_url = add_params_to_url($users_api_url, $api_params);

    $users_data = make_curl_request($users_api_url);

    echo json_encode($users_data);
}

function ah_test_push_users($opts) {
    // get request vars and server data
    $target_server_ids_raw = grab_request_var('target_server_ids', '');
    $target_server_ids = json_decode($target_server_ids_raw, true);

    $users_raw = grab_request_var('users', '');
    $users = json_decode($users_raw, true);
    

    // get the server url from the server data
    $target_server_data_url = '';
    if (isset($target_server_data['url'])) {
        $target_server_data_url = rtrim($target_server_data['url'], '/');
    }
    
    $target_servers_payloads = array();
    // generate the add user payloads for each target server
    foreach ($target_server_ids as $target_server_id) {
        $target_server_data = get_server($target_server_id);
        $target_server_data_url = rtrim($target_server_data['url'], '/');

        $user_count = count($users);
        $user_index = 0;
        // generate the add user payloads
        foreach ($users as $user) {
            
            $users_api_url = $target_server_data_url . '/api/v1/system/user';
            
            $api_params = array(
                'apikey' => $target_server_data['fusekey'],
            );

            $users_api_url = add_params_to_url($users_api_url, $api_params);

            $user_data = array();
            foreach ($user as $key => $value) { 
                if ($key == 'user_id') {
                    continue;
                }

                $user_data[$key] = $value;
            }

            $user_data['password'] = 'password';
            $user_data['applyconfig'] = $user_index == $user_count - 1 ? 1 : 0;

            $target_servers_payloads[$target_server_id][] = array(
                'username' => $user['username'],
                'endpoint' => $users_api_url,
                'data' => $user_data,
            );

            $user_index == $user_count - 1 ? $user_index = 0 : $user_index++;
        }
    }

    // make the add user curl requests to target server
    $target_servers_responses = array();
    foreach ($target_servers_payloads as $target_server_id => $target_server_payloads) {
        foreach ($target_server_payloads as $target_server_payload) {
            $target_servers_responses[$target_server_id][$target_server_payload['username']] = make_curl_request($target_server_payload['endpoint'], 'POST', $target_server_payload['data']);
        }
    }

    
    // generate the response
    $response = array(
        'success' => true,
        'message' => 'Users successfully pushed to target servers!',
        'target_servers_payloads' => $target_servers_payloads,
        'target_servers_responses' => $target_servers_responses,
    );

    echo json_encode($response);
}

function make_curl_request($url, $method = 'GET', $data = array()) {
    // initialize curl
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);

    // disable ssl verification to avoid certificate errors
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

    if ($method == 'POST') {
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    }

    $response = curl_exec($ch);
    curl_close($ch);

    return json_decode($response, true);
}

function add_params_to_url($url, $params) {
    $param_index = 0;
    foreach ($params as $key => $value) {
        if ($param_index > 0) {
            $url .= '&';
        } else {
            $url .= '?';
        }

        $url .= $key . '=' . urlencode($value);
        $param_index++;
    }
    return $url;
}

function ah_get_views_text($opts) {

    $str = '';
    if (isset($opts['str']))
        $str = $opts['str'];

    if ($str == 'start')
        echo '&nbsp;' . _('Start Rotation');
    if ($str == 'stop')
        echo '&nbsp;' . _('Stop Rotation');
}

function ah_get_my_views_menu() {

    global $menu;
    init_menu('views');
    $menu->print_menu('views', 'views-mine');
}

function ah_update_view_order($opts) {

    global $db;
    
    $user_id = 0;
    if (isset($_SESSION['user_id']))
        $user_id = intval($_SESSION['user_id']);

    foreach ($opts as $view_order => $view_id) {

        $bind_array = array(
            ':view_order' => $view_order,
            ':view_id'    => $view_id,
            ':user_id'    => $user_id,
            );

        $db->exec_query('UPDATE views SET view_order = :view_order WHERE view_id = :view_id AND user_id = :user_id', $bind_array);
    }
}

function ah_add_view($url, $title) {

    if (!add_view($url, $title)) {
        header('X-PHP-Response-Code: 500', true, 500);
    }
}

function ah_get_add_to_views_submitting() {

    print_popup_div(_('Please Wait'), _('Processing..'));
}

function ah_get_add_to_views_success() {

    print_popup_div(_('View Added'), _('Success! Your view was added to your Views page!'));
}

function ah_get_add_to_views_error() {

    print_popup_div(_('Error'), _('An error has occurred while processing your request.'));
}

function ah_get_add_to_views_form($opts) {

    if (!is_array($opts) || !isset($opts['theurl']))
        exit();

    $theurl = encode_html($opts['theurl']);

    echo '
        <div id="popup_header">
            ' . _('Add View') . '
        </div>
        <div id="popup_data">
            <p style="margin-top: 10px;">
                ' . _('Use this to add what you see on the screen to your Views page') . '
            </p>
        </div>
        <form id="addview_form" method="get" action="' . get_ajax_helper_url() . '">
            <input type="hidden" name="cmd" value="add_view">
            <input type="hidden" name="url" value="' . $theurl . '">
            <label for="addviewTitleBox">' . _('View Title') . '</label>
            <div class="popup-form-box">
                <input type="text" name="title" id="addviewTitleBox" value="" style="width: 100%;" class="form-control">
            </div>
            <div id="addviewFormButtons">
                <button type="submit" class="btn btn-sm btn-primary" name="submitButton" id="submitAddViewButton">' . _('Add to Views') . '</button>
            </div>
        </form>';
}

function ah_get_permalink_form($opts) {

    if (!is_array($opts) || !isset($opts['theurl']))
        exit();

    $theurl = encode_html($opts['theurl']);

    echo 
        '<form>
            <div id="popup_header">
                ' . _('Permalink') . '
            </div>
            <div id="popup_data">
                <p>
                    ' . _('Copy the URL below to retain a direct link to your current view.') . '
                </p>
                <label for="permalinkURLBox">' . _('Permalink URL') . ':</label>
                <input type="text" size="50" class="textfield form-control" style="width: 100%;" name="url" id="permalinkURLBox"
                    value="' . $theurl . '">
            </div>
            <div>
                <a id="permalink-copy" href="#" data-clipboard-target="#permalinkURLBox" class="btn btn-sm btn-copy btn-primary">' .
                    _('Copy to Clipboard') .
                '</a>
            </div>
        </form>
        <script type="text/javascript">

            $(".btn-copy").tooltip({ trigger: "click", placement: "bottom" });

            var clipboard = new Clipboard(".btn-copy");

            clipboard.on("success", function(e) { 
                setTooltip(e.trigger, "' . _('Copied') . '!");
                hideTooltip(e.trigger); 
            });

            clipboard.on("error", function(e) { 
                setTooltip(e.trigger, "' . _('Press Ctrl+C to copy') . '");
                hideTooltip(e.trigger);
            });
        </script>';
}

// yep ..exactly the same as the feedback div. no, i didn't choose this -bh
function print_popup_div($header, $data) {

    echo '<div id="popup_header">' . $header . '</div><div id="popup_data"><p>' . $data . '</p></div>';
}

function print_feedback_div($header, $data) {

    echo '<div id="feedback_header">' . $header . '</div><div id="feedback_data"><p>' . $data . '</p></div>';
}

function ah_get_feedback_sending() {

    print_feedback_div(_('Sending feedback...'), _('Please wait...'));
}

function ah_get_feedback_success() {

    print_feedback_div(_('Thank you!'), 
        _('Hey, you. Yeah, ') . '<strong>' . _('you!') . '</strong> ' .
        _("The one who just submitted that awesome feedback. We really appreciate it. We're going to review your comments just as soon as we get a chance. Until then, kudos to you for being awesome!") . '<br><br><br>&nbsp;&nbsp;&nbsp;&mdash;&nbsp;&nbsp;' . _('The Nagios Enterprises Team'));
}

function ah_get_feedback_error() {

    print_feedback_div(_('Error!'), _("An error occured! Please try again later, and if that doesn't work, contact your Nagios Administrator"));
}

function ah_get_user_meta($opts) {

    if (empty($opts) || !is_array($opts))
        exit();

    $keyname = grab_array_var($opts, 'keyname', '');

    if (!empty($keyname))
        echo get_user_meta($keyname, '');
}

function ah_set_user_meta($opts) {

    if (empty($opts) || !is_array($opts))
        exit();

    $keyname = grab_array_var($opts, 'keyname', '');
    $keyvalue = grab_array_var($opts, 'keyvalue', '');
    $autoload = grab_array_var($opts, 'autoload', false);

    $allowed = array(
        'view_rotation_speed', 
        'view_rotation_enabled', 
        'show_login_alert_screen', 
        'day_45', 
        'day_30', 
        'day_15', 
        'day_5', 
        'day_1', 
        'exp_10', 
        'exp_30', 
        'exp_45', 
        'exp_60', 
        'exp_no_show', 
        );

    // only allow some user metas to be set for security reasons
    $allow = false;
    if (in_array($keyname, $allowed)) {

        $allow = true;

    } else if (strpos($keyname, '_tpl_default') !== false) {

        $allow = true;

    } else if ($keyname == 'menu_collapse_options') {

        if (isset($opts['menuid']))
            set_user_menu_preferences($opts['menuid'], $keyvalue);

        return;

    } else if ($keyname == 'tours') {

        if (isset($opts['tourid']))
            set_user_tour_preferences($opts['tourid'], $keyvalue);

        return;
    }

    if ($allow == false) {
        echo 'NOT ALLOWED';
        return;
    }

    set_user_meta($keyname, $keyvalue, $autoload);

    echo 'DONE';
}


function ah_set_session_vars($opts = array()) {

    if (empty($opts) || !is_array($opts))
        exit();

    $msg = _('Variable set');

    // Set the session variable for only variables we accept
    if (isset($opts['ignore_trial_notice'])) {

        $_SESSION['ignore_trial_notice'] = $opts['ignore_trial_notice'];

    } else if (isset($opts['ignore_free_notice'])) {

        $_SESSION['ignore_free_notice'] = $opts['ignore_free_notice'];

    } else if (isset($opts['ignore_fips_warning'])) {
        $_SESSION['ignore_fips_warning'] = $opts['ignore_fips_warning'];
    } else if (isset($opts['ignore_25_year_celebration_license_notice'])) {
        $_SESSION['ignore_25_year_celebration_license_notice'] = $opts['ignore_25_year_celebration_license_notice'];
    } else {

        $msg = _('No variable set');
    }

    return json_encode(array("msg" => $msg));
}


function ah_paged_table($opts = array()) {

    if (empty($opts) || !is_array($opts))
        exit();

    $which = grab_array_var($opts, 'which');
    $rowcount = intval(grab_array_var($opts, 'rowcount', 0));
    $additional = intval(grab_array_var($opts, 'additional', 0));
    $table_data = grab_array_var($opts, 'table_data');

    // decode the table data
    phelp_tabledata_decode($table_data, $select_statement, $bind_array, $options);

    // Verify that we're allowed to run this query
    $user_allowed_statements = array('SELECT * FROM views WHERE user_id = $user_id');
    $admin_allowed_statements = array(
        'SELECT * FROM views WHERE user_id = $user_id',
        'SELECT * FROM log',
        'SELECT * FROM servers',
        'SELECT user_id, username, name, email, enabled, account_locked FROM users',
        'SELECT * FROM dashboards WHERE user_id = :user_id AND screen != 1',
    );

    if (is_admin()) {
        if (in_array($select_statement, $admin_allowed_statements, true) === false) {
            // User is asking for a non-whitelisted query
            exit();
        }
    }
    else {
        if (in_array($select_statement, $user_allowed_statements, true) === false) {
            // User is asking for a non-whitelisted query
            exit();
        }

        // Currently, no 'user'-level queries require the 'eval' feature in table pagination.
        // If this ever changes, it's worth rewriting the pagination code so that executable code isn't passed over XHR.
        if (array_key_exists('columns', $opts)) {
            foreach ($opts['columns'] as $name => $column_opts) {
                if (array_key_exists('eval', $column_opts)) {
                    // Query is trying to run custom code - assume malicious intent
                    exit();
                }
            }
        }

    }

    // get any override options
    $static_limit = grab_array_var($options, 'static_limit', -1);

    // get the current meta for this table!
    $meta_array = phelp_get_pagination($select_statement, $static_limit);

    // what action are we taking? (which button was pressed?)
    switch ($which) {

        case 'first':
            $meta_array['offset'] = 0;
            break;

        case 'prev':
            $meta_array['offset'] -= $meta_array['limit'];
            break;

        case 'next':
            $meta_array['offset'] += $meta_array['limit'];
            break;

        case 'last':
            // we just set it to rowcount since phelp_sanitize_pagination will do the proper math to fix it
            $meta_array['offset'] = $rowcount;
            break;

        case 'jump':
            $meta_array['offset'] = ($additional - 1) * $meta_array['limit'];
            break;

        case 'records':
            if ($static_limit < 0) {
                if ($additional == 0) {
                    $meta_array['offset'] = 0;
                    $meta_array['limit'] = 0;
                } else {
                    $meta_array['limit'] = $additional;
                }
            }
            break;

        case 'reset':
            $meta_array = phelp_get_pagination_user_meta("defaultpagination:{$select_statement}");
            break;

        case 'sort':
            $sort_column = $opts['additional'];
            
            // if we're already sorting by this column, we just need to toggle
            if (isset($meta_array['orderby_column']) && $meta_array['orderby_column'] == $sort_column) {
                if ($meta_array['orderby_order'] == 'ASC') {
                    $meta_array['orderby_order'] = 'DESC';
                } else {
                    $meta_array['orderby_order'] = 'ASC';
                }
            } else {
                $meta_array['orderby_column'] = $sort_column;
                $meta_array['orderby_order'] = 'ASC';
            }
            break;

        default:
            exit();
    }

    // update our info
    phelp_set_pagination_user_meta($select_statement, $meta_array);

    echo get_paged_table($select_statement, $bind_array, $options);
}

// output in format of 'fusekey:AUTH;username:AUTH'
// where AUTH can be the auth_type numeric value returned from check_server_auth
// or the word 'false' -> indicating an error
// or the word 'empty' -> indicating that the field wasn't present
function ah_test_server($opts = array()) {

    if (empty($opts) || !is_array($opts))
        exit();

    if (!is_admin()) {
        exit();
    }

    // we need to check to see if the password is set to password_set
    // because if it is, we need to pull the actual password from the given server_id
    $password = grab_array_var($opts, 'password');
    $server_id = grab_array_var($opts, 'server_id', false);
    if ($password == 'password_set' && $server_id != false) {
        $password = _decrypt(get_server_attr('password', $server_id, 'password_set'));
    }

    // build a simulated server array and pass to check auth
    $fusekey = grab_array_var($opts, 'fusekey');
    $api_key = grab_array_var($opts, 'api_key');
    $username = grab_array_var($opts, 'username');
    $server_type = intval(grab_array_var($opts, 'server_type'));

    $authentication_type = AUTH_TYPE_FUSEKEY;
    if ($server_type == SERVER_TYPE_CORE)
        $authentication_type = AUTH_TYPE_BASIC;

    $server = array(
        'url'                   => grab_array_var($opts, 'url'),
        'cgi_bin'               => grab_array_var($opts, 'cgi_bin'),
        'ssl_hostname_verify'   => grab_array_var($opts, 'ssl_hostname_verify', false),
        'server_type'           => $server_type,
        'authentication_type'   => $authentication_type,
        'fusekey'               => $fusekey,
        'api_key'               => $api_key,
        'username'              => $username,
        'password'              => $password,
        'last_auth_unix'        => 0,
    );

    // if the fusekey is set, it will attempt to check against that no matter what. but we
    // want to make sure the username and password are good too
    $fusekey_auth = false;
    if ($server['server_type'] != SERVER_TYPE_CORE && !empty($server['fusekey']))
        $fusekey_auth = check_server_authentication($server, $failure_on_stale = false);

    // if the API key is set, it will also attempt to check against that no matter what.
    $api_key_auth = false;
    if ($server['server_type'] != SERVER_TYPE_CORE && !empty($server['api_key']))
        $api_key_auth = check_server_authentication($server, $failure_on_stale = false);

    // now we check against the username/password
    $server['fusekey'] = '';
    $username_auth = check_server_authentication($server, $failure_on_stale = false);

    if ($fusekey_auth === false)
        $fusekey_auth = 'false';
    if ($username_auth === false)
        $username_auth = 'false';
    if ($api_key_auth === false)
        $api_key_auth = 'false';

    if (empty($fusekey) || $server['server_type'] == SERVER_TYPE_CORE)
        $fusekey_auth = 'empty';
    if (empty($username))
        $username_auth = 'empty';
    if (empty($api_key))
        $api_key_auth = 'empty';

    $output = "fusekey:{$fusekey_auth};username:{$username_auth};api_key:{$api_key_auth};";
    echo $output;
}

function ah_dashletize($opts = array()) {

    global $dashlets;
    $dashlet = 0;

    if (empty($opts) || !is_array($opts)) {

        echo 'error';
        exit();
    }

    if (!empty($opts['dashlet']) && !empty($dashlets[$opts['dashlet']]))
        $dashlet = $dashlets[$opts['dashlet']];

    if (!empty($dashlet)) {

        if (!empty($opts['title']))
            $dashlet[DASHLET_TITLE] = $opts['title'];

        // we have to grab this here to initialize these before its
        // passed along, otherwise get_dashlet_params thinks the entire
        // array has been passed
        if (isset($dashlet[DASHLET_PARAMS])) {
            $dashlet[DASHLET_PARAMS] = get_dashlet_params($dashlet[DASHLET_PARAMS]);
            if ($dashlet[DASHLET_PARAMS] === false) {
                echo 'error';
                exit();
            }
        }

        // set the params vals
        if (!empty($opts['params'])) {
            if (is_array($opts['params'])) {
                foreach ($opts['params'] as $param => $val) {
                    $dashlet[DASHLET_PARAMS][$param]['val'] = $val;
                }
            }
        }

        echo get_add_dashlet_settings($dashlet);

    } else {

        echo 'error';
        exit();
    }
}

function ah_update_dashlet($opts = array()) {

    global $dashlets;

    $failed = true;
    $add = (bool) grab_array_var($opts, 'add', 0);
    $delete = (bool) grab_array_var($opts, 'delete', 0);
    $update = !$add && !$delete;

    $dashlet = grab_array_var($opts, 'dashlet');
    $dashlet_id = intval(grab_array_var($opts, 'id'));
    $dashboard_id = intval(grab_array_var($opts, 'dashboard_id'));

    $settings = grab_array_var($opts, 'settings');
    $params = grab_array_var($opts, 'params');

    if ($delete) {
        if (!empty($dashlet_id) && delete_db_dashlet($dashlet_id))
            $failed = false;
    }

    else if ($add) {
        if (!empty($dashlet) && add_dashlet($dashlet, $dashboard_id, $settings, $params))
            $failed = false;
    }

    else if ($update) {
        if (!empty($dashlet_id) && update_dashlet($dashlet_id, $settings, $params))
            $failed = false;
    }

    if ($failed)
        echo 'error';
}

function ah_system_alert($opts = array()) {

    $output = '<table>';

    $sys_img = "fa-check-circle-o";
    $sys_msg = _('Everything is OK!');
    $sys_img_color = "ok-indicator";

    // get the sysstat info first
    $sysstat_rows = fusion_subsys_status_get_sysstat_rows();
    foreach ($sysstat_rows as $row) {

        get_subsys_row_data($row, $metric, $img, $msg, $color, $status);
        if ($status != SUBSYS_OK && $status != 'no_data') {
            $sys_img = $img;
            $sys_msg = _('There are some problems with the system!');
            $sys_img_color = "warning-indicator";
        }

        $url_open = "<a href='" . get_base_url() . "admin/?fusionwindow=sysstat.php' title='{$msg}'>";
        $url_close = '</a>';

        if (!is_admin()) {
            $url_open = '<span>';
            $url_close = '</span>';
        }

        $output .= '<tr>';
        $output .= '<td>';
        $output .= $url_open;
        $output .= "<i class='fa {$img} {$color} fa-lg' alt='{$msg}' title='{$msg}' aria-hidden='true'></i>";
        $output .= $url_close;
        $output .= '</td>';
        $output .= '<td>';
        $output .= $url_open;
        $output .= $metric;
        $output .= $url_close;
        $output .= '</td>';
        $output .= '</tr>';
    }

    $output .= '</table>';

    $sys_img = '<i class="fa ' . $sys_img . ' ' . $sys_img_color . ' fa-lg" alt="' . $sys_msg . '" aria-hidden="true"></i>';
    $_system = _('System');

    echo '<a id="topalert-popover" title="' . $sys_msg . '" data-placement="bottom" data-content="' . $output . '"><label class="popup-label">'. $_system . '</label>' . $sys_img . '</a>';
}

function ah_fused_server_alerts($opts = array()) {
    
    $output = '<table>';

    $sys_img = "fa-check-circle-o";
    $sys_msg = _('Everything is OK!');
    $sys_img_color = "ok-indicator";

    // get the fused server statuses
    $servers = get_servers();
    $auto_logins = get_auto_logins(0, null);
    $base_url = get_base_url();
    if (count($servers) > 0) {

        foreach ($servers as $server) {

            if (get_fused_server_data($server, $server_name, $server_type, $img, $msg, $color, $ok) === false)
                continue;

                $auto = '<span class="auto-login">&nbsp;</span>';

                $url = $server['url'];

                // Search logins and find matching server login... or not
                foreach ($auto_logins as $al) {
                    if ($al['server_id'] == $server['server_id']) {
                        if ($al['enabled']) {
                            $auto = '<span class="auto-login tt-bind" title="'._('Auto logged in').'" data-placement="right"><i class="fa fa-14 fa-check"></i></span>';

                            // if its basic auth we need to pass THIS auto_login username and password to the url
                            // instead of using the server's url
                            if ($server['authentication_type'] == AUTH_TYPE_BASIC) {

                                $user = $al['username'];
                                $pass = _decrypt($al['password']);

                                $url = get_server_base_url($server, false, $user, $pass);
                            }
                        } else {

                            $saved_creds_url = '';
                            if ($server['server_type'] == SERVER_TYPE_XI) {

                                $saved_creds_url = $base_url . 'login.php?external&server_id=' . $al['server_id'];

                            } else if ($server['server_type'] == SERVER_TYPE_CORE) {

                                $user = $al['username'];
                                $pass = _decrypt($al['password']);

                                $saved_creds_url = get_server_base_url($server, false, $user, $pass);
                            }

                            $auto = '
                                <span class="auto-login tt-bind" title="' . _('Login with saved credentials') . '" data-placement="right">
                                    <a class="external-login" href="' . $saved_creds_url . '" target="_blank">
                                        <i class="fa fa-14 fa-sign-in"></i>
                                    </a>
                                </span>';
                        }
                    }
                }

            if ($ok != true) {
                $sys_img = $img;
                $sys_msg = _('There are some problems with the fused servers!');
                $sys_img_color = "warning-indicator";
            }

            $_edit = _('Edit Settings');
            $url_open = "<a href='" . get_base_url() . "admin/?fusionwindow=".urlencode('servers.php?edit=1&server_id='.$server['server_id'])."' title='{$msg}'>";
            $url_close = "</a>";
            $url_open_padding = "<a title='{$msg}' style='margin-left: 5px; pointer-events: none;'>";
            $url_to_server_open = "<a href='" . $url . "' target='_blank' style='padding-left: 30px; padding-right: 5px;'>";
            $edit_img = "<i class='fa fa-cog fa-lg' alt='{$_edit}' title='{$_edit}'>";

            if (!is_admin()) {
                $url_open = '<span>';
                $url_close = '</span>';
                $edit_img = "<i>";
            }

            $_sign_into_server = _('Sign into server');
            $output .= '<tr>';
            $output .= '<td>';
            $output .= "<i class=' fa {$img} {$color} fa-lg' alt='{$msg}' title='{$msg}'>";
            $output .= '</td>';
            $output .= '<td>';
            $output .= $url_open_padding;
            $output .= encode_html($server_name);
            $output .= $url_close;
            $output .= '</td>';
            $output .= '<td>';
            $output .= $url_to_server_open;
            $output .= "<i class='fa fa-sign-in fa-lg' alt'{$_sign_into_server}' title='{$_sign_into_server}'";
            $output .= $url_close;
            $output .= '</td>';
            $output .= '<td>';
            $output .= $url_open;
            $output .= $edit_img;
            $output .= $url_close;
            $output .= '</td>';
            $output .= '</tr>';
        }
    } else {
        $output .= "<tr><td colspan='4' align='center'><strong><a>" . _('No fused servers') . '</a></strong></td></tr>';
    }

    $output .= '</table>';

    $sys_img = '<i class="fa ' . $sys_img . ' ' . $sys_img_color . ' fa-lg" alt="' . $sys_msg . '" aria-hidden="true"></i>';
    $_server = _('Servers');

    echo '<a id="topalert-popover-servers" title="' . $sys_msg . '" data-placement="bottom" data-content="' . $output . '"><label class="popup-label">' . $_server . '</label>' . $sys_img . '</a>';
}

function truncate_polling_locks() {

    global $db;

    $db->query('TRUNCATE TABLE polling_lock');
    $result = $db->exec();

    if ($result == 1) {
        echo "Successfully cleared polling locks.";
    } else {
        echo "Failed to clear polling locks.";
    }

}

function authenticate_auto_login($opts = array()) {
    $auto_logins_raw = get_auto_logins();
    $auto_logins = array();
    
    foreach ($auto_logins_raw as $index => $auto_login) {
        $server_id = $auto_login['server_id'];
        $server = get_server($server_id);
        $version = get_version($server_id);
        
        if( version_compare($version, '5.5.0', '>=') ) {
            $username = $auto_login['username'];
            $password = _decrypt($auto_login['password']);
            $base_url = get_server_base_url($server_id, false);
    
            $auto_logins[] = array(
                "use_api" => true,
                "server_id" => $server_id,
                "server_user" => $username,
                "server_pass" => $password,
                "server_url" => $base_url,
            );
        } else {
            $auto_logins[] = array(
                "use_api" => false
            );
        }
    }
    
    echo json_encode($auto_logins);
}

function get_subsys_row_data($row, &$metric, &$img, &$msg, &$color, &$status = null) {

    $metric = fusion_subsys_status_metric_to_readable($row['metric']);
    $value = $row['value'];

    // keep formatted and non formatted so we can use strtotime in calculations
    $update_time = convert_timestring_to_local_users_time($row['update_time'], true);
    $time = convert_timestring_to_local_users_time($row['update_time'], false);

    // default to being ok
    $status = $value;

    switch ($status) {
        case SUBSYS_OK:
            $img = "fa-check-circle-o";
            $msg = $metric . _(' reported OK');
            $color = "ok-indicator";
            break;
        case SUBSYS_STOPPED:
            $img = "fa-stop-circle-o";
            $msg = $metric . _(' reported STOPPED');
            $color = "warning-indicator";
            break;
        case SUBSYS_ERROR:
            $img = "fa-exclamation-circle";
            $msg = $metric . _(' reported ERROR');
            $color = "critical-indicator";
            break;
        case SUBSYS_UNKNOWN:
            $img = "fa-exclamation-triangle";
            $msg = $metric . _(' reported UNKNOWN');
            $color = "warning-indicator";
            break;
    }

    if ($status !== 'no_data') {

        // if it didn't run in the last 5 minutes
        // then its only a warning
        if (time() - 300 > strtotime($time)) {

            $msg = get_icon_url('warning_small.png');
            $msg = $metric . _(' last check was over 5 minutes ago');
        }

        // if it didn't run in the last 10 minutes
        // its a serious problem
        if (time() - 600 > strtotime($time)) {

            $msg = get_icon_url('critical_small.png');
            $msg = $metric . _(' last check was over 10 minutes ago');
        }
    }

    // append users formatted date to msg
    $msg .= " ({$update_time})";
}

function get_fused_server_data($server, &$server_name, &$server_type, &$img, &$msg, &$color, &$ok = null) {

    $server = get_server($server);
    if ($server === false)
        return false;

    $server_name = encode_html($server['name']);
    $server_type = server_type_to_readable($server['server_type']);

    $img = "fa-check-circle-o";
    $msg = _('Authentication OK');
    $color = "ok-indicator";
    $ok = true;

    if (check_server_authentication($server, $failure_on_stale = true) === false) {
        $img = "fa-exclamation-circle";
        $msg = _('Authentication Failed');
        $color = "critical-indicator";
        $ok = false;
    }

    $msg .= encode_form_val(' (' . $server['last_auth_time'] . ')');
}

function get_source_bw_data($opts) {
    $server = grab_request_var("server_id", "");
    
    $bandwidth_data = get_server_polled_key($server, 'nna_sources_bandwidth', $limit = 1, $user_id = 0);
    $bandwidth = unpack_array($bandwidth_data[0]['nna_sources_bandwidth']);

    echo json_encode($bandwidth);
}

function ah_check_auth($opts) {
    check_authentication(false);
}

function ah_update_status_pages_refresh($opts) {
    $refresh_rate = grab_array_var($opts, 'refresh_rate', '');

    set_option("status_pages_refresh_rate", $refresh_rate);
}

// Anniversary Key
function ah_get_25_year_celebration_license_popup($opts) {
    echo get_25_year_celebration_license_popup_content($opts['key'], $opts['needs_acknowledgement']);
}

function ah_check_25_year_celebration_license($opts) {
    echo validate_25_year_celebration_license($opts['key']);
}