Merge pull request #603 from HB9HIL/installer_v2

[INSTALLER] Next generation of the Wavelog Installer
This commit is contained in:
HB9HIL
2024-07-28 13:10:03 +02:00
committed by GitHub
24 changed files with 1967 additions and 37870 deletions

4
.gitignore vendored
View File

@@ -1,13 +1,13 @@
/application/config/database.php
/application/config/config.php
/application/logs/*.php
/application/logs/*
/application/cache/*
/uploads
/uploads/*.adi
/uploads/*.ADI
/uploads/*.tq8
/uploads/*.TQ8
/install/*
/install/.lock
/updates/*.xml
/updates/*.html
/images/eqsl_card_images/*.jpg

View File

@@ -1,13 +1,24 @@
<?php class Migrate extends CI_Controller {
<?php
class Migrate extends CI_Controller {
public function index()
{
$this->load->library('Migration');
public function index() {
$this->load->library('Migration');
if (!$this->migration->latest()) {
show_error($this->migration->error_string());
$result = array();
$latest = $this->migration->latest();
if (!$latest) {
show_error($this->migration->error_string());
log_message('error', 'Migration failed');
$result['status'] = 'error';
} else {
while (file_exists(APPPATH . 'cache/.migration_running')) {
sleep(1);
}
$result['status'] = 'success';
$result['version'] = $latest;
}
header('Content-Type: application/json');
echo json_encode($result);
}
}
} ?>
}

View File

@@ -36,7 +36,9 @@ class Update extends CI_Controller {
public function dxcc_entities() {
// Load the cty file
$this->load->library('Paths');
if(!$this->load->is_loaded('Paths')) {
$this->load->library('Paths');
}
$xml_data = simplexml_load_file($this->paths->make_update_path("cty.xml"));
//$xml_data->entities->entity->count();
@@ -87,7 +89,9 @@ class Update extends CI_Controller {
public function dxcc_exceptions() {
// Load the cty file
$this->load->library('Paths');
if(!$this->load->is_loaded('Paths')) {
$this->load->library('Paths');
}
$xml_data = simplexml_load_file($this->paths->make_update_path("cty.xml"));
$count = 0;
@@ -129,7 +133,9 @@ class Update extends CI_Controller {
public function dxcc_prefixes() {
// Load the cty file
$this->load->library('Paths');
if(!$this->load->is_loaded('Paths')) {
$this->load->library('Paths');
}
$xml_data = simplexml_load_file($this->paths->make_update_path("cty.xml"));
$count = 0;
@@ -169,7 +175,9 @@ class Update extends CI_Controller {
// Updates the DXCC & Exceptions from the Club Log Cty.xml file.
public function dxcc() {
$this->load->library('Paths');
if(!$this->load->is_loaded('Paths')) {
$this->load->library('Paths');
}
// set the last run in cron table for the correct cron id
$this->load->model('cron_model');
@@ -192,7 +200,7 @@ class Update extends CI_Controller {
if ($gz === FALSE) {
$this->update_status("FAILED: Could not download from clublog.org");
log_message('error', 'FAILED: Could not download exceptions from clublog.org');
return;
exit();
}
$data = "";
@@ -203,7 +211,7 @@ class Update extends CI_Controller {
if (file_put_contents($this->paths->make_update_path("cty.xml"), $data) === FALSE) {
$this->update_status("FAILED: Could not write to cty.xml file");
return;
exit();
}
// Clear the tables, ready for new data
@@ -220,21 +228,25 @@ class Update extends CI_Controller {
$this->db->trans_complete();
$this->update_status(__("DONE"));
echo 'success';
}
public function update_status($done=""){
$this->load->library('Paths');
if(!$this->load->is_loaded('Paths')) {
$this->load->library('Paths');
}
if ($done != "Downloading file"){
// Check that everything is done?
if ($done == ""){
$done = "Updating...";
$done = __("Updating...");
}
$html = $done."<br/>";
$html .= "Dxcc Entities: ".$this->db->count_all('dxcc_entities')."<br/>";
$html .= "Dxcc Exceptions: ".$this->db->count_all('dxcc_exceptions')."<br/>";
$html .= "Dxcc Prefixes: ".$this->db->count_all('dxcc_prefixes')."<br/>";
$html .= __("Dxcc Entities:")." ".$this->db->count_all('dxcc_entities')."<br/>";
$html .= __("Dxcc Exceptions:")." ".$this->db->count_all('dxcc_exceptions')."<br/>";
$html .= __("Dxcc Prefixes:")." ".$this->db->count_all('dxcc_prefixes')."<br/>";
} else {
$html = $done."....<br/>";
}

View File

@@ -765,7 +765,7 @@ class User extends CI_Controller {
}
}
function login() {
function login($firstlogin = false) {
// Check our version and run any migrations
if (!$this->load->is_loaded('Migration')) {
$this->load->library('Migration');
@@ -775,6 +775,10 @@ class User extends CI_Controller {
}
$this->migration->current();
if($firstlogin == true) {
$this->session->set_flashdata('success', __("Congrats! Wavelog was successfully installed. You can now login for the first time."));
}
$this->load->model('user_model');
$query = $this->user_model->get($this->input->post('user_name', true));

View File

@@ -272,7 +272,7 @@
<p><u><?= __("Settings"); ?></u></p>
<?php
$max_execution_time = 600; // Seconds
$max_upload_file_size = 8; // Megabyte
$upload_max_filesize = 8; // Megabyte
$post_max_size = 8; // Megabyte
$memory_limit = 256; // Megabyte
$req_allow_url_fopen = '1'; // 1 = on
@@ -293,13 +293,13 @@
</tr>
<tr>
<td>max_upload_file_size</td>
<td><?php echo '> ' . $max_upload_file_size . 'M'; ?></td>
<td>upload_max_filesize</td>
<td><?php echo '> ' . $upload_max_filesize . 'M'; ?></td>
<td>
<?php
$maxUploadFileSize = ini_get('upload_max_filesize');
$maxUploadFileSizeBytes = (int)($maxUploadFileSize) * (1024 * 1024); // convert to bytes
if ($maxUploadFileSizeBytes >= ($max_upload_file_size * 1024 * 1024)) { // compare with given value in bytes
if ($maxUploadFileSizeBytes >= ($upload_max_filesize * 1024 * 1024)) { // compare with given value in bytes
?>
<span class="badge text-bg-success"><?php echo $maxUploadFileSize; ?></span>
<?php } else { ?>
@@ -631,4 +631,4 @@
<?= __("Spanish"); ?>
<?= __("Swedish"); ?>
<?= __("Turkish"); ?>
</div>
</div>

View File

@@ -1292,7 +1292,15 @@ $(document).ready(function(){
$(".ld-ext-right").addClass("running");
$(".ld-ext-right").prop("disabled", true);
$('#dxcc_update_status').show();
$.ajax({url:"update/dxcc"});
$.ajax({
url:"update/dxcc",
success: function(response) {
if (response == 'success') {
$(".ld-ext-right").removeClass("running");
$(".ld-ext-right").prop("disabled", false);
}
}
});
setTimeout(update_stats,5000);
});
function update_stats(){

View File

@@ -36,7 +36,7 @@ function l(o) {
const t = a(), e = i(t, o, "#fff"), n = i(t, o, "#000");
return n === e && !n.startsWith("0,0,0,");
}
function f(o = "Twemoji Country Flags", t = base_url + 'assets/fonts/TwemojiCountryFlags/TwemojiCountryFlags.woff2') {
function f(o = "Twemoji Country Flags", t = '../assets/fonts/TwemojiCountryFlags/TwemojiCountryFlags.woff2') {
if (typeof window < "u" && l("\u{1F60A}") && !l("\u{1F1E8}\u{1F1ED}")) {
const e = document.createElement("style");
return e.textContent = `@font-face {

17
install/ajax.php Normal file
View File

@@ -0,0 +1,17 @@
<?php
// Target for Ajax Calls
require_once('includes/install_config/install_lib.php');
require_once('includes/install_config/install_config.php');
require_once('includes/gettext/gettext.php');
require_once('includes/gettext/gettext_conf.php');
require_once('includes/core/core_class.php');
require_once('includes/core/database_class.php');
$core = new Core();
$database = new Database();
require_once('includes/interface_assets/triggers.php');

View File

@@ -1,6 +1,11 @@
/*!
* No overrides for the default theme as it aligns with general.css
*/
body {
font-family: "Twemoji Country Flags", "Helvetica", "Comic Sans", serif;
}
:root {
--cl-border-btn-pwd: var(--bs-body-bg);
}
@@ -205,8 +210,39 @@ div.alert-danger {
--bs-tooltip-opacity: 1;
}
#languageButton {
#languageButton, #advancedSettingsButton, #resetButton {
position: absolute;
bottom: 70px;
right: 20px;
}
.required:after {
content: " *";
color: red;
}
.required-prefix:before {
content: "* ";
color: red;
}
#logContainer {
display: none;
padding: 10px;
font-family: "Courier New", Courier, monospace;
font-size: 14px;
color: #a4a4a4;
white-space: pre-wrap;
text-align: left;
font-style: italic;
background-color: #1a1a1a;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.has-warning {
border-color: #ffc107;
}
.uppercase {
text-transform: uppercase;
}

