Compare commits

..

No commits in common. "6363a6b33264494eb1ee30adf9b7da49ecb12479" and "76ba0213c60022dac666e57ed16a36d25221eb1e" have entirely different histories.

15 changed files with 31 additions and 91 deletions

1
.gitignore vendored
View File

@ -17,7 +17,6 @@ temp_restore_*/
# Logs
error_log
access_log
*.log
# Debug and utility scripts
debug_db.php

View File

@ -1,20 +0,0 @@
# Disable Directory Listing
Options -Indexes
# Protect sensitive files
<FilesMatch "^\.">
Order allow,deny
Deny from all
</FilesMatch>
# Protect config files
<FilesMatch "(db|config)\.php">
Order allow,deny
Deny from all
</FilesMatch>
# Protect SQL files
<FilesMatch "\.sql$">
Order allow,deny
Deny from all
</FilesMatch>

View File

@ -83,3 +83,8 @@ Feel free to fork this project and submit pull requests to the [Linology Git](ht
## 📄 License
This project is licensed under the MIT License.
=======
# Podcast-server
A lightweight, professional-grade podcast hosting and management platform designed for churches and small organizations. Built with PHP 8 and MySQL, this system provides a seamless way to host audio content, track analytics, and engage listeners via push notifications.

View File

@ -2,6 +2,11 @@
require_once '../includes/db.php';
require_once '../includes/functions.php';
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
ini_set('log_errors', 1);
ini_set('error_log', 'backup_debug.log');
set_time_limit(300); // 5 minutes
ini_set('memory_limit', '512M');

View File

@ -1 +0,0 @@
<?php header('Location: ../../index.php'); exit;

View File

@ -11,9 +11,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
updateSetting($pdo, 'site_title', $_POST['site_title']);
updateSetting($pdo, 'footer_copyright', $_POST['footer_copyright']);
updateSetting($pdo, 'footer_powered_by', $_POST['footer_powered_by']);
updateSetting($pdo, 'theme_primary_color', $_POST['theme_primary_color']);
updateSetting($pdo, 'theme_bg_color', $_POST['theme_bg_color']);
updateSetting($pdo, 'theme_text_color', $_POST['theme_text_color']);
$success = "Site settings updated!";
}
@ -70,25 +67,9 @@ $site_title = getSetting($pdo, 'site_title');
<input type="text" id="footer_copyright" name="footer_copyright" value="<?php echo htmlspecialchars(getSetting($pdo, 'footer_copyright')); ?>" required>
</div>
<div class="form-group">
<label for="footer_powered_by">Other</label>
<label for="footer_powered_by">"Powered By" Text</label>
<input type="text" id="footer_powered_by" name="footer_powered_by" value="<?php echo htmlspecialchars(getSetting($pdo, 'footer_powered_by')); ?>" required>
</div>
<h3 style="margin: 2rem 0 1rem; border-bottom: 1px solid var(--glass-border); padding-bottom: 0.5rem;">Theme Colors</h3>
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 1rem; margin-bottom: 1.5rem;">
<div class="form-group">
<label for="theme_primary_color">Primary Color</label>
<input type="color" id="theme_primary_color" name="theme_primary_color" value="<?php echo htmlspecialchars(getSetting($pdo, 'theme_primary_color') ?: '#6366f1'); ?>" style="height: 45px; cursor: pointer;">
</div>
<div class="form-group">
<label for="theme_bg_color">Background Color</label>
<input type="color" id="theme_bg_color" name="theme_bg_color" value="<?php echo htmlspecialchars(getSetting($pdo, 'theme_bg_color') ?: '#0f172a'); ?>" style="height: 45px; cursor: pointer;">
</div>
<div class="form-group">
<label for="theme_text_color">Text Color</label>
<input type="color" id="theme_text_color" name="theme_text_color" value="<?php echo htmlspecialchars(getSetting($pdo, 'theme_text_color') ?: '#f8fafc'); ?>" style="height: 45px; cursor: pointer;">
</div>
</div>
<button type="submit" name="update_site" class="btn btn-primary" style="width: 100%;">Update Settings</button>
</form>

View File

