mirror of
https://github.com/itflow-org/itflow
synced 2026-03-06 13:54:51 +00:00
Merge branch 'develop' of https://github.com/itflow-org/itflow into develop
This commit is contained in:
@@ -8,7 +8,7 @@ require_once "includes/inc_all_admin.php";
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-body" style="text-align: center;">
|
<div class="card-body" style="text-align: center;">
|
||||||
<div class="alert alert-secondary">If you are unable to back up the entire VM, you'll need to back up the files & database individually. There is no built-in restore. See the <a href="https://docs.itflow.org/backups" target="_blank">docs here</a>.</div>
|
<div class="alert alert-secondary">If you are unable to back up the entire VM, you'll need to back up the files & database individually. There is no built-in restore. See the <a href="https://docs.itflow.org/backups" target="_blank">docs here</a>.</div>
|
||||||
<a class="btn btn-primary btn-lg p-3" href="post.php?download_database&csrf_token=<?php echo $_SESSION['csrf_token'] ?>"><i class="fas fa-fw fa-4x fa-download"></i><br><br>Download database</a>
|
<a class="btn btn-primary btn-lg p-3" href="post.php?download_backup&csrf_token=<?php echo $_SESSION['csrf_token'] ?>"><i class="fas fa-fw fa-4x fa-download"></i><br><br>Download Backup</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -24,40 +24,49 @@ ob_start();
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-body bg-white">
|
<div class="modal-body bg-white">
|
||||||
|
<table class="table table-sm table-hover table-borderless">
|
||||||
<?php if ($num_notifications) { ?>
|
<?php if ($num_notifications) { ?>
|
||||||
|
|
||||||
<?php while ($row = mysqli_fetch_array($sql)) {
|
<?php while ($row = mysqli_fetch_array($sql)) {
|
||||||
|
|
||||||
$notification_id = intval($row["notification_id"]);
|
$notification_id = intval($row["notification_id"]);
|
||||||
$notification_type = nullable_htmlentities($row["notification_type"]);
|
$notification_type = nullable_htmlentities($row["notification_type"]);
|
||||||
$notification_details = nullable_htmlentities($row["notification"]);
|
$notification_details = nullable_htmlentities($row["notification"]);
|
||||||
$notification_action = nullable_htmlentities(
|
$notification_action = nullable_htmlentities(
|
||||||
$row["notification_action"]
|
$row["notification_action"]
|
||||||
);
|
);
|
||||||
$notification_timestamp_formated = date(
|
$notification_timestamp_formated = date(
|
||||||
"M d g:ia",
|
"M d g:ia",
|
||||||
strtotime($row["notification_timestamp"])
|
strtotime($row["notification_timestamp"])
|
||||||
);
|
);
|
||||||
$notification_client_id = intval($row["notification_client_id"]);
|
$notification_client_id = intval($row["notification_client_id"]);
|
||||||
if (empty($notification_action)) {
|
if (empty($notification_action)) {
|
||||||
$notification_action = "#";
|
$notification_action = "#";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<tr class="notification-item">
|
||||||
|
<th>
|
||||||
|
<a class="text-dark" href="<?php echo $notification_action; ?>">
|
||||||
|
<i class="fas fa-bullhorn mr-2"></i><?php echo $notification_type; ?>
|
||||||
|
<small class="text-muted float-right">
|
||||||
|
<?php echo $notification_timestamp_formated; ?>
|
||||||
|
</small>
|
||||||
|
<br>
|
||||||
|
<small class="text-secondary text-wrap"><?php echo $notification_details; ?></small>
|
||||||
|
</a>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<?php
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
</table>
|
||||||
<a class="text-dark dropdown-item px-1" href="<?php echo $notification_action; ?>">
|
<div class="text-center mt-2">
|
||||||
<div>
|
<button id="prev-btn" class="btn btn-sm btn-outline-secondary mr-2"><i class="fas fa-caret-left"></i></button>
|
||||||
<span class="text-bold">
|
<button id="next-btn" class="btn btn-sm btn-outline-secondary"><i class="fas fa-caret-right"></i></button>
|
||||||
<i class="fas fa-bullhorn mr-2"></i><?php echo $notification_type; ?>
|
|
||||||
</span>
|
|
||||||
<small class="text-muted float-right">
|
|
||||||
<?php echo $notification_timestamp_formated; ?>
|
|
||||||
</small>
|
|
||||||
</div>
|
</div>
|
||||||
<small class="text-secondary text-wrap"><?php echo $notification_details; ?></small>
|
<?php } else { ?>
|
||||||
</a>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
}} else { ?>
|
|
||||||
<div class="text-center text-secondary py-5">
|
<div class="text-center text-secondary py-5">
|
||||||
<i class='far fa-6x fa-bell-slash'></i>
|
<i class='far fa-6x fa-bell-slash'></i>
|
||||||
<h3 class="mt-3">No Notifications</h3>
|
<h3 class="mt-3">No Notifications</h3>
|
||||||
@@ -85,4 +94,41 @@ ob_start();
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
var perPage = 5;
|
||||||
|
var $items = $(".notification-item");
|
||||||
|
var totalItems = $items.length;
|
||||||
|
var totalPages = Math.ceil(totalItems / perPage);
|
||||||
|
var currentPage = 0;
|
||||||
|
|
||||||
|
function showPage(page) {
|
||||||
|
$items.hide().slice(page * perPage, (page + 1) * perPage).show();
|
||||||
|
$("#prev-btn").prop("disabled", page === 0);
|
||||||
|
$("#next-btn").prop("disabled", page >= totalPages - 1);
|
||||||
|
$("#page-indicator").text(`Page ${page + 1} of ${totalPages} (${totalItems} total)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#prev-btn").on("click", function () {
|
||||||
|
if (currentPage > 0) {
|
||||||
|
currentPage--;
|
||||||
|
showPage(currentPage);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#next-btn").on("click", function () {
|
||||||
|
if (currentPage < totalPages - 1) {
|
||||||
|
currentPage++;
|
||||||
|
showPage(currentPage);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (totalItems <= perPage) {
|
||||||
|
$("#prev-btn, #next-btn, #page-indicator").hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
showPage(currentPage);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<?php require_once "../includes/ajax_footer.php";
|
<?php require_once "../includes/ajax_footer.php";
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ if (isset($_GET['asset_id'])) {
|
|||||||
$ticket_count = mysqli_num_rows($sql_related_tickets);
|
$ticket_count = mysqli_num_rows($sql_related_tickets);
|
||||||
|
|
||||||
// Related Recurring Tickets Query
|
// Related Recurring Tickets Query
|
||||||
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM recurring_tickets
|
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT recurring_tickets.* FROM recurring_tickets
|
||||||
LEFT JOIN recurring_ticket_assets ON recurring_tickets.recurring_ticket_id = recurring_ticket_assets.recurring_ticket_id
|
LEFT JOIN recurring_ticket_assets ON recurring_tickets.recurring_ticket_id = recurring_ticket_assets.recurring_ticket_id
|
||||||
WHERE recurring_ticket_asset_id = $asset_id OR recurring_ticket_assets.asset_id = $asset_id
|
WHERE recurring_ticket_asset_id = $asset_id OR recurring_ticket_assets.asset_id = $asset_id
|
||||||
GROUP BY recurring_tickets.recurring_ticket_id
|
GROUP BY recurring_tickets.recurring_ticket_id
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ if ($total_found_rows > 5) {
|
|||||||
<option <?php if ($user_config_records_per_page == 20) { echo "selected"; } ?> >20</option>
|
<option <?php if ($user_config_records_per_page == 20) { echo "selected"; } ?> >20</option>
|
||||||
<option <?php if ($user_config_records_per_page == 50) { echo "selected"; } ?> >50</option>
|
<option <?php if ($user_config_records_per_page == 50) { echo "selected"; } ?> >50</option>
|
||||||
<option <?php if ($user_config_records_per_page == 100) { echo "selected"; } ?> >100</option>
|
<option <?php if ($user_config_records_per_page == 100) { echo "selected"; } ?> >100</option>
|
||||||
<option <?php if ($user_config_records_per_page == 500) { echo "selected"; } ?> >500</option>
|
|
||||||
</select>
|
</select>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -28,37 +28,33 @@
|
|||||||
<!-- Right navbar links -->
|
<!-- Right navbar links -->
|
||||||
<ul class="navbar-nav ml-auto">
|
<ul class="navbar-nav ml-auto">
|
||||||
|
|
||||||
<?php if(CURRENT_DATABASE_VERSION > '1.4.5' ) { // Check DB Version REMOVE on Decemeber 1st 2024 -Johnny ?>
|
<!--Custom Nav Link -->
|
||||||
|
<?php
|
||||||
|
$sql_custom_links = mysqli_query($mysqli, "SELECT * FROM custom_links WHERE custom_link_location = 2 AND custom_link_archived_at IS NULL
|
||||||
|
ORDER BY custom_link_order ASC, custom_link_name ASC"
|
||||||
|
);
|
||||||
|
|
||||||
<!--Custom Nav Link -->
|
while ($row = mysqli_fetch_array($sql_custom_links)) {
|
||||||
<?php
|
$custom_link_name = nullable_htmlentities($row['custom_link_name']);
|
||||||
$sql_custom_links = mysqli_query($mysqli, "SELECT * FROM custom_links WHERE custom_link_location = 2 AND custom_link_archived_at IS NULL
|
$custom_link_uri = nullable_htmlentities($row['custom_link_uri']);
|
||||||
ORDER BY custom_link_order ASC, custom_link_name ASC"
|
$custom_link_icon = nullable_htmlentities($row['custom_link_icon']);
|
||||||
);
|
$custom_link_new_tab = intval($row['custom_link_new_tab']);
|
||||||
|
if ($custom_link_new_tab == 1) {
|
||||||
|
$target = "target='_blank' rel='noopener noreferrer'";
|
||||||
|
} else {
|
||||||
|
$target = "";
|
||||||
|
}
|
||||||
|
|
||||||
while ($row = mysqli_fetch_array($sql_custom_links)) {
|
?>
|
||||||
$custom_link_name = nullable_htmlentities($row['custom_link_name']);
|
|
||||||
$custom_link_uri = nullable_htmlentities($row['custom_link_uri']);
|
|
||||||
$custom_link_icon = nullable_htmlentities($row['custom_link_icon']);
|
|
||||||
$custom_link_new_tab = intval($row['custom_link_new_tab']);
|
|
||||||
if ($custom_link_new_tab == 1) {
|
|
||||||
$target = "target='_blank' rel='noopener noreferrer'";
|
|
||||||
} else {
|
|
||||||
$target = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
<li class="nav-item" title="<?php echo $custom_link_name; ?>">
|
||||||
|
<a href="<?php echo $custom_link_uri; ?>" <?php echo $target; ?> class="nav-link">
|
||||||
|
<i class="fas fa-<?php echo $custom_link_icon; ?> nav-icon"></i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="nav-item" title="<?php echo $custom_link_name; ?>">
|
<?php } ?>
|
||||||
<a href="<?php echo $custom_link_uri; ?>" <?php echo $target; ?> class="nav-link">
|
<!-- End Custom Nav Links -->
|
||||||
<i class="fas fa-<?php echo $custom_link_icon; ?> nav-icon"></i>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<?php } ?>
|
|
||||||
<!-- End Custom Nav Links -->
|
|
||||||
|
|
||||||
<?php } // End DB Check ?>
|
|
||||||
|
|
||||||
<!-- New Notifications Dropdown -->
|
<!-- New Notifications Dropdown -->
|
||||||
<?php
|
<?php
|
||||||
|
|||||||
@@ -6,28 +6,24 @@
|
|||||||
|
|
||||||
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
|
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
|
||||||
|
|
||||||
if (isset($_GET['download_database'])) {
|
require_once "includes/app_version.php";
|
||||||
validateCSRFToken($_GET['csrf_token']);
|
|
||||||
|
|
||||||
|
if (isset($_GET['download_backup'])) {
|
||||||
|
validateCSRFToken($_GET['csrf_token']);
|
||||||
global $mysqli, $database;
|
global $mysqli, $database;
|
||||||
|
|
||||||
$backupFileName = date('Y-m-d_H-i-s') . '_backup.sql';
|
$timestamp = date('YmdHis');
|
||||||
|
$baseName = "itflow_$timestamp";
|
||||||
|
$sqlFile = "$baseName.sql";
|
||||||
|
$uploadsZip = "$baseName_uploads.zip";
|
||||||
|
$finalZip = "$baseName.zip";
|
||||||
|
$versionFile = "version.txt";
|
||||||
|
|
||||||
header('Content-Type: application/sql');
|
// === 1. Generate SQL Dump ===
|
||||||
header('Content-Disposition: attachment; filename="' . $backupFileName . '"');
|
$sqlContent = "-- UTF-8 + Foreign Key Safe Dump\n";
|
||||||
header('Cache-Control: no-store, no-cache, must-revalidate');
|
$sqlContent .= "SET NAMES 'utf8mb4';\n";
|
||||||
header('Pragma: no-cache');
|
$sqlContent .= "SET foreign_key_checks = 0;\n\n";
|
||||||
header('Expires: 0');
|
|
||||||
|
|
||||||
if (ob_get_level()) ob_end_clean();
|
|
||||||
flush();
|
|
||||||
|
|
||||||
// Start of dump file — charset declaration
|
|
||||||
echo "-- UTF-8 + Foreign Key Safe Dump\n";
|
|
||||||
echo "SET NAMES 'utf8mb4';\n";
|
|
||||||
echo "SET foreign_key_checks = 0;\n\n";
|
|
||||||
|
|
||||||
// Get all tables
|
|
||||||
$tables = [];
|
$tables = [];
|
||||||
$res = $mysqli->query("SHOW TABLES");
|
$res = $mysqli->query("SHOW TABLES");
|
||||||
while ($row = $res->fetch_row()) {
|
while ($row = $res->fetch_row()) {
|
||||||
@@ -35,39 +31,102 @@ if (isset($_GET['download_database'])) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach ($tables as $table) {
|
foreach ($tables as $table) {
|
||||||
// Table structure
|
|
||||||
$createRes = $mysqli->query("SHOW CREATE TABLE `$table`");
|
$createRes = $mysqli->query("SHOW CREATE TABLE `$table`");
|
||||||
$createRow = $createRes->fetch_assoc();
|
$createRow = $createRes->fetch_assoc();
|
||||||
$createSQL = array_values($createRow)[1];
|
$createSQL = array_values($createRow)[1];
|
||||||
|
|
||||||
echo "\n-- ----------------------------\n";
|
$sqlContent .= "\n-- ----------------------------\n";
|
||||||
echo "-- Table structure for `$table`\n";
|
$sqlContent .= "-- Table structure for `$table`\n";
|
||||||
echo "-- ----------------------------\n";
|
$sqlContent .= "-- ----------------------------\n";
|
||||||
echo "DROP TABLE IF EXISTS `$table`;\n";
|
$sqlContent .= "DROP TABLE IF EXISTS `$table`;\n";
|
||||||
echo $createSQL . ";\n\n";
|
$sqlContent .= $createSQL . ";\n\n";
|
||||||
|
|
||||||
// Table data
|
|
||||||
$dataRes = $mysqli->query("SELECT * FROM `$table`");
|
$dataRes = $mysqli->query("SELECT * FROM `$table`");
|
||||||
if ($dataRes->num_rows > 0) {
|
if ($dataRes->num_rows > 0) {
|
||||||
echo "-- Dumping data for table `$table`\n";
|
$sqlContent .= "-- Dumping data for table `$table`\n";
|
||||||
while ($row = $dataRes->fetch_assoc()) {
|
while ($row = $dataRes->fetch_assoc()) {
|
||||||
$columns = array_map(fn($col) => '`' . $mysqli->real_escape_string($col) . '`', array_keys($row));
|
$columns = array_map(fn($col) => '`' . $mysqli->real_escape_string($col) . '`', array_keys($row));
|
||||||
$values = array_map(function ($val) use ($mysqli) {
|
$values = array_map(function ($val) use ($mysqli) {
|
||||||
if (is_null($val)) return "NULL";
|
return is_null($val) ? "NULL" : "'" . $mysqli->real_escape_string($val) . "'";
|
||||||
return "'" . $mysqli->real_escape_string($val) . "'";
|
|
||||||
}, array_values($row));
|
}, array_values($row));
|
||||||
|
$sqlContent .= "INSERT INTO `$table` (" . implode(", ", $columns) . ") VALUES (" . implode(", ", $values) . ");\n";
|
||||||
echo "INSERT INTO `$table` (" . implode(", ", $columns) . ") VALUES (" . implode(", ", $values) . ");\n";
|
|
||||||
}
|
}
|
||||||
echo "\n";
|
$sqlContent .= "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//FINAL STEP: Re-enable foreign key checks
|
$sqlContent .= "SET foreign_key_checks = 1;\n";
|
||||||
echo "\nSET foreign_key_checks = 1;\n";
|
file_put_contents($sqlFile, $sqlContent);
|
||||||
|
|
||||||
logAction("Database", "Download", "$session_name downloaded the database.");
|
// === 2. Create uploads.zip ===
|
||||||
$_SESSION['alert_message'] = "Database downloaded";
|
function zipFolder($folderPath, $zipFilePath) {
|
||||||
|
$zip = new ZipArchive();
|
||||||
|
if ($zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
|
||||||
|
die("Cannot open <$zipFilePath>");
|
||||||
|
}
|
||||||
|
|
||||||
|
$folderPath = realpath($folderPath);
|
||||||
|
$files = new RecursiveIteratorIterator(
|
||||||
|
new RecursiveDirectoryIterator($folderPath),
|
||||||
|
RecursiveIteratorIterator::LEAVES_ONLY
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
if (!$file->isDir()) {
|
||||||
|
$filePath = $file->getRealPath();
|
||||||
|
$relativePath = substr($filePath, strlen($folderPath) + 1);
|
||||||
|
$zip->addFile($filePath, $relativePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$zip->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
zipFolder("uploads", $uploadsZip);
|
||||||
|
|
||||||
|
// === 3. Generate version.txt ===
|
||||||
|
$commitHash = trim(shell_exec('git log -1 --format=%H'));
|
||||||
|
$gitBranch = trim(shell_exec('git rev-parse --abbrev-ref HEAD'));
|
||||||
|
|
||||||
|
$versionContent = "ITFlow Backup Metadata\n";
|
||||||
|
$versionContent .= "-----------------------------\n";
|
||||||
|
$versionContent .= "Generated: " . date('Y-m-d H:i:s') . "\n";
|
||||||
|
$versionContent .= "Backup File: $baseName.zip\n";
|
||||||
|
$versionContent .= "Generated By: $session_name\n";
|
||||||
|
$versionContent .= "Host: " . gethostname() . "\n";
|
||||||
|
$versionContent .= "Git Branch: $gitBranch\n";
|
||||||
|
$versionContent .= "Git Commit: $commitHash\n";
|
||||||
|
$versionContent .= "ITFlow Version: " . (defined('APP_VERSION') ? APP_VERSION : 'Unknown') . "\n";
|
||||||
|
$versionContent .= "Database Version: " . (defined('CURRENT_DATABASE_VERSION') ? CURRENT_DATABASE_VERSION : 'Unknown') . "\n";
|
||||||
|
|
||||||
|
file_put_contents($versionFile, $versionContent);
|
||||||
|
|
||||||
|
// === 4. Combine into final .zip file ===
|
||||||
|
$final = new ZipArchive();
|
||||||
|
if ($final->open($finalZip, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
|
||||||
|
die("Cannot create final backup zip.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$final->addFile($sqlFile, "db.sql");
|
||||||
|
$final->addFile($uploadsZip, "uploads.zip");
|
||||||
|
$final->addFile($versionFile, "version.txt");
|
||||||
|
$final->close();
|
||||||
|
|
||||||
|
// Cleanup temp files before download
|
||||||
|
unlink($sqlFile);
|
||||||
|
unlink($uploadsZip);
|
||||||
|
unlink($versionFile);
|
||||||
|
|
||||||
|
// === 5. Serve the zip for download ===
|
||||||
|
header('Content-Type: application/zip');
|
||||||
|
header('Content-Disposition: attachment; filename="' . $finalZip . '"');
|
||||||
|
header('Content-Length: ' . filesize($finalZip));
|
||||||
|
flush();
|
||||||
|
readfile($finalZip);
|
||||||
|
unlink($finalZip); // remove final zip after serving
|
||||||
|
|
||||||
|
logAction("System", "Backup Download", "$session_name downloaded full backup.");
|
||||||
|
$_SESSION['alert_message'] = "Full backup downloaded.";
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,3 +163,4 @@ if (isset($_POST['backup_master_key'])) {
|
|||||||
header("Location: " . $_SERVER["HTTP_REFERER"]);
|
header("Location: " . $_SERVER["HTTP_REFERER"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
154
setup.php
154
setup.php
@@ -6,7 +6,6 @@ if (file_exists("config.php")) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
include "functions.php";
|
include "functions.php";
|
||||||
|
|
||||||
include "includes/database_version.php";
|
include "includes/database_version.php";
|
||||||
|
|
||||||
|
|
||||||
@@ -109,6 +108,118 @@ if (isset($_POST['add_database'])) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($_POST['restore'])) {
|
||||||
|
|
||||||
|
if (!isset($_FILES['backup_zip']) || $_FILES['backup_zip']['error'] !== UPLOAD_ERR_OK) {
|
||||||
|
die("No backup file uploaded or upload failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $_FILES['backup_zip'];
|
||||||
|
$fileExt = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
|
||||||
|
if ($fileExt !== "zip") {
|
||||||
|
die("Only .zip files are allowed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save uploaded file temporarily
|
||||||
|
$backupZip = "restore_" . time() . ".zip";
|
||||||
|
if (!move_uploaded_file($file["tmp_name"], $backupZip)) {
|
||||||
|
die("Failed to save uploaded backup file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$zip = new ZipArchive;
|
||||||
|
if ($zip->open($backupZip) !== TRUE) {
|
||||||
|
unlink($backupZip);
|
||||||
|
die("Failed to open backup zip file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract to a temp directory
|
||||||
|
$tempDir = "restore_temp_" . time();
|
||||||
|
mkdir($tempDir);
|
||||||
|
|
||||||
|
if (!$zip->extractTo($tempDir)) {
|
||||||
|
$zip->close();
|
||||||
|
unlink($backupZip);
|
||||||
|
die("Failed to extract backup contents.");
|
||||||
|
}
|
||||||
|
$zip->close();
|
||||||
|
unlink($backupZip);
|
||||||
|
|
||||||
|
// === 1. Restore SQL Dump ===
|
||||||
|
$sqlPath = "$tempDir/db.sql";
|
||||||
|
if (file_exists($sqlPath)) {
|
||||||
|
mysqli_query($mysqli, "SET foreign_key_checks = 0");
|
||||||
|
$tables = mysqli_query($mysqli, "SHOW TABLES");
|
||||||
|
while ($row = mysqli_fetch_array($tables)) {
|
||||||
|
mysqli_query($mysqli, "DROP TABLE IF EXISTS `" . $row[0] . "`");
|
||||||
|
}
|
||||||
|
mysqli_query($mysqli, "SET foreign_key_checks = 1");
|
||||||
|
|
||||||
|
$command = sprintf(
|
||||||
|
'mysql -h%s -u%s -p%s %s < %s',
|
||||||
|
escapeshellarg($dbhost),
|
||||||
|
escapeshellarg($dbusername),
|
||||||
|
escapeshellarg($dbpassword),
|
||||||
|
escapeshellarg($database),
|
||||||
|
escapeshellarg($sqlPath)
|
||||||
|
);
|
||||||
|
|
||||||
|
exec($command, $output, $returnCode);
|
||||||
|
if ($returnCode !== 0) {
|
||||||
|
die("SQL import failed. Error code: $returnCode");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
die("Missing db.sql in the backup archive.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// === 2. Restore Upload Folder ===
|
||||||
|
$uploadDir = __DIR__ . "/uploads/";
|
||||||
|
$uploadsZip = "$tempDir/uploads.zip";
|
||||||
|
|
||||||
|
if (file_exists($uploadsZip)) {
|
||||||
|
$uploads = new ZipArchive;
|
||||||
|
if ($uploads->open($uploadsZip) === TRUE) {
|
||||||
|
// Clean existing uploads
|
||||||
|
foreach (glob($uploadDir . '*') as $item) {
|
||||||
|
if (is_dir($item)) {
|
||||||
|
array_map('unlink', glob("$item/*"));
|
||||||
|
rmdir($item);
|
||||||
|
} else {
|
||||||
|
unlink($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$uploads->extractTo($uploadDir);
|
||||||
|
$uploads->close();
|
||||||
|
} else {
|
||||||
|
die("Failed to open uploads.zip in backup.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
die("Missing uploads.zip in the backup archive.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// === 3. Read version.txt (optional log/display)
|
||||||
|
$versionTxt = "$tempDir/version.txt";
|
||||||
|
if (file_exists($versionTxt)) {
|
||||||
|
$versionInfo = file_get_contents($versionTxt);
|
||||||
|
// You could log it, show it, or ignore it
|
||||||
|
// e.g. logAction("Backup Restore", "Version Info", $versionInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup temp restore directory
|
||||||
|
array_map('unlink', glob("$tempDir/*"));
|
||||||
|
rmdir($tempDir);
|
||||||
|
|
||||||
|
// === 4. Final Setup Stages ===
|
||||||
|
$myfile = fopen("config.php", "a");
|
||||||
|
$txt = "\$config_enable_setup = 0;\n\n";
|
||||||
|
fwrite($myfile, $txt);
|
||||||
|
fclose($myfile);
|
||||||
|
|
||||||
|
$_SESSION['alert_message'] = "Full backup restored successfully.";
|
||||||
|
// header("Location: login.php");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($_POST['add_user'])) {
|
if (isset($_POST['add_user'])) {
|
||||||
$user_count = mysqli_num_rows(mysqli_query($mysqli,"SELECT COUNT(*) FROM users"));
|
$user_count = mysqli_num_rows(mysqli_query($mysqli,"SELECT COUNT(*) FROM users"));
|
||||||
if ($user_count < 0) {
|
if ($user_count < 0) {
|
||||||
@@ -146,7 +257,7 @@ if (isset($_POST['add_user'])) {
|
|||||||
$new_file_name = md5(time() . $file_name) . '.' . $file_extension;
|
$new_file_name = md5(time() . $file_name) . '.' . $file_extension;
|
||||||
|
|
||||||
// check if file has one of the following extensions
|
// check if file has one of the following extensions
|
||||||
$allowed_file_extensions = array('jpg', 'gif', 'png');
|
$allowed_file_extensions = array('jpg', 'jpeg', 'gif', 'png', 'webp');
|
||||||
|
|
||||||
if (in_array($file_extension,$allowed_file_extensions) === false) {
|
if (in_array($file_extension,$allowed_file_extensions) === false) {
|
||||||
$file_error = 1;
|
$file_error = 1;
|
||||||
@@ -195,9 +306,6 @@ if (isset($_POST['add_company_settings'])) {
|
|||||||
$phone = preg_replace("/[^0-9]/", '',$_POST['phone']);
|
$phone = preg_replace("/[^0-9]/", '',$_POST['phone']);
|
||||||
$email = sanitizeInput($_POST['email']);
|
$email = sanitizeInput($_POST['email']);
|
||||||
$website = sanitizeInput($_POST['website']);
|
$website = sanitizeInput($_POST['website']);
|
||||||
$locale = sanitizeInput($_POST['locale']);
|
|
||||||
$currency_code = sanitizeInput($_POST['currency_code']);
|
|
||||||
$timezone = sanitizeInput($_POST['timezone']);
|
|
||||||
|
|
||||||
mysqli_query($mysqli,"INSERT INTO companies SET company_name = '$name', company_address = '$address', company_city = '$city', company_state = '$state', company_zip = '$zip', company_country = '$country', company_phone = '$phone', company_email = '$email', company_website = '$website', company_locale = '$locale', company_currency = '$currency_code'");
|
mysqli_query($mysqli,"INSERT INTO companies SET company_name = '$name', company_address = '$address', company_city = '$city', company_state = '$state', company_zip = '$zip', company_country = '$country', company_phone = '$phone', company_email = '$email', company_website = '$website', company_locale = '$locale', company_currency = '$currency_code'");
|
||||||
|
|
||||||
@@ -287,7 +395,6 @@ if (isset($_POST['add_company_settings'])) {
|
|||||||
mysqli_query($mysqli,"INSERT INTO categories SET category_name = 'Event', category_type = 'Referral', category_color = 'red'");
|
mysqli_query($mysqli,"INSERT INTO categories SET category_name = 'Event', category_type = 'Referral', category_color = 'red'");
|
||||||
mysqli_query($mysqli,"INSERT INTO categories SET category_name = 'Affiliate', category_type = 'Referral', category_color = 'pink'");
|
mysqli_query($mysqli,"INSERT INTO categories SET category_name = 'Affiliate', category_type = 'Referral', category_color = 'pink'");
|
||||||
mysqli_query($mysqli,"INSERT INTO categories SET category_name = 'Client', category_type = 'Referral', category_color = 'lightblue'");
|
mysqli_query($mysqli,"INSERT INTO categories SET category_name = 'Client', category_type = 'Referral', category_color = 'lightblue'");
|
||||||
mysqli_query($mysqli,"INSERT INTO categories SET category_name = 'Influencer', category_type = 'Referral', category_color = 'turquoise'");
|
|
||||||
|
|
||||||
// Payment Methods
|
// Payment Methods
|
||||||
mysqli_query($mysqli,"INSERT INTO categories SET category_name = 'Cash', category_type = 'Payment Method', category_color = 'blue'");
|
mysqli_query($mysqli,"INSERT INTO categories SET category_name = 'Cash', category_type = 'Payment Method', category_color = 'blue'");
|
||||||
@@ -855,10 +962,19 @@ if (isset($_POST['add_telemetry'])) {
|
|||||||
<h3 class="card-title"><i class="fas fa-fw fa-database mr-2"></i>Step 2 - Connect your Database</h3>
|
<h3 class="card-title"><i class="fas fa-fw fa-database mr-2"></i>Step 2 - Connect your Database</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<?php if (file_exists('config.php')) { ?>
|
<?php
|
||||||
Database is already configured. Any further changes should be made by editing the config.php file,
|
if (file_exists('config.php')) {
|
||||||
or deleting it and refreshing this page.
|
|
||||||
<?php } else { ?>
|
echo "<p>Database is already configured. Any further changes should be made by editing the <code>config.php</code> file.</p>";
|
||||||
|
|
||||||
|
if (@$mysqli) {
|
||||||
|
echo "<a href='?user' class='btn btn-success text-bold mt-3'>Next Step (User Setup) <i class='fa fa-fw fa-arrow-circle-right ml-2'></i></a>";
|
||||||
|
} else {
|
||||||
|
echo "<div class='alert alert-danger mt-3'>Database connection failed. Check <code>config.php</code>.</div>";
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
?>
|
||||||
<form method="post" autocomplete="off">
|
<form method="post" autocomplete="off">
|
||||||
|
|
||||||
<h5>Database Connection Details</h5>
|
<h5>Database Connection Details</h5>
|
||||||
@@ -918,6 +1034,24 @@ if (isset($_POST['add_telemetry'])) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<?php } elseif (isset($_GET['restore'])) { ?>
|
||||||
|
|
||||||
|
<div class="card card-dark">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title"><i class="fas fa-fw fa-database mr-2"></i>Step 2.5 - Restore from Backup</h3>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form method="post" enctype="multipart/form-data">
|
||||||
|
<label>Restore ITFlow Backup (.zip)</label>
|
||||||
|
<input type="file" name="backup_zip" accept=".zip" required>
|
||||||
|
<hr>
|
||||||
|
<button type="submit" name="restore" class="btn btn-primary text-bold">
|
||||||
|
Restore Backup<i class="fas fa-fw fa-upload ml-2"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<?php } elseif (isset($_GET['user'])) { ?>
|
<?php } elseif (isset($_GET['user'])) { ?>
|
||||||
|
|
||||||
<div class="card card-dark">
|
<div class="card card-dark">
|
||||||
|
|||||||
Reference in New Issue
Block a user