File diff suppressed because it is too large Load Diff

View File

@@ -286,7 +286,7 @@ $config['allow_get_array'] = TRUE;
| your log files will fill up very fast.
|
*/
$config['log_threshold'] = 0;
$config['log_threshold'] = '%log_threshold%';
/*
|--------------------------------------------------------------------------
@@ -400,7 +400,7 @@ $config['cache_query_string'] = FALSE;
| https://codeigniter.com/user_guide/libraries/encryption.html
|
*/
$config['encryption_key'] = 'flossie1234555541';
$config['encryption_key'] = '%encryptionkey%';
/*
|--------------------------------------------------------------------------

View File

@@ -26,7 +26,7 @@ class Core
$counter++;
}
if ($data['directory'] != "") {
if ($data['directory'] ?? '' != "") {
if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/' . $data['directory'])) {
//pass folders real
$counter++;
@@ -39,33 +39,33 @@ class Core
}
// Validate First Name
if (isset($_POST['firstname']) && !empty($_POST['firstname'])) {
if (isset($data['firstname']) && !empty($data['firstname'])) {
$counter++;
}
// Validate Last Name
if (isset($_POST['lastname']) && !empty($_POST['lastname'])) {
if (isset($data['lastname']) && !empty($data['lastname'])) {
$counter++;
}
// Validate Username
if (isset($_POST['username']) && !empty($_POST['username'])) {
if (isset($data['username']) && !empty($data['username'])) {
$counter++;
}
// Validate Callsign
if (isset($_POST['callsign']) && !empty($_POST['callsign'])) {
if (isset($data['callsign']) && !empty($data['callsign'])) {
$counter++;
}
// Validate Password
if (isset($_POST['password']) && !empty($_POST['password'])) {
if (isset($data['password']) && !empty($data['password'])) {
$counter++;
}
// Validate Locator
if (isset($_POST['userlocator']) && !empty($_POST['userlocator'])) {
$locator = $_POST['userlocator'];
if (isset($data['userlocator']) && !empty($data['userlocator'])) {
$locator = $data['userlocator'];
if (preg_match('/^[A-R]{2}[0-9]{2}[A-X]{2}$/i', $locator)) {
$counter++;
} else {
@@ -76,19 +76,19 @@ class Core
}
// Validate Confirm Password
if (isset($_POST['cnfm_password']) && !empty($_POST['cnfm_password'])) {
if (isset($data['cnfm_password']) && !empty($data['cnfm_password'])) {
$counter++;
}
// Validate Email Address
if (isset($_POST['user_email']) && filter_var($_POST['user_email'], FILTER_VALIDATE_EMAIL)) {
if (isset($data['user_email']) && filter_var($data['user_email'], FILTER_VALIDATE_EMAIL)) {
$counter++;
} else {
$errors[] = "Invalid Email Address.";
}
// Validate Timezone
if (isset($_POST['timezone']) && is_numeric($_POST['timezone'])) {
if (isset($data['timezone']) && is_numeric($data['timezone'])) {
$counter++;
}
@@ -96,16 +96,11 @@ class Core
if ($counter == '13') {
return true;
} else {
log_message('error', 'Failed to validate POST data');
return false;
}
}
// Function to show an error
function show_message($type, $message)
{
return $message;
}
// Function to write the config file
function write_config($data) {
@@ -138,7 +133,11 @@ class Core
// Write the file
if (fwrite($handle, $new)) {
return true;
if(file_exists($output_path)) {
return true;
} else {
return false;
}
} else {
return false;
}
@@ -151,15 +150,18 @@ class Core
function write_configfile($data) {
$template_path = 'config/config.php';
$output_path = $_SERVER['DOCUMENT_ROOT'] . '/' . $data['directory'] . '/application/config/config.php';
$output_path = '../application/config/config.php';
if (isset($_ENV['CI_ENV'])) {
$output_path = $_SERVER['DOCUMENT_ROOT'] . '/' . $data['directory'] . '/application/config/'.$_ENV['CI_ENV'].'/config.php';
$output_path = '../application/config/'.$_ENV['CI_ENV'].'/config.php';
}
// Open the file
$database_file = file_get_contents($template_path);
$new = str_replace("%baselocator%", $data['locator'], $database_file);
// creating a unique encryption key
$encryptionkey = uniqid(bin2hex(random_bytes(8)), false);
$new = str_replace("%baselocator%", strtoupper($data['userlocator']), $database_file);
$new = str_replace("%websiteurl%", $data['websiteurl'], $new);
$new = str_replace("%directory%", $data['directory'], $new);
$new = str_replace("%callbook%", $data['global_call_lookup'], $new);
@@ -174,19 +176,22 @@ class Core
$new = str_replace("%hamqth_username%", $data['callbook_username'], $new);
$new = str_replace("%hamqth_password%", $data['callbook_password'], $new);
}
$new = str_replace("%encryptionkey%", $encryptionkey, $new);
$new = str_replace("'%log_threshold%'", $data['log_threshold'], $new);
// Write the new config.php file
$handle = fopen($output_path, 'w+');
// Chmod the file, in case the user forgot
@chmod($output_path, 0777);
// Verify file permissions
if (is_writable($output_path)) {
// Write the file
if (fwrite($handle, $new)) {
return true;
if(file_exists($output_path)) {
return true;
} else {
return false;
}
} else {
return false;
}

View File

@@ -1,30 +1,9 @@
<?php
class Database
{
// Function to the database and tables and fill them with the default data
function create_database($data)
{
// Connect to the database
$mysqli = new mysqli($data['db_hostname'], $data['db_username'], $data['db_password'], '');
// Check for errors
if (mysqli_connect_errno())
return false;
// Create the prepared statement
$mysqli->query("CREATE DATABASE IF NOT EXISTS " . $data['db_name']);
// Close the connection
$mysqli->close();
return true;
}
class Database {
// Function to create the tables and fill them with the default data
function create_tables($data)
{
function create_tables($data) {
// Connect to the database
$mysqli = new mysqli($data['db_hostname'], $data['db_username'], $data['db_password'], $data['db_name']);
@@ -39,8 +18,8 @@ class Database
$newquery = str_replace("%%FIRSTUSER_NAME%%", $data['username'], $query);
$newquery = str_replace("%%FIRSTUSER_PASS%%", $newpw, $newquery);
$newquery = str_replace("%%FIRSTUSER_MAIL%%", $data['user_email'], $newquery);
$newquery = str_replace("%%FIRSTUSER_CALL%%", $data['callsign'], $newquery);
$newquery = str_replace("%%FIRSTUSER_LOCATOR%%", $data['userlocator'], $newquery);
$newquery = str_replace("%%FIRSTUSER_CALL%%", strtoupper($data['callsign']), $newquery);
$newquery = str_replace("%%FIRSTUSER_LOCATOR%%", strtoupper($data['userlocator']), $newquery);
$newquery = str_replace("%%FIRSTUSER_FIRSTNAME%%", $data['firstname'], $newquery);
$newquery = str_replace("%%FIRSTUSER_LASTNAME%%", $data['lastname'], $newquery);
$newquery = str_replace("%%FIRSTUSER_TIMEZONE%%", $data['timezone'], $newquery);
@@ -67,24 +46,38 @@ class Database
return true;
}
function database_check($data)
{
function database_check($data) {
try {
$timeout = 5; /* five seconds for timeout */
$link = mysqli_init();
$link->options(MYSQLI_OPT_CONNECT_TIMEOUT, $timeout);
$link->real_connect($data['db_hostname'], $data['db_username'], $data['db_password'], $data['db_name']);
$link->real_connect($data['db_hostname'], $data['db_username'], $data['db_password']);
if ($link->connect_error) {
throw new Exception('Connection Error: ' . $link->connect_error);
throw new Exception(__("Connection Error: ") . $link->connect_error);
}
if (!$link->query("CREATE DATABASE IF NOT EXISTS " . $data['db_name'])) {
throw new Exception(__("Unable to create database: ") . $link->error);
}
// Wählen Sie die Datenbank aus
if (!$link->select_db($data['db_name'])) {
throw new Exception(__("Unable to select database: ") . $link->error);
}
$result = $link->query("SHOW TABLES");
if ($result->num_rows > 0) {
throw new Exception(__("Database is not empty."));
}
$mysql_version = $link->server_info;
$link->close();
return $mysql_version;
} catch (Exception $e) {
return 'Error: ' . $e->getMessage();

View File

@@ -76,10 +76,9 @@ function _get_client_language() {
global $default_lang;
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
$code = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
$lang = find_by('code', $code) ?: $default_lang;
$lang = find_by('code', $code) ?? find_by('folder', $default_lang);
} else {
$code = 'en';
$lang = find_by('code', $code);
$lang = find_by('folder', $default_lang);
}
return $lang;
}

