lang);
        require_once './lang/en_US.utf8.php';
        $this->defaultlang = new en_US();
        require_once './lang/' . $settings->lang . '.php';
        $lang_class = substr($settings->lang, 0, strpos($settings->lang, ".")); // grab "en_US" from "en_US.utf8"
        if ($lang_class !== "en_US" && class_exists($lang_class)) {
            $this->lang = new $lang_class;
        } else {
            $this->lang = $this->defaultlang;
        }
        $this->time = microtime(true);
        if ($header) {
            require_once './inc/header.php';
        }
        $this->conn = $settings->conn;
        $this->settings = $settings;
        $this->uuid_name_cache = array();
        $this->name = $name;
        $this->type = null;
        $this->table = null;
        $this->title = null;
        $info = $this->type_info($name);
        $this->set_info($info);
        $this->permanent = array(
            'ban'  => $this->t("generic.permanent.ban"),
            'mute' => $this->t("generic.permanent.mute"),
            'warn' => $this->t("generic.permanent"),
            'kick' => null,
        );
        $this->expired = array(
            'ban'  => $this->t("page.expired.ban"),
            'mute' => $this->t("page.expired.mute"),
            'warn' => $this->t("page.expired.warning"),
            'kick' => null,
        );
        $this->expired_by = array(
            'ban'  => $this->t("page.expired.ban-by"),
            'mute' => $this->t("page.expired.mute-by"),
            'warn' => $this->t("page.expired.warning"),
            'kick' => null,
        );
        $this->punished_by = array(
            'ban'  => $this->t("generic.banned.by"),
            'mute' => $this->t("generic.muted.by"),
            'warn' => $this->t("generic.warned.by"),
            'kick' => $this->t("generic.kicked.by"),
        );
        $this->table_headers_printed = false;
        $this->args = array_values($_GET);
        $this->is_index = ((substr($_SERVER['SCRIPT_NAME'], -strlen("index.php"))) === "index.php");
        if ($this->is_index) {
            $this->index_base_path = substr($_SERVER["PHP_SELF"], 0, -strlen("index.php"));
            if ($settings->simple_urls) {
                $keys = array_keys($_GET);
                $request_path = $keys[0];
                $local_path = substr($request_path, strlen($this->index_base_path));
                $this->args = explode("/", substr($local_path, strpos($local_path, "/") + 1));
            }
        }
        $argc = count($this->args);
        $this->page = 1;
        $page = "1";
        if (isset($_GET['page'])) {
            $page = $_GET['page']; // user input
        } else {
            if ($argc > 1) {
                $page = $this->args[$argc - 2];
            }
        }
        if (filter_var($page, FILTER_VALIDATE_INT)) {
            $this->page = max(0, (int)$page);
        }
        if ($header) {
            $h = new Header($this);
            $this->header = $h;
            $h->print_header();
        }
    }
    public function get_requested_page() {
        $keys = array_keys($_GET);
        if (count($keys) == 0 || !$this->is_index) return "";
        $request_path = $keys[0];
        $local_path = substr($request_path, strlen($this->index_base_path));
        return substr($local_path, 0, strpos($local_path, "/"));
    }
    public function t($str) {
        if (array_key_exists($str, $this->lang->array)) {
            return $this->lang->array[$str];
        }
        if (array_key_exists($str, $this->defaultlang->array)) {
            return $this->defaultlang->array[$str];
        }
//        return "404";
        return $str;
    }
    public function type_info($type) {
        $settings = $this->settings;
        switch ($type) {
            case "ban":
            case "bans":
                return array(
                    "type"  => "ban",
                    "table" => $settings->table['bans'],
                    "title" => $this->t("title.bans"),
                    "page"  => "bans.php",
                );
            case "mute":
            case "mutes":
                return array(
                    "type"  => "mute",
                    "table" => $settings->table['mutes'],
                    "title" => $this->t("title.mutes"),
                    "page"  => "mutes.php",
                );
            case "warn":
            case "warnings":
                return array(
                    "type"  => "warn",
                    "table" => $settings->table['warnings'],
                    "title" => $this->t("title.warnings"),
                    "page"  => "warnings.php",
                );
            case "kick":
            case "kicks":
                return array(
                    "type"  => "kick",
                    "table" => $settings->table['kicks'],
                    "title" => $this->t("title.kicks"),
                    "page"  => "kicks.php",
                );
            default:
                return array(
                    "type"  => null,
                    "table" => null,
                    "title" => null,
                    "page"  => null,
                );
        }
    }
    /**
     * @param $info
     */
    function set_info($info) {
        $this->type = $info['type'];
        $this->table = $info['table'];
        $this->title = $info['title'];
    }
    function run_query() {
        try {
            $table = $this->table; // Safe user input (constants only)
            $limit = $this->settings->limit_per_page; // Not user input
            $offset = 0;
            if ($this->settings->show_pager) {
                $page = $this->page - 1;
                $offset = ($limit * $page);
            }
            $select = $this->get_selection($table); // Not user input
            $where = $this->where_append($this->name === "kicks" ? "" : $this->settings->active_query); // Not user input
            $where .= "(uuid <> '#offline#' AND uuid IS NOT NULL)";
            $st = $this->conn->prepare("SELECT $select FROM $table $where GROUP BY $table.id ORDER BY time DESC LIMIT :limit OFFSET :offset");
            $st->bindParam(':offset', $offset, PDO::PARAM_INT);
            $st->bindParam(':limit', $limit, PDO::PARAM_INT);
            $st->execute();
            $rows = $st->fetchAll(PDO::FETCH_ASSOC);
            $st->closeCursor();
            return $rows;
        } catch (PDOException $ex) {
            Settings::handle_error($this->settings, $ex);
            return array();
        }
    }
    function get_selection($table, $phpIsBroken = true) {
        $columns = array("id", "uuid", "reason", "banned_by_name", "banned_by_uuid", "time", "until", "server_origin", "server_scope", "active", "ipban");
        $bitColumns = array("active", "ipban");
        if ($table === $this->settings->table['warnings']) {
            array_push($columns, "warned");
            array_push($bitColumns, "warned");
        }
        if ($table !== $this->settings->table['kicks']) {
            array_push($columns, "removed_by_uuid", "removed_by_name", "removed_by_date");
        }
        // Under certain versions of PHP, there is a bug with BIT columns.
        // An empty string is returned no matter what the value is.
        // Workaround: cast to unsigned.
        if ($phpIsBroken === true) {
            foreach ($bitColumns as $column) {
                unset($columns[$column]);
                array_push($columns, "CAST($column AS UNSIGNED) AS $column");
            }
        }
        return implode(",", $columns);
    }
    /**
     * Returns HTML representing the Minecraft avatar for a specific name or UUID.
     * @return string
     */
    function get_avatar($name, $uuid, $name_under = true, $name_repl = null, $name_left = true) {
        if ($name_under) {
            $name_under = $this->settings->avatar_names_below;
        }
        $avatar_source = $this->settings->avatar_source;
        if (strlen($uuid) === 36 && $uuid[14] === '3') {
            $avatar_source = $this->settings->avatar_source_offline_mode;
        }
        $uuid = $this->uuid_undashify($uuid);
        $src = str_replace('{name}', $name, str_replace('{uuid}', $uuid, $avatar_source));
        if (in_array($name, $this->settings->console_aliases) || $name === $this->settings->console_name) {
            $src = $this->resource($this->settings->console_image);
            $name = $this->settings->console_name;
        }
        if ($name_repl !== null) {
            $name = $name_repl;
        }
        $img = "";
        $str = "{$img}$name";
        if ($name_under) {
            $str = "{$img}
$name";
            return "