@ -127,7 +127,7 @@ nav {
.hero {
height: 400px;
background-size: cover;
background-position: top center; /* Anchored to top to prevent cutting off */
background-position: center 20%; /* Adjusted to show more of the top/center */
display: flex;
align-items: center;
justify-content: center;
@ -136,7 +136,6 @@ nav {
border-radius: 0 0 40px 40px;
margin-bottom: 3rem;
background-repeat: no-repeat;
overflow: hidden; /* Prevent image bleeding */
}
.hero::after {
@ -146,7 +145,7 @@ nav {
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to bottom, rgba(15, 23, 42, 0.05), rgba(15, 23, 42, 0.3));
background: linear-gradient(to bottom, rgba(15, 23, 42, 0.4), var(--bg-dark));
}
.hero-content {
@ -266,12 +265,6 @@ input:focus, textarea:focus {
.hero h1 {
font-size: 2.5rem;
}
.hero {
height: auto;
min-height: 180px;
padding: 2.5rem 1.5rem;
border-radius: 0 0 24px 24px;
}
.nav-links {
display: none;
}

View File

@ -1,5 +1,5 @@
<footer style="text-align: center; padding: 3rem; color: var(--text-muted); border-top: 1px solid var(--glass-border); margin-top: 3rem;">
<p>&copy; <?php echo date('Y'); ?> <?php echo parseFooterText(getSetting($pdo, 'footer_copyright')); ?>. <?php echo parseFooterText(getSetting($pdo, 'footer_powered_by')); ?></p>
<p>&copy; <?php echo date('Y'); ?> <?php echo htmlspecialchars(getSetting($pdo, 'footer_copyright')); ?>. Powered by <?php echo htmlspecialchars(getSetting($pdo, 'footer_powered_by')); ?>.</p>
</footer>
<script src="<?php echo PROJECT_ROOT_URL; ?>/assets/js/main.js"></script>
</body>

View File

@ -43,14 +43,7 @@ function requireRole($role) {
function logActivity($user_id, $action, $details = null) {
global $pdo;
$username = $_SESSION['admin_username'] ?? 'GUEST';
$ip = 'UNKNOWN';
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0];
} elseif (!empty($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
}
$ip = $_SERVER['REMOTE_ADDR'] ?? 'UNKNOWN';
$stmt = $pdo->prepare("INSERT INTO activity_log (user_id, username, action, details, ip_address) VALUES (?, ?, ?, ?, ?)");
$stmt->execute([$user_id, $username, $action, $details, $ip]);
@ -128,15 +121,4 @@ function uploadImage($file) {
function formatDate($date) {
return date("F j, Y", strtotime($date));
}
/**
* Parse text for URLs and convert to clickable links
*/
function parseFooterText($text) {
$escaped = htmlspecialchars($text);
// Regex for URLs
$pattern = '/(https?:\/\/[^\s]+)/';
$replacement = '<a href="$1" target="_blank" style="color: var(--primary-color); text-decoration: none; font-weight: 600;">$1</a>';
return preg_replace($pattern, $replacement, $escaped);
}
?>

View File

@ -12,25 +12,13 @@ $banner_image = getSetting($pdo, 'banner_image');
<title><?php echo htmlspecialchars($site_title); ?></title>
<link rel="stylesheet" href="<?php echo PROJECT_ROOT_URL; ?>/assets/css/style.css">
<link rel="icon" type="image/png" href="<?php echo PROJECT_ROOT_URL; ?>/assets/uploads/images/icon.png">
<style>
:root {
<?php
$pColor = getSetting($pdo, 'theme_primary_color') ?: '#6366f1';
$bgColor = getSetting($pdo, 'theme_bg_color') ?: '#0f172a';
$tColor = getSetting($pdo, 'theme_text_color') ?: '#f8fafc';
?>
--primary-color: <?php echo $pColor; ?>;
--bg-dark: <?php echo $bgColor; ?>;
--text-main: <?php echo $tColor; ?>;
--primary-hover: <?php echo $pColor; ?>dd; /* Slightly lighter/transparent for hover */
}
</style>
</head>
<body>
<nav>
<a href="<?php echo PROJECT_ROOT_URL; ?>/" class="logo"><?php echo htmlspecialchars($site_title); ?></a>
<div class="nav-links">
<a href="<?php echo PROJECT_ROOT_URL; ?>/">Home</a>
<a href="<?php echo PROJECT_ROOT_URL; ?>/subscribe.php">How to Subscribe</a>
<button id="notify-btn" class="notify-btn">🔔 Notify Me</button>
<?php if (isAdmin()): ?>
<a href="<?php echo PROJECT_ROOT_URL; ?>/admin/dashboard.php">Dashboard</a>

View File

@ -1 +0,0 @@
<?php header('Location: ../index.php'); exit;

View File

@ -26,11 +26,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
logActivity(null, 'LISTENER_STARTED', "Episode: $title (Session: $session_id)");
}
file_put_contents('debug.log', date('[Y-m-d H:i:s] ') . "SUCCESS: Logged play for episode $episode_id ($duration s, session: $session_id)" . PHP_EOL, FILE_APPEND);
echo json_encode(['status' => 'success']);
} catch (PDOException $e) {
file_put_contents('debug.log', date('[Y-m-d H:i:s] ') . "DB ERROR: " . $e->getMessage() . PHP_EOL, FILE_APPEND);
echo json_encode(['status' => 'error', 'message' => 'Database error']);
}
} else {
file_put_contents('debug.log', date('[Y-m-d H:i:s] ') . "INVALID DATA: ID=$episode_id, DUR=$duration" . PHP_EOL, FILE_APPEND);
echo json_encode(['status' => 'error', 'message' => 'Invalid episode ID']);
}
}

View File

@ -18,7 +18,17 @@ if ($banner_image === 'default-banner.jpg') {
?>
<div class="hero" style="background-image: url('<?php echo $banner_url; ?>');">
<div class="hero-content">
<h1><?php echo htmlspecialchars($site_title); ?></h1>
<p>Listen to our latest messages and sermons.</p>
<div style="margin-top: 2rem; display: flex; gap: 1rem; justify-content: center;">
<a href="subscribe.php" class="btn btn-primary">How to Subscribe</a>
<a href="feed.php" class="btn" style="background: rgba(255,255,255,0.1); backdrop-filter: blur(10px); border: 1px solid var(--glass-border);">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align: middle; margin-right: 0.5rem;"><path d="M4 11a9 9 0 0 1 9 9"></path><path d="M4 4a16 16 0 0 1 16 16"></path><circle cx="5" cy="19" r="1"></circle></svg>
RSS Feed
</a>
</div>
</div>
</div>
<div class="container">

View File

@ -1 +0,0 @@
<?php header('Location: ../index.php'); exit;

View File

@ -44,10 +44,7 @@ INSERT IGNORE INTO settings (`key`, `value`) VALUES
('site_title', 'Our Church Podcast'),
('banner_image', 'default-banner.jpg'),
('footer_copyright', 'Our Church'),
('footer_powered_by', 'Antigravity Podcast Server'),
('theme_primary_color', '#6366f1'),
('theme_bg_color', '#0f172a'),
('theme_text_color', '#f8fafc');
('footer_powered_by', 'Antigravity Podcast Server');
-- Subscriptions table (Push Notifications)
CREATE TABLE IF NOT EXISTS subscriptions (