View File

@@ -8,8 +8,6 @@
*
*/
$gt_conf['default_domain'] = 'installer';
$gt_conf['default_lang'] = 'english';

View File

@@ -0,0 +1,41 @@
<?php
/**
* PRECONFIGURATION
*/
$http_scheme = is_https() ? "https" : "http";
// Config Paths
$db_config_path = '../application/config/';
if (isset($_ENV['CI_ENV'])) {
$db_config_path = '../application/config/' . $_ENV['CI_ENV'] . '/';
}
$db_file_path = $db_config_path . "database.php";
// Logfile Path
global $logfile;
$logfile = '../application/logs/installer_debug.log';
// Wanted Pre-Check Parameters
// PHP
$min_php_version = '7.4.0'; // below this version is no install possible
$min_php_version_warning = '8.0.0'; // below this version some features may not available (e.g. Cronmanager)
$max_execution_time = 600; // Seconds
$upload_max_filesize = 8; // Megabyte
$memory_limit = 256; // Megabyte
$post_max_size = 8; // Megabyte
$req_allow_url_fopen = '1'; // 1 = on
// Array of PHP modules to check
global $required_php_modules;
$required_php_modules = [
'php-curl' => ['condition' => isExtensionInstalled('curl')],
'php-mysql' => ['condition' => isExtensionInstalled('mysqli')],
'php-mbstring' => ['condition' => isExtensionInstalled('mbstring')],
'php-xml' => ['condition' => isExtensionInstalled('xml')],
'php-zip' => ['condition' => isExtensionInstalled('zip')],
];
// MariaDB / MySQL
$mariadb_version = 10.1;
$mysql_version = 5.7;

View File

@@ -0,0 +1,135 @@
<?php
// Function to check if a PHP extension is installed
function isExtensionInstalled($extensionName) {
return in_array($extensionName, get_loaded_extensions());
}
// function to switch the language based on the user selection
function switch_lang($new_language) {
global $gt_conf;
setcookie($gt_conf['lang_cookie'], $new_language);
}
// check if page is called with https or not
function is_https() {
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
return true;
}
if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
return true;
}
if (!empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] === 'on') {
return true;
}
return false;
}
// Folder permission checks
function is_really_writable($path) {
// Check if the folder exists
if (!file_exists($path)) {
log_message('error', 'is_really_writable(): File "'.$path.'" does not exist.');
return false;
}
// Check if the folder is writable
try {
if (is_writable($path)) {
// Check if the subdirectories are writable (recursive check)
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
foreach ($iterator as $item) {
if ($item->isDir() && basename($item->getPathName()) != '..') {
if (!is_writable($item->getRealPath())) {
return false;
}
}
}
return true;
}
} catch (Exception $e) {
log_message('error', 'is_really_writable(): Something went wrong while testing write permissions.');
return false;
}
return false;
}
function verify_log() {
global $logfile;
if (!file_exists($logfile)) {
if (touch($logfile)) {
if(is_writable($logfile)) {
$log_header = "Wavelog Installer Debug Log\n-------\nLog Location: $logfile\n\n";
file_put_contents($logfile, $log_header, FILE_APPEND);
return true;
} else {
return false;
}
} else {
return false;
}
} else {
return is_writable($logfile);
}
}
function country2flag($code) {
$code = strtoupper($code);
$offset = 0x1F1E6;
$code_p1 = $offset + ord($code[0]) - ord('A');
$code_p2 = $offset + ord($code[1]) - ord('A');
$flag = mb_chr($code_p1, 'UTF-8') . mb_chr($code_p2, 'UTF-8');
return $flag;
}
// Function to read the debug logfile
function read_logfile() {
if (verify_log()) {
global $logfile;
$file_content = file_get_contents($logfile);
echo $file_content;
} else {
echo "Log file is not available.";
}
}
// Function to log messages in the installer logfile
function log_message($level, $message) {
if (verify_log()) {
global $logfile;
$level = strtoupper($level);
$timestamp = date("Y-m-d H:i:s");
$logMessage = $level . " - " . $timestamp . " --> " . $message . PHP_EOL;
file_put_contents($logfile, $logMessage, FILE_APPEND);
} else {
echo "Log file is not available or not writable.";
}
}
// Custom error handler
function customError($errno, $errstr, $errfile, $errline) {
$message = "[$errno] $errstr in $errfile on line $errline";
log_message('error', $message);
}
// Detect webserver and version
function detect_webserver() {
return $_SERVER['SERVER_SOFTWARE'] ?? __("not detected");
}
// Detect nginx setting for PHP file processing
function detect_nginx_php_setting($http_scheme) {
$ch = curl_init($http_scheme.'://'.$_SERVER['HTTP_HOST'].'/install/nginx.php/test');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, 0);
$data = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $code;
}

View File

@@ -0,0 +1,66 @@
<footer>
<script>
// restore data from the localstorage if available
$('#install_form input').each(function() {
var inputId = $(this).attr('id');
if (localStorage.getItem(inputId)) {
$(this).val(localStorage.getItem(inputId));
}
});
$('#install_form select').each(function() {
var inputId = $(this).attr('id');
if (localStorage.getItem(inputId)) {
$(this).val(localStorage.getItem(inputId));
}
});
// save data in the localstorage
$('#install_form input').on('input', function() {
var inputId = $(this).attr('id');
var inputValue = $(this).val();
localStorage.setItem(inputId, inputValue);
});
$('#install_form select').on('input', function() {
var inputId = $(this).attr('id');
var inputValue = $(this).val();
localStorage.setItem(inputId, inputValue);
});
// delete all data in localStorage and reload page
$('#resetInstaller').click(function() {
localStorage.clear();
location.reload();
});
</script>
<script type="module" defer>
import {
polyfillCountryFlagEmojis
} from "../assets/js/country-flag-emoji-polyfill.js";
polyfillCountryFlagEmojis();
</script>
<?php
/**
* Hidden field to be able to translate the language names
* Add english Language Name here if you add new languages to application/config/gettext.php
* This helps the po scanner to make them translatable
*/
?>
<div style="display: none">
<?= __("Bulgarian"); ?>
<?= __("Chinese (Simplified)"); ?>
<?= __("Czech"); ?>
<?= __("Dutch"); ?>
<?= __("English"); ?>
<?= __("Finnish"); ?>
<?= __("French"); ?>
<?= __("German"); ?>
<?= __("Greek"); ?>
<?= __("Italian"); ?>
<?= __("Portuguese"); ?>
<?= __("Polish"); ?>
<?= __("Russian"); ?>
<?= __("Spanish"); ?>
<?= __("Swedish"); ?>
<?= __("Turkish"); ?>
</div>
</footer>

View File

@@ -0,0 +1,105 @@
<?php
/**
* Includes needed stuff
*/
require_once('includes/install_config/install_lib.php');
require_once('includes/install_config/install_config.php');
require_once('includes/gettext/gettext.php');
require_once('includes/gettext/gettext_conf.php');
require_once('includes/core/core_class.php');
require_once('includes/core/database_class.php');
$core = new Core();
$database = new Database();
include('includes/interface_assets/triggers.php');
// Configure PHP to log errors
set_error_handler("customError");
ini_set('error_reporting', E_ALL);
/**
* Gettext Implementation
*/
/**
* save all available languages
* @var array $languages
*/
$languages = $gt_conf['languages'];
// if we come with a get call we can switch the language cookie
if (isset($_GET['lang'])) {
switch_lang($_GET['lang']);
log_message('info', 'Manually switched language to "' . find_by('gettext', $_GET['lang'])['name_en'] . '"');
header("Location: " . strtok($_SERVER['REQUEST_URI'], '?'));
exit();
}
// get the browsers language if no cookie exists and set one
if (!isset($_COOKIE[$gt_conf['lang_cookie']])) {
log_message('info', 'Called Installer index.php');
log_message('info', 'With URL: ' . $http_scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . '/');
log_message('info', 'From IP: ' . $_SERVER['REMOTE_ADDR']);
$browser_language = _get_client_language();
setcookie($gt_conf['lang_cookie'], $browser_language['gettext']);
log_message('info', 'Set language cookie to "' . $browser_language['name_en'] . '"');
header("Location: " . $_SERVER['REQUEST_URI']);
exit();
}
// get the language from the cookie
$language = $_COOKIE[$gt_conf['lang_cookie']];
// and set the locale for gettext
T_setlocale(LC_MESSAGES, $language);
$websiteurl = $http_scheme . '://' . str_replace("index.php", "", $_SERVER['HTTP_HOST'] . str_replace("/install/", "", $_SERVER['REQUEST_URI'])) . '/';
?>
<!DOCTYPE html>
<html lang="<?= $language; ?>">
<script>
function log_message(level, message) {
return new Promise((resolve, reject) => {
$.ajax({
type: 'POST',
url: 'ajax.php',
data: {
write_to_logfile: 1,
log_level: level,
log_message: message
},
success: function(response) {
resolve();
},
error: function(error) {
console.error("log_message (js) failed: ", error);
reject(error);
}
});
});
}
</script>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title><?= __("Install | Wavelog"); ?></title>
<link rel="icon" type="image/x-icon" href="../favicon.ico">
<link rel="stylesheet" href="../assets/css/darkly/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/installer.css">
<link rel="stylesheet" href="../assets/fontawesome/css/all.min.css">
<link rel="stylesheet" href="../assets/css/ldbtn.min.css">
<link rel="stylesheet" href="../assets/css/loading.min.css">
<script type="text/javascript" src="../assets/js/bootstrap.bundle.min.js"></script>
<script type="text/javascript" src="../assets/js/jquery-3.3.1.min.js"></script>
</head>

View File

@@ -0,0 +1,110 @@
<?php
/**
* Triggers for Ajax Calls
*/
// Database Check
if ($_POST['database_check'] ?? false == true) {
$result = $database->database_check($_POST);
echo $result;
exit;
}
if ($_POST['read_logfile'] ?? false == true) {
$result = read_logfile();
echo $result;
exit;
}
if ($_POST['write_to_logfile'] ?? false == true) {
$level = $_POST['log_level'];
$message = $_POST['log_message'];
if(log_message($level, $message)) {
$result = 'success';
} else {
$result = 'error';
}
echo $result;
exit;
}
/**
*
* Install Triggers
*
*/
if ($_POST['check_lockfile'] ?? false == true) {
$lockfile = '../install/.lock';
if (file_exists($lockfile)) {
$result = 'installer_locked';
} else {
$result = 'no_lockfile';
}
echo $result;
exit;
}
// config_file()
if ($_POST['run_config_file'] ?? false == true) {
sleep(1);
$data = $_POST['data'];
if ($core->validate_post($data)) {
if($core->write_configfile($data)) {
$result = 'success';
} else {
$result = 'error';
}
} else {
$result = 'error';
}
echo $result;
exit;
}
if ($_POST['run_database_file'] ?? false == true) {
sleep(1);
$data = $_POST['data'];
if ($core->validate_post($data)) {
if($core->write_config($data)) {
$result = 'success';
} else {
$result = 'error';
}
} else {
$result = 'error';
}
echo $result;
exit;
}
if ($_POST['run_database_tables'] ?? false == true) {
$data = $_POST['data'];
if ($core->validate_post($data)) {
$result = $database->create_tables($data);
} else {
$result = 'error';
}
echo $result ? 'success' : 'error';
exit;
}
if ($_POST['run_installer_lock'] ?? false == true) {
exec('touch .lock', $output, $return_var);
if ($return_var === 0 && file_exists('.lock')) {
echo 'success';
} else {
echo 'error';
}
exit;
}

File diff suppressed because it is too large Load Diff

9
install/nginx.php Normal file
View File

@@ -0,0 +1,9 @@
<?php
/*
This file is just for testing purposes to detect the correct
PHP settings for nginx web servers with php-fpm
Please ignore.
*/
echo "success";
?>

377
install/run.php Normal file
View File

@@ -0,0 +1,377 @@
<!DOCTYPE html>
<html>
<?php include 'includes/interface_assets/header.php'; ?>
<body>
<div class="container" style="max-width: 1200px; margin-top: 8rem; ">
<div class="card mt-4" style="min-height: 750px; margin: 0 auto;">
<div class="card-body text-center">
<h3 style="margin-top: 150px;"><?= __("Installation"); ?></h3>
<p style="margin-bottom: 60px;"><?= __("Please wait..."); ?></p>
<div class="mb-3" id="config_file" style="opacity: 50%;">
<i id="config_file_spinner" class="ld-ext-right"><?= __("Copy config.php to application/config/") ?><div class="ld ld-ring ld-spin"></div></i><i id="config_file_check" class="ms-2 fas fa-check-circle" style="display: none;"></i>
</div>
<div class="mb-3" id="database_file" style="opacity: 50%;">
<i id="database_file_spinner" class="ld-ext-right"><?= __("Copy database.php to application/config/") ?><div class="ld ld-ring ld-spin"></div></i><i id="database_file_check" class="ms-2 fas fa-check-circle" style="display: none;"></i>
</div>
<div class="mb-3" id="database_tables" style="opacity: 50%;">
<i id="database_tables_spinner" class="ld-ext-right"><?= __("Creating database tables") ?><div class="ld ld-ring ld-spin"></div></i><i id="database_tables_check" class="ms-2 fas fa-check-circle" style="display: none;"></i>
</div>
<div class="mb-3" id="database_migrations" style="opacity: 50%;">
<i id="database_migrations_spinner" class="ld-ext-right"><?= __("Running database migrations") ?><div class="ld ld-ring ld-spin"></div></i><i id="database_migrations_check" class="ms-2 fas fa-check-circle" style="display: none;"></i>
</div>
<div class="mb-3" id="update_dxcc" style="opacity: 50%;">
<i id="update_dxcc_spinner" class="ld-ext-right"><?= __("Updating DXCC data") ?><div class="ld ld-ring ld-spin"></div></i><i id="update_dxcc_check" class="ms-2 fas fa-check-circle" style="display: none;"></i>
</div>
<?php
// we can easily add more steps here if necessary
?>
<div class="mb-3" id="installer_lock" style="opacity: 50%;">
<i id="installer_lock_spinner" class="ld-ext-right"><?= __("Lock the installer") ?><div class="ld ld-ring ld-spin"></div></i><i id="installer_lock_check" class="ms-2 fas fa-check-circle" style="display: none;"></i>
</div>
<div class="mb-3" id="success_message" style="display: none;">
<p><?= sprintf(__("All install steps went through. Redirect to user login in %s seconds..."), "<span id='countdown'>4</span>"); ?></p>
</div>
<div class="mb-3" id="success_button" style="display: none;">
<a class="btn btn-primary" href="<?php echo $_POST['websiteurl'] ?? $websiteurl; ?>index.php/user/login/1"><?= __("Done. Go to the user login ->"); ?></a>
</div>
<div id="error_message"></div>
<div class="container mt-5">
<button id="toggleLogButton" class="btn btn-sm btn-secondary mb-3"><?= __("Show detailled debug log"); ?></button>
<div id="logContainer">
<pre>
<code id="debuglog">
<!-- Log Content -->
</code>
</pre>
</div>
</div>
</div>
</div>
</div>
</body>
<script>
let _POST = <?php echo json_encode($_POST); ?>;
$(document).ready(async function() {
init_read_log();
try {
await check_lockfile();
await config_file();
await database_file();
await database_tables();
await database_migrations();
await update_dxcc();
await installer_lock();
await log_message('info', 'Finish. Installer went through successfully.');
if ($('#logContainer').css('display') == 'none') {
// after all install steps went through we can show a success message and redirect to the user/login
$("#success_message").show();
// Initialize the countdown
var countdown = 4;
var countdownInterval = setInterval(function() {
countdown--;
$("#countdown").text(countdown);
if (countdown <= 0) {
clearInterval(countdownInterval);
window.location.href = _POST.websiteurl + "index.php/user/login/1";
}
}, 1000);
} else {
// after all install steps went through we can show the redirect button
$("#success_button").show();
}
} catch (error) {
var errormsg = '';
if (typeof error === 'object') {
errormsg = error.statusText;
} else {
errormsg = error;
}
$("#error_message").text("Installation failed: " + errormsg).show();
}
});
function init_read_log() {
setInterval(function() {
$.ajax({
type: 'POST',
url: 'ajax.php',
data: {
read_logfile: 1
},
success: function(response) {
$("#debuglog").text(response);
}
});
}, 500);
}
$('#toggleLogButton').on('click', function() {
var logContainer = $('#logContainer');
logContainer.toggle();
if (logContainer.css('display') == 'none') {
$('#toggleLogButton').text("<?= __("Show detailled debug log"); ?>");
} else {
$('#toggleLogButton').text("<?= __("Hide detailled debug log"); ?>");
}
});
// if a user goes back to the installer we need to redirect him
async function check_lockfile() {
return new Promise((resolve, reject) => {
$.ajax({
type: 'POST',
url: 'ajax.php',
data: {
check_lockfile: 1
},
success: async function(response) {
if (response != 'installer_locked') {
resolve();
} else {
await log_message('error', 'Attention: Installer is locked. Redirect to user/login.');
reject(response);
window.location.href = "<?php echo str_replace('run.php', '', $websiteurl); ?>" + "index.php/user/login";
}
},
error: async function(error) {
await log_message('error', "Install Lock Check went wrong...");
reject(error);
window.location.href = "<?php echo str_replace('run.php', '', $websiteurl); ?>" + "index.php/user/login";
}
});
});
}
async function config_file() {
var field = '#config_file';
running(field, true);
await log_message('debug', 'Start writing config.php');
return new Promise((resolve, reject) => {
$.ajax({
type: 'POST',
url: 'ajax.php',
data: {
data: _POST,
run_config_file: 1
},
success: async function(response) {
if (response == 'success') {
running(field, false);
await log_message('debug', 'File: config.php successfully written');
resolve();
} else {
running(field, false, true);
await log_message('error', 'File: Could not write file. Check Permissions.');
reject("<?= __("Could not create application/config/config.php"); ?>");
}
},
error: async function(error) {
await log_message('error', 'File: Could not write file. Ajax failed.');
running(field, false, true);
reject(error);
}
});
});
}
async function database_file() {
var field = '#database_file';
running(field, true);
await log_message('debug', 'Start writing database.php');
return new Promise((resolve, reject) => {
$.ajax({
type: 'POST',
url: 'ajax.php',
data: {
data: _POST,
run_database_file: 1
},
success: async function(response) {
if (response == 'success') {
running(field, false);
await log_message('debug', 'File: database.php successfully written');
resolve();
} else {
running(field, false, true);
await log_message('error', 'File: Could not write file. Check Permissions.');
reject("<?= __("Could not create application/config/database.php"); ?>");
}
},
error: async function(error) {
await log_message('error', 'File: Could not write file. Ajax failed.');
running(field, false, true);
reject(error);
}
});
});
}
async function database_tables() {
var field = '#database_tables';
running(field, true);
await log_message('debug', 'Start creating database structure with assets/install.sql');
return new Promise((resolve, reject) => {
$.ajax({
type: 'POST',
url: 'ajax.php',
data: {
data: _POST,
run_database_tables: 1
},
success: async function(response) {
if (response == 'success') {
await log_message('debug', 'Tables successfully created');
running(field, false);
resolve();
} else {
running(field, false, true);
await log_message('error', 'Creating database tables from assets/install.sql failed. Response: ' + response);
reject("<?= __("Could not create database tables"); ?>");
}
},
error: async function(error) {
running(field, false, true);
await log_message('error', 'Creating database tables failed. Ajax crashed.');
reject(error);
}
});
});
}
async function database_migrations() {
var field = '#database_migrations';
running(field, true);
await log_message('debug', 'Start migrating database to the newest version.');
return new Promise((resolve, reject) => {
$.ajax({
url: "<?php echo $_POST['websiteurl'] ?? $websiteurl; ?>" + "index.php/migrate",
dataType: 'json',
success: async function(response) {
if (response.status == 'success') {
running(field, false);
await log_message('debug', 'Database successfully migrated. Latest Version: ' + response.version);
resolve();
} else {
running(field, false, true);
await log_message('error', 'Could not migrate database. Response: ' + response.status);
reject("<?= __("Could not run database migrations"); ?>");
}
},
error: async function(error) {
running(field, false, true);
await log_message('error', 'Could not migrate database. Ajax crashed.');
reject(error);
}
});
});
}
async function update_dxcc() {
var field = '#update_dxcc';
await log_message('debug', 'Start updating DXCC database. This can take a moment or two... Please wait');
running(field, true);
return new Promise((resolve, reject) => {
$.ajax({
url: "<?php echo $_POST['websiteurl'] ?? $websiteurl; ?>" + "index.php/update/dxcc",
success: async function(response) {
if (response == 'success') {
running(field, false);
await log_message('debug', 'Successfully update DXCC database');
resolve();
} else {
running(field, false, true);
await log_message('error', 'Could not update DXCC data.');
reject("<?= __("Could not update DXCC data"); ?>");
}
},
error: async function(error) {
running(field, false, true);
await log_message('error', 'Could not update DXCC data. Ajax crashed.');
reject(error);
}
});
});
}
async function installer_lock() {
var field = '#installer_lock';
await log_message('debug', 'Try to create .lock file for the installer');
running(field, true);
return new Promise((resolve, reject) => {
$.ajax({
type: 'POST',
url: 'ajax.php',
data: {
run_installer_lock: 1
},
success: async function(response) {
if (response == 'success') {
running(field, false);
await log_message('debug', 'Successfully created .lock file in folder /install');
resolve();
} else {
running(field, false, true);
await log_message('error', 'Could not create .lock file.');
reject("<?= __("Could not create install/.lock file"); ?>");
}
},
error: async function(error) {
running(field, false, true);
await log_message('error', 'Could not create .lock file. Ajax crashed');
reject(error);
}
});
});
}
//
function running(field, running, failure = false) {
if (running) {
$(field).css('opacity', '100%');
$(field + '_spinner').addClass("running");
} else {
$(field + '_spinner').removeClass("running");
if (failure) {
$(field + '_check').addClass('fa-times-circle');
$(field + '_check').css('color', 'red');
} else {
$(field + '_check').addClass('fa-check-circle');
$(field + '_check').css('color', '#04a004');
}
$(field + '_check').css('display', 'inline');
}
}
</script>
<?php include 'includes/interface_assets/footer.php'; ?>
</html>

View File

@@ -235,7 +235,7 @@ class CI_Migration {
else
{
// Well, there's nothing to migrate then ...
return TRUE;
return $current_version;
}
// Validate all available migrations within our target range.