mirror of
https://github.com/danpros/htmly.git
synced 2026-04-17 19:26:08 +05:30
Merge pull request #1020 from Emidio/master
Comment system update and minor fixes related to htmly PHP 8 compatibility, theme labels
This commit is contained in:
commit
9e52fc80ad
7 changed files with 500 additions and 155 deletions
|
|
@ -2025,6 +2025,13 @@ function delete_comments($mdfile) {
|
||||||
// regardless if file is content .md file or comments .json file
|
// regardless if file is content .md file or comments .json file
|
||||||
function get_url_from_file($file)
|
function get_url_from_file($file)
|
||||||
{
|
{
|
||||||
|
// Ensure config is loaded - if not loads it
|
||||||
|
$config_loaded = config('permalink.type');
|
||||||
|
if (!$config_loaded) {
|
||||||
|
if (file_exists('config/config.ini')) {
|
||||||
|
config('source', 'config/config.ini');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Normalize path separators (Windows/Linux))
|
// Normalize path separators (Windows/Linux))
|
||||||
$file = str_replace('\\', '/', $file);
|
$file = str_replace('\\', '/', $file);
|
||||||
|
|
@ -2096,9 +2103,6 @@ function get_url_from_file($file)
|
||||||
// return site_url() . $slug;
|
// return site_url() . $slug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Check if it's a blog post: {username}/blog/{category}/{type}/[scheduled/]{date}_{tags}_{slug}.md
|
// Check if it's a blog post: {username}/blog/{category}/{type}/[scheduled/]{date}_{tags}_{slug}.md
|
||||||
if (count($parts) >= 5 && $parts[1] == 'blog') {
|
if (count($parts) >= 5 && $parts[1] == 'blog') {
|
||||||
$filename_parts = explode('_', pathinfo($basename, PATHINFO_FILENAME));
|
$filename_parts = explode('_', pathinfo($basename, PATHINFO_FILENAME));
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,8 @@
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="<?php echo site_url() . get_url_from_file($comment['file']); ?>" target="_blank">
|
<a href="<?php echo site_url() . $comment['url']; ?>" target="_blank">
|
||||||
<?php echo _h(get_url_from_file($comment['file'])); ?>
|
<?php echo _h($comment['url']); ?>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
@ -162,6 +162,13 @@
|
||||||
<label class="form-check-label"><?php echo i18n('Enable_honeypot');?></label>
|
<label class="form-check-label"><?php echo i18n('Enable_honeypot');?></label>
|
||||||
</div>
|
</div>
|
||||||
<small class="form-text text-muted"><?php echo i18n('Honeypot_desc');?></small>
|
<small class="form-text text-muted"><?php echo i18n('Honeypot_desc');?></small>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input type="checkbox" class="form-check-input" name="comments.jstime" value="true"
|
||||||
|
<?php echo comments_config('comments.jstime') === 'true' ? 'checked' : ''; ?>>
|
||||||
|
<label class="form-check-label"><?php echo i18n('Enable_jstime');?></label>
|
||||||
|
</div>
|
||||||
|
<small class="form-text text-muted"><?php echo i18n('Jstime_desc');?></small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
224
system/htmly.php
224
system/htmly.php
|
|
@ -498,7 +498,7 @@ get('/edit/password', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
post('/edit/password', function() {
|
post('/edit/password', function() {
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if (login() && $proper) {
|
if (login() && $proper) {
|
||||||
$username = from($_REQUEST, 'username');
|
$username = from($_REQUEST, 'username');
|
||||||
$new_password = from($_REQUEST, 'password');
|
$new_password = from($_REQUEST, 'password');
|
||||||
|
|
@ -545,7 +545,7 @@ get('/edit/mfa', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
post('/edit/mfa', function() {
|
post('/edit/mfa', function() {
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if (login() && $proper) {
|
if (login() && $proper) {
|
||||||
$username = from($_REQUEST, 'username');
|
$username = from($_REQUEST, 'username');
|
||||||
$mfa_secret = from($_REQUEST, 'mfa_secret');
|
$mfa_secret = from($_REQUEST, 'mfa_secret');
|
||||||
|
|
@ -613,8 +613,8 @@ post('/edit/mfa', function() {
|
||||||
// Edit the frontpage
|
// Edit the frontpage
|
||||||
get('/edit/frontpage', function () {
|
get('/edit/frontpage', function () {
|
||||||
|
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
|
|
||||||
if (login()) {
|
if (login()) {
|
||||||
|
|
||||||
|
|
@ -909,8 +909,8 @@ post('/add/content', function () {
|
||||||
// Show the static add page
|
// Show the static add page
|
||||||
get('/add/page', function () {
|
get('/add/page', function () {
|
||||||
|
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
|
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
|
|
@ -1152,8 +1152,8 @@ post('/admin/autosave', function () {
|
||||||
|
|
||||||
// Show the add category
|
// Show the add category
|
||||||
get('/add/category', function () {
|
get('/add/category', function () {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
|
|
@ -1242,8 +1242,8 @@ post('/add/category', function () {
|
||||||
// Show admin/posts
|
// Show admin/posts
|
||||||
get('/admin/posts', function () {
|
get('/admin/posts', function () {
|
||||||
|
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
|
|
@ -1306,8 +1306,8 @@ get('/admin/posts', function () {
|
||||||
// Show admin/popular
|
// Show admin/popular
|
||||||
get('/admin/popular', function () {
|
get('/admin/popular', function () {
|
||||||
|
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
|
|
@ -1609,8 +1609,8 @@ get('/admin/content', function () {
|
||||||
|
|
||||||
// Show admin/pages
|
// Show admin/pages
|
||||||
get('/admin/pages', function () {
|
get('/admin/pages', function () {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
|
|
@ -1660,8 +1660,8 @@ post('/admin/pages', function () {
|
||||||
// Show admin/pages
|
// Show admin/pages
|
||||||
get('/admin/pages/:static', function ($static)
|
get('/admin/pages/:static', function ($static)
|
||||||
{
|
{
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
|
|
@ -1734,8 +1734,8 @@ post('/admin/pages/:static', function ($static) {
|
||||||
|
|
||||||
// Show import page
|
// Show import page
|
||||||
get('/admin/import', function () {
|
get('/admin/import', function () {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'admin') {
|
if ($role === 'admin') {
|
||||||
|
|
@ -1834,8 +1834,8 @@ post('/admin/import', function () {
|
||||||
// Show admin/search
|
// Show admin/search
|
||||||
get('/admin/search', function () {
|
get('/admin/search', function () {
|
||||||
|
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if (login()) {
|
if (login()) {
|
||||||
if ($role === 'editor' || $role === 'admin' && config('fulltext.search') == "true") {
|
if ($role === 'editor' || $role === 'admin' && config('fulltext.search') == "true") {
|
||||||
|
|
@ -1957,8 +1957,8 @@ post('/admin/search/reindex', function () {
|
||||||
// Show Config page
|
// Show Config page
|
||||||
get('/admin/config', function () {
|
get('/admin/config', function () {
|
||||||
|
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
|
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
|
|
@ -1995,7 +1995,7 @@ get('/admin/config', function () {
|
||||||
// Submitted Config page data
|
// Submitted Config page data
|
||||||
post('/admin/config', function () {
|
post('/admin/config', function () {
|
||||||
|
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if (login() && $proper) {
|
if (login() && $proper) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'];
|
||||||
$role = user('role', $user);
|
$role = user('role', $user);
|
||||||
|
|
@ -2031,8 +2031,8 @@ post('/admin/config', function () {
|
||||||
// Show Config page
|
// Show Config page
|
||||||
get('/admin/config/custom', function () {
|
get('/admin/config/custom', function () {
|
||||||
|
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
|
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
|
|
@ -2068,7 +2068,7 @@ get('/admin/config/custom', function () {
|
||||||
// Submitted Config page data
|
// Submitted Config page data
|
||||||
post('/admin/config/custom', function () {
|
post('/admin/config/custom', function () {
|
||||||
|
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if (login() && $proper) {
|
if (login() && $proper) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'];
|
||||||
$role = user('role', $user);
|
$role = user('role', $user);
|
||||||
|
|
@ -2103,8 +2103,8 @@ post('/admin/config/custom', function () {
|
||||||
// Show Config page
|
// Show Config page
|
||||||
get('/admin/config/reading', function () {
|
get('/admin/config/reading', function () {
|
||||||
|
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
|
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
|
|
@ -2140,7 +2140,7 @@ get('/admin/config/reading', function () {
|
||||||
// Submitted Config page data
|
// Submitted Config page data
|
||||||
post('/admin/config/reading', function () {
|
post('/admin/config/reading', function () {
|
||||||
|
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if (login() && $proper) {
|
if (login() && $proper) {
|
||||||
$new_config = array();
|
$new_config = array();
|
||||||
$new_Keys = array();
|
$new_Keys = array();
|
||||||
|
|
@ -2173,8 +2173,8 @@ post('/admin/config/reading', function () {
|
||||||
// Show Config page
|
// Show Config page
|
||||||
get('/admin/config/writing', function () {
|
get('/admin/config/writing', function () {
|
||||||
|
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
|
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
|
|
@ -2210,7 +2210,7 @@ get('/admin/config/writing', function () {
|
||||||
// Submitted Config page data
|
// Submitted Config page data
|
||||||
post('/admin/config/writing', function () {
|
post('/admin/config/writing', function () {
|
||||||
|
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if (login() && $proper) {
|
if (login() && $proper) {
|
||||||
$new_config = array();
|
$new_config = array();
|
||||||
$new_Keys = array();
|
$new_Keys = array();
|
||||||
|
|
@ -2243,8 +2243,8 @@ post('/admin/config/writing', function () {
|
||||||
// Show Config page
|
// Show Config page
|
||||||
get('/admin/config/widget', function () {
|
get('/admin/config/widget', function () {
|
||||||
|
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
|
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
|
|
@ -2280,7 +2280,7 @@ get('/admin/config/widget', function () {
|
||||||
// Submitted Config page data
|
// Submitted Config page data
|
||||||
post('/admin/config/widget', function () {
|
post('/admin/config/widget', function () {
|
||||||
|
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if (login() && $proper) {
|
if (login() && $proper) {
|
||||||
$new_config = array();
|
$new_config = array();
|
||||||
$new_Keys = array();
|
$new_Keys = array();
|
||||||
|
|
@ -2316,8 +2316,8 @@ post('/admin/config/widget', function () {
|
||||||
// Show Config page
|
// Show Config page
|
||||||
get('/admin/config/metatags', function () {
|
get('/admin/config/metatags', function () {
|
||||||
|
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
|
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
|
|
@ -2354,7 +2354,7 @@ get('/admin/config/metatags', function () {
|
||||||
// Submitted Config page data
|
// Submitted Config page data
|
||||||
post('/admin/config/metatags', function () {
|
post('/admin/config/metatags', function () {
|
||||||
|
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if (login() && $proper) {
|
if (login() && $proper) {
|
||||||
$new_config = array();
|
$new_config = array();
|
||||||
$new_Keys = array();
|
$new_Keys = array();
|
||||||
|
|
@ -2390,8 +2390,8 @@ post('/admin/config/metatags', function () {
|
||||||
// Show Config page
|
// Show Config page
|
||||||
get('/admin/config/security', function () {
|
get('/admin/config/security', function () {
|
||||||
|
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
|
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
|
|
@ -2427,7 +2427,7 @@ get('/admin/config/security', function () {
|
||||||
// Submitted Config page data
|
// Submitted Config page data
|
||||||
post('/admin/config/security', function () {
|
post('/admin/config/security', function () {
|
||||||
|
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if (login() && $proper) {
|
if (login() && $proper) {
|
||||||
$new_config = array();
|
$new_config = array();
|
||||||
$new_Keys = array();
|
$new_Keys = array();
|
||||||
|
|
@ -2499,7 +2499,7 @@ get('/admin/config/performance', function () {
|
||||||
// Submitted Config page data
|
// Submitted Config page data
|
||||||
post('/admin/config/performance', function () {
|
post('/admin/config/performance', function () {
|
||||||
|
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if (login() && $proper) {
|
if (login() && $proper) {
|
||||||
$new_config = array();
|
$new_config = array();
|
||||||
$new_Keys = array();
|
$new_Keys = array();
|
||||||
|
|
@ -2531,8 +2531,8 @@ post('/admin/config/performance', function () {
|
||||||
|
|
||||||
// Show Backup page
|
// Show Backup page
|
||||||
get('/admin/backup', function () {
|
get('/admin/backup', function () {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'admin') {
|
if ($role === 'admin') {
|
||||||
|
|
@ -2593,8 +2593,8 @@ get('/admin/backup-start', function () {
|
||||||
|
|
||||||
// Show clear cache page
|
// Show clear cache page
|
||||||
get('/admin/clear-cache', function () {
|
get('/admin/clear-cache', function () {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
|
|
@ -2628,8 +2628,8 @@ get('/admin/clear-cache', function () {
|
||||||
|
|
||||||
// Show Update page
|
// Show Update page
|
||||||
get('/admin/update', function () {
|
get('/admin/update', function () {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'admin') {
|
if ($role === 'admin') {
|
||||||
|
|
@ -2663,11 +2663,11 @@ get('/admin/update', function () {
|
||||||
|
|
||||||
// Show the update now link
|
// Show the update now link
|
||||||
get('/admin/update/now/:csrf', function ($CSRF) {
|
get('/admin/update/now/:csrf', function ($CSRF) {
|
||||||
$proper = is_csrf_proper($CSRF);
|
$proper = is_csrf_proper($CSRF) ?? null;
|
||||||
$updater = new \Kanti\HubUpdater(array(
|
$updater = new \Kanti\HubUpdater(array(
|
||||||
'name' => 'danpros/htmly',
|
'name' => 'danpros/htmly',
|
||||||
'prerelease' => !!config("prerelease"),
|
'prerelease' => !!config("prerelease"),
|
||||||
));
|
)) ?? null;
|
||||||
if (login() && $proper && $updater->able()) {
|
if (login() && $proper && $updater->able()) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'];
|
||||||
$role = user('role', $user);
|
$role = user('role', $user);
|
||||||
|
|
@ -2697,8 +2697,8 @@ get('/admin/update/now/:csrf', function ($CSRF) {
|
||||||
|
|
||||||
// Show Menu builder
|
// Show Menu builder
|
||||||
get('/admin/menu', function () {
|
get('/admin/menu', function () {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
|
|
@ -2733,8 +2733,8 @@ get('/admin/menu', function () {
|
||||||
post('/admin/menu', function () {
|
post('/admin/menu', function () {
|
||||||
|
|
||||||
if (login()) {
|
if (login()) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
$json = from($_REQUEST, 'json');
|
$json = from($_REQUEST, 'json');
|
||||||
file_put_contents('content/data/menu.json', json_encode($json, JSON_UNESCAPED_UNICODE));
|
file_put_contents('content/data/menu.json', json_encode($json, JSON_UNESCAPED_UNICODE));
|
||||||
|
|
@ -2750,8 +2750,8 @@ post('/admin/menu', function () {
|
||||||
|
|
||||||
// Manage users page
|
// Manage users page
|
||||||
get('/admin/users', function () {
|
get('/admin/users', function () {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'admin') {
|
if ($role === 'admin') {
|
||||||
|
|
@ -2784,8 +2784,8 @@ get('/admin/users', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
get('/admin/add/user', function () {
|
get('/admin/add/user', function () {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'admin') {
|
if ($role === 'admin') {
|
||||||
|
|
@ -2818,9 +2818,9 @@ get('/admin/add/user', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
post('/admin/add/user', function () {
|
post('/admin/add/user', function () {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
$username = from($_REQUEST, 'username');
|
$username = from($_REQUEST, 'username');
|
||||||
$user_role = from($_REQUEST, 'user-role');
|
$user_role = from($_REQUEST, 'user-role');
|
||||||
$password = from($_REQUEST, 'password');
|
$password = from($_REQUEST, 'password');
|
||||||
|
|
@ -2868,8 +2868,8 @@ post('/admin/add/user', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
get('/admin/users/:username/edit', function ($username) {
|
get('/admin/users/:username/edit', function ($username) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'admin') {
|
if ($role === 'admin') {
|
||||||
|
|
@ -2905,7 +2905,7 @@ get('/admin/users/:username/edit', function ($username) {
|
||||||
// Submitted Config page data
|
// Submitted Config page data
|
||||||
post('/admin/users/:username/edit', function () {
|
post('/admin/users/:username/edit', function () {
|
||||||
|
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if (login() && $proper) {
|
if (login() && $proper) {
|
||||||
$username = from($_REQUEST, 'username');
|
$username = from($_REQUEST, 'username');
|
||||||
$user_role = from($_REQUEST, 'role-name');
|
$user_role = from($_REQUEST, 'role-name');
|
||||||
|
|
@ -2937,8 +2937,8 @@ post('/admin/users/:username/edit', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
get('/admin/users/:username/delete', function ($username) {
|
get('/admin/users/:username/delete', function ($username) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'admin') {
|
if ($role === 'admin') {
|
||||||
|
|
@ -2972,12 +2972,12 @@ get('/admin/users/:username/delete', function ($username) {
|
||||||
});
|
});
|
||||||
|
|
||||||
post('/admin/users/:username/delete', function () {
|
post('/admin/users/:username/delete', function () {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
$file = from($_REQUEST, 'file');
|
$file = from($_REQUEST, 'file') ?? null;
|
||||||
$username = from($_REQUEST, 'username');
|
$username = from($_REQUEST, 'username') ?? null;
|
||||||
$user_role = user('role', $username);
|
$user_role = user('role', $username) ?? null;
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if ($proper && login()) {
|
if ($proper && login()) {
|
||||||
if ($role === 'admin') {
|
if ($role === 'admin') {
|
||||||
if ($user_role !== 'admin') {
|
if ($user_role !== 'admin') {
|
||||||
|
|
@ -2994,7 +2994,6 @@ post('/admin/users/:username/delete', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
post('/admin/gallery', function () {
|
post('/admin/gallery', function () {
|
||||||
|
|
||||||
if (login()) {
|
if (login()) {
|
||||||
$page = from($_REQUEST, 'page');
|
$page = from($_REQUEST, 'page');
|
||||||
$images = image_gallery(null, $page, 40);
|
$images = image_gallery(null, $page, 40);
|
||||||
|
|
@ -3004,8 +3003,8 @@ post('/admin/gallery', function () {
|
||||||
|
|
||||||
// Show category page
|
// Show category page
|
||||||
get('/admin/categories', function () {
|
get('/admin/categories', function () {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
|
|
@ -3040,8 +3039,8 @@ get('/admin/categories', function () {
|
||||||
// Show the category page
|
// Show the category page
|
||||||
get('/admin/categories/:category', function ($category) {
|
get('/admin/categories/:category', function ($category) {
|
||||||
|
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
|
|
@ -3101,8 +3100,8 @@ get('/admin/categories/:category', function ($category) {
|
||||||
|
|
||||||
// Show admin/comments - All comments
|
// Show admin/comments - All comments
|
||||||
get('/admin/comments', function () {
|
get('/admin/comments', function () {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login() && ($role === 'admin' || $role === 'editor')) {
|
if (login() && ($role === 'admin' || $role === 'editor')) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
|
|
||||||
|
|
@ -3139,8 +3138,8 @@ get('/admin/comments', function () {
|
||||||
|
|
||||||
// Show admin/comments/pending - Pending comments
|
// Show admin/comments/pending - Pending comments
|
||||||
get('/admin/comments/pending', function () {
|
get('/admin/comments/pending', function () {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login() && ($role === 'admin' || $role === 'editor')) {
|
if (login() && ($role === 'admin' || $role === 'editor')) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
|
|
||||||
|
|
@ -3187,8 +3186,8 @@ get('/admin/comments/pending', function () {
|
||||||
|
|
||||||
// Show admin/comments/settings - Settings page
|
// Show admin/comments/settings - Settings page
|
||||||
get('/admin/comments/settings', function () {
|
get('/admin/comments/settings', function () {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login() && $role === 'admin') {
|
if (login() && $role === 'admin') {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
|
|
||||||
|
|
@ -3214,7 +3213,7 @@ get('/admin/comments/settings', function () {
|
||||||
|
|
||||||
// Save comments settings
|
// Save comments settings
|
||||||
post('/admin/comments/settings', function () {
|
post('/admin/comments/settings', function () {
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if (login() && $proper) {
|
if (login() && $proper) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'];
|
||||||
$role = user('role', $user);
|
$role = user('role', $user);
|
||||||
|
|
@ -3225,6 +3224,7 @@ post('/admin/comments/settings', function () {
|
||||||
// Note: HTML forms convert dots to underscores in POST data
|
// Note: HTML forms convert dots to underscores in POST data
|
||||||
$config['comments.moderation'] = isset($_POST['comments_moderation']) ? 'true' : 'false';
|
$config['comments.moderation'] = isset($_POST['comments_moderation']) ? 'true' : 'false';
|
||||||
$config['comments.honeypot'] = isset($_POST['comments_honeypot']) ? 'true' : 'false';
|
$config['comments.honeypot'] = isset($_POST['comments_honeypot']) ? 'true' : 'false';
|
||||||
|
$config['comments.jstime'] = isset($_POST['comments_jstime']) ? 'true' : 'false';
|
||||||
$config['comments.notify'] = isset($_POST['comments_notify']) ? 'true' : 'false';
|
$config['comments.notify'] = isset($_POST['comments_notify']) ? 'true' : 'false';
|
||||||
$config['comments.mail.enabled'] = isset($_POST['comments_mail_enabled']) ? 'true' : 'false';
|
$config['comments.mail.enabled'] = isset($_POST['comments_mail_enabled']) ? 'true' : 'false';
|
||||||
|
|
||||||
|
|
@ -3274,8 +3274,8 @@ post('/admin/comments/settings', function () {
|
||||||
|
|
||||||
// Show edit comment form
|
// Show edit comment form
|
||||||
get('/admin/comments/edit/:commentfile/:commentid', function ($commentfile, $commentid) {
|
get('/admin/comments/edit/:commentfile/:commentid', function ($commentfile, $commentid) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login() && ($role === 'admin' || $role === 'editor')) {
|
if (login() && ($role === 'admin' || $role === 'editor')) {
|
||||||
|
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
|
|
@ -3320,7 +3320,7 @@ get('/admin/comments/edit/:commentfile/:commentid', function ($commentfile, $com
|
||||||
|
|
||||||
// Update comment
|
// Update comment
|
||||||
post('/admin/comments/update/:commentfile/:commentid', function ($commentfile, $commentid) {
|
post('/admin/comments/update/:commentfile/:commentid', function ($commentfile, $commentid) {
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if (login() && $proper) {
|
if (login() && $proper) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'];
|
||||||
$role = user('role', $user);
|
$role = user('role', $user);
|
||||||
|
|
@ -3626,7 +3626,7 @@ post('/admin/themes/:theme', function ($theme) {
|
||||||
$redir = site_url() . 'admin/themes';
|
$redir = site_url() . 'admin/themes';
|
||||||
header("location: $redir");
|
header("location: $redir");
|
||||||
}
|
}
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if (login() && $proper) {
|
if (login() && $proper) {
|
||||||
$new_config = array();
|
$new_config = array();
|
||||||
$new_Keys = array();
|
$new_Keys = array();
|
||||||
|
|
@ -3758,8 +3758,8 @@ get('/category/:category/feed', function ($category) {
|
||||||
|
|
||||||
// Show edit the category page
|
// Show edit the category page
|
||||||
get('/category/:category/edit', function ($category) {
|
get('/category/:category/edit', function ($category) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
|
|
@ -3804,7 +3804,7 @@ get('/category/:category/edit', function ($category) {
|
||||||
// Get edited data from category page
|
// Get edited data from category page
|
||||||
post('/category/:category/edit', function () {
|
post('/category/:category/edit', function () {
|
||||||
|
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
|
|
||||||
if(!login()) {
|
if(!login()) {
|
||||||
$login = site_url() . 'login';
|
$login = site_url() . 'login';
|
||||||
|
|
@ -3862,8 +3862,8 @@ post('/category/:category/edit', function () {
|
||||||
|
|
||||||
// Delete category
|
// Delete category
|
||||||
get('/category/:category/delete', function ($category) {
|
get('/category/:category/delete', function ($category) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
|
|
@ -3908,7 +3908,7 @@ get('/category/:category/delete', function ($category) {
|
||||||
|
|
||||||
// Get deleted category data
|
// Get deleted category data
|
||||||
post('/category/:category/delete', function () {
|
post('/category/:category/delete', function () {
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if ($proper && login()) {
|
if ($proper && login()) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'];
|
||||||
$role = user('role', $user);
|
$role = user('role', $user);
|
||||||
|
|
@ -4788,7 +4788,7 @@ get('/'. permalink_type() .'/:name/delete', function ($name) {
|
||||||
// Get deleted data from blog post
|
// Get deleted data from blog post
|
||||||
post('/'. permalink_type() .'/:name/delete', function () {
|
post('/'. permalink_type() .'/:name/delete', function () {
|
||||||
|
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if ($proper && login()) {
|
if ($proper && login()) {
|
||||||
$file = from($_REQUEST, 'file');
|
$file = from($_REQUEST, 'file');
|
||||||
$destination = from($_GET, 'destination');
|
$destination = from($_GET, 'destination');
|
||||||
|
|
@ -5023,8 +5023,8 @@ get('/:static', function ($static) {
|
||||||
|
|
||||||
// Show the add sub static page
|
// Show the add sub static page
|
||||||
get('/:static/add', function ($static) {
|
get('/:static/add', function ($static) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
|
|
@ -5137,8 +5137,8 @@ post('/:static/add', function ($static) {
|
||||||
|
|
||||||
// Show edit the static page
|
// Show edit the static page
|
||||||
get('/:static/edit', function ($static) {
|
get('/:static/edit', function ($static) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
|
|
@ -5188,7 +5188,7 @@ get('/:static/edit', function ($static) {
|
||||||
|
|
||||||
// Get edited data from static page
|
// Get edited data from static page
|
||||||
post('/:static/edit', function () {
|
post('/:static/edit', function () {
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if(!login()) {
|
if(!login()) {
|
||||||
$login = site_url() . 'login';
|
$login = site_url() . 'login';
|
||||||
header("location: $login");
|
header("location: $login");
|
||||||
|
|
@ -5264,8 +5264,8 @@ post('/:static/edit', function () {
|
||||||
|
|
||||||
// Deleted the static page
|
// Deleted the static page
|
||||||
get('/:static/delete', function ($static) {
|
get('/:static/delete', function ($static) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
|
|
@ -5315,7 +5315,7 @@ get('/:static/delete', function ($static) {
|
||||||
// Get deleted data for static page
|
// Get deleted data for static page
|
||||||
post('/:static/delete', function () {
|
post('/:static/delete', function () {
|
||||||
|
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if ($proper && login()) {
|
if ($proper && login()) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'];
|
||||||
$role = user('role', $user);
|
$role = user('role', $user);
|
||||||
|
|
@ -5437,8 +5437,8 @@ get('/:static/:sub', function ($static, $sub) {
|
||||||
|
|
||||||
// Edit the sub static page
|
// Edit the sub static page
|
||||||
get('/:static/:sub/edit', function ($static, $sub) {
|
get('/:static/:sub/edit', function ($static, $sub) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
|
|
@ -5496,7 +5496,7 @@ get('/:static/:sub/edit', function ($static, $sub) {
|
||||||
|
|
||||||
// Submitted data from edit sub static page
|
// Submitted data from edit sub static page
|
||||||
post('/:static/:sub/edit', function ($static, $sub) {
|
post('/:static/:sub/edit', function ($static, $sub) {
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if(!login()) {
|
if(!login()) {
|
||||||
$login = site_url() . 'login';
|
$login = site_url() . 'login';
|
||||||
header("location: $login");
|
header("location: $login");
|
||||||
|
|
@ -5577,8 +5577,8 @@ post('/:static/:sub/edit', function ($static, $sub) {
|
||||||
|
|
||||||
// Delete sub static page
|
// Delete sub static page
|
||||||
get('/:static/:sub/delete', function ($static, $sub) {
|
get('/:static/:sub/delete', function ($static, $sub) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'] ?? null;
|
||||||
$role = user('role', $user);
|
$role = user('role', $user) ?? null;
|
||||||
if (login()) {
|
if (login()) {
|
||||||
config('views.root', 'system/admin/views');
|
config('views.root', 'system/admin/views');
|
||||||
if ($role === 'editor' || $role === 'admin') {
|
if ($role === 'editor' || $role === 'admin') {
|
||||||
|
|
@ -5636,7 +5636,7 @@ get('/:static/:sub/delete', function ($static, $sub) {
|
||||||
// Submitted data from delete sub static page
|
// Submitted data from delete sub static page
|
||||||
post('/:static/:sub/delete', function () {
|
post('/:static/:sub/delete', function () {
|
||||||
|
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if ($proper && login()) {
|
if ($proper && login()) {
|
||||||
$user = $_SESSION[site_url()]['user'];
|
$user = $_SESSION[site_url()]['user'];
|
||||||
$role = user('role', $user);
|
$role = user('role', $user);
|
||||||
|
|
@ -6057,7 +6057,7 @@ get('/:year/:month/:name/delete', function ($year, $month, $name) {
|
||||||
// Get deleted data from blog post
|
// Get deleted data from blog post
|
||||||
post('/:year/:month/:name/delete', function () {
|
post('/:year/:month/:name/delete', function () {
|
||||||
|
|
||||||
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token'));
|
$proper = is_csrf_proper(from($_REQUEST, 'csrf_token')) ?? null;
|
||||||
if ($proper && login()) {
|
if ($proper && login()) {
|
||||||
$file = from($_REQUEST, 'file');
|
$file = from($_REQUEST, 'file');
|
||||||
$destination = from($_GET, 'destination');
|
$destination = from($_GET, 'destination');
|
||||||
|
|
@ -6085,6 +6085,7 @@ post('/comments/submit', function () {
|
||||||
$parentId = from($_POST, 'parent_id');
|
$parentId = from($_POST, 'parent_id');
|
||||||
$notify = from($_POST, 'notify');
|
$notify = from($_POST, 'notify');
|
||||||
$website = from($_POST, 'website'); // honeypot field
|
$website = from($_POST, 'website'); // honeypot field
|
||||||
|
$company = from($_POST, 'company'); // antispam js and timestamp field
|
||||||
|
|
||||||
// Note: $url was also set in json file single comment block, but then it is hard to manage if .md file changes name or path
|
// Note: $url was also set in json file single comment block, but then it is hard to manage if .md file changes name or path
|
||||||
// introduced instead function get_url_from_file that handle both .md (content) and .json (content/comments)
|
// introduced instead function get_url_from_file that handle both .md (content) and .json (content/comments)
|
||||||
|
|
@ -6095,7 +6096,8 @@ post('/comments/submit', function () {
|
||||||
'comment' => $comment,
|
'comment' => $comment,
|
||||||
'parent_id' => $parentId,
|
'parent_id' => $parentId,
|
||||||
'notify' => $notify,
|
'notify' => $notify,
|
||||||
'website' => $website
|
'website' => $website,
|
||||||
|
'company' => $company
|
||||||
);
|
);
|
||||||
|
|
||||||
$result = commentInsert($data, $url, null);
|
$result = commentInsert($data, $url, null);
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,10 @@ function displayCommentsForm($url, $mdfile = null, $parentId = null)
|
||||||
<input type="text" name="website" tabindex="-1" value="" autocomplete="off">
|
<input type="text" name="website" tabindex="-1" value="" autocomplete="off">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- JS check & time check field (hidden from users) -->
|
||||||
|
<div style="position:absolute;left:-6000px;" aria-hidden="true">
|
||||||
|
<input type="text" name="company" tabindex="-2" value="" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group" style="width: 100%">
|
<div class="form-group" style="width: 100%">
|
||||||
<label for="name-<?php echo $formId; ?>"><?php echo i18n('Name'); ?> <span class="required">*</span></label>
|
<label for="name-<?php echo $formId; ?>"><?php echo i18n('Name'); ?> <span class="required">*</span></label>
|
||||||
|
|
@ -43,14 +47,12 @@ function displayCommentsForm($url, $mdfile = null, $parentId = null)
|
||||||
<textarea class="form-control" id="comment-<?php echo $formId; ?>" name="comment" rows="5" required></textarea>
|
<textarea class="form-control" id="comment-<?php echo $formId; ?>" name="comment" rows="5" required></textarea>
|
||||||
<small class="form-text text-muted"><?php echo i18n('Comment_formatting_help'); ?></small>
|
<small class="form-text text-muted"><?php echo i18n('Comment_formatting_help'); ?></small>
|
||||||
</div>
|
</div>
|
||||||
<!-- Emidio 20251105 - temporarily disabled
|
|
||||||
<div class="form-group form-check">
|
<div class="form-group form-check">
|
||||||
<input type="checkbox" class="form-check-input" id="notify-<?php echo $formId; ?>" name="notify" value="1">
|
<input type="checkbox" class="form-check-input" id="notify-<?php echo $formId; ?>" name="notify" value="1">
|
||||||
<label class="form-check-label" for="notify-<?php echo $formId; ?>">
|
<label class="form-check-label" for="notify-<?php echo $formId; ?>">
|
||||||
<?php echo i18n('Notify_new_comments'); ?>
|
<?php echo i18n('Notify_new_comments'); ?>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
-->
|
|
||||||
<br>
|
<br>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<button type="submit" class="btn btn-primary submit-comment"><?php echo $parentId ? i18n('Post_Reply') : i18n('Post_Comment'); ?></button>
|
<button type="submit" class="btn btn-primary submit-comment"><?php echo $parentId ? i18n('Post_Reply') : i18n('Post_Comment'); ?></button>
|
||||||
|
|
@ -186,7 +188,7 @@ function displayCommentsSection($url, $file = null)
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<script>
|
<script type="text/javascript">
|
||||||
function showReplyForm(commentId, commentUrl) {
|
function showReplyForm(commentId, commentUrl) {
|
||||||
// Hide all other reply forms
|
// Hide all other reply forms
|
||||||
document.querySelectorAll('.reply-container').forEach(function(el) {
|
document.querySelectorAll('.reply-container').forEach(function(el) {
|
||||||
|
|
@ -209,6 +211,9 @@ function displayCommentsSection($url, $file = null)
|
||||||
'<div style="position:absolute;left:-5000px;" aria-hidden="true">' +
|
'<div style="position:absolute;left:-5000px;" aria-hidden="true">' +
|
||||||
'<input type="text" name="website" tabindex="-1" value="" autocomplete="off">' +
|
'<input type="text" name="website" tabindex="-1" value="" autocomplete="off">' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
|
'<div style="position:absolute;left:-6000px;" aria-hidden="true">' +
|
||||||
|
'<input type="text" name="company" tabindex="-2" value="" autocomplete="off">' +
|
||||||
|
'</div>' +
|
||||||
'<div class="form-group">' +
|
'<div class="form-group">' +
|
||||||
'<label for="name-' + formId + '"><?php echo i18n("Name"); ?> <span class="required">*</span></label>' +
|
'<label for="name-' + formId + '"><?php echo i18n("Name"); ?> <span class="required">*</span></label>' +
|
||||||
'<input type="text" class="form-control" id="name-' + formId + '" name="name" required>' +
|
'<input type="text" class="form-control" id="name-' + formId + '" name="name" required>' +
|
||||||
|
|
@ -223,12 +228,10 @@ function displayCommentsSection($url, $file = null)
|
||||||
'<textarea class="form-control" id="comment-' + formId + '" name="comment" rows="5" required></textarea>' +
|
'<textarea class="form-control" id="comment-' + formId + '" name="comment" rows="5" required></textarea>' +
|
||||||
'<small class="form-text text-muted"><?php echo i18n("Comment_formatting_help"); ?></small>' +
|
'<small class="form-text text-muted"><?php echo i18n("Comment_formatting_help"); ?></small>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<!-- Emidio 20251105 - temporarily disabled ' +
|
|
||||||
'<div class="form-group form-check">' +
|
'<div class="form-group form-check">' +
|
||||||
'<input type="checkbox" class="form-check-input" id="notify-' + formId + '" name="notify" value="1">' +
|
'<input type="checkbox" class="form-check-input" id="notify-' + formId + '" name="notify" value="1">' +
|
||||||
'<label class="form-check-label" for="notify-' + formId + '"><?php echo i18n("Notify_new_comments"); ?></label>' +
|
'<label class="form-check-label" for="notify-' + formId + '"><?php echo i18n("Notify_new_comments"); ?></label>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
' -->' +
|
|
||||||
'<br><div class="form-group">' +
|
'<br><div class="form-group">' +
|
||||||
'<button type="submit" class="btn btn-primary submit-reply"><?php echo i18n("Post_Reply"); ?></button> ' +
|
'<button type="submit" class="btn btn-primary submit-reply"><?php echo i18n("Post_Reply"); ?></button> ' +
|
||||||
'<button type="button" class="btn btn-secondary cancel-reply" onclick="cancelReply(\'' + commentId + '\')"><?php echo i18n("Cancel"); ?></button>' +
|
'<button type="button" class="btn btn-secondary cancel-reply" onclick="cancelReply(\'' + commentId + '\')"><?php echo i18n("Cancel"); ?></button>' +
|
||||||
|
|
@ -236,6 +239,13 @@ function displayCommentsSection($url, $file = null)
|
||||||
'</form>';
|
'</form>';
|
||||||
|
|
||||||
container.innerHTML = formHtml;
|
container.innerHTML = formHtml;
|
||||||
|
|
||||||
|
// Populate antispam company field with current timestamp
|
||||||
|
const timestampSeconds = Math.floor(Date.now() / 1000);
|
||||||
|
const companyField = container.querySelector('[name="company"]');
|
||||||
|
if (companyField) {
|
||||||
|
companyField.value = timestampSeconds;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -299,11 +309,24 @@ function displayCommentsSection($url, $file = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Antispam protection, executed when page is loaded
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
const timestampSeconds = Math.floor(Date.now() / 1000);
|
||||||
|
|
||||||
// Esegui la funzione quando il DOM è caricato
|
// Select all forms in page
|
||||||
|
document.querySelectorAll('form').forEach(function (form) {
|
||||||
|
// Finds all fields named "company"
|
||||||
|
form.querySelectorAll('[name="company"]').forEach(function (field) {
|
||||||
|
field.value = timestampSeconds;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Executed when page is loaded
|
||||||
document.addEventListener('DOMContentLoaded', handleCommentStatus);
|
document.addEventListener('DOMContentLoaded', handleCommentStatus);
|
||||||
|
|
||||||
// Esegui anche quando l'hash cambia (se navighi sulla stessa pagina)
|
// Executed also when page hash changes (navigating in same page)
|
||||||
window.addEventListener('hashchange', handleCommentStatus);
|
window.addEventListener('hashchange', handleCommentStatus);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -213,9 +213,6 @@ function get_comments_file_from_url($url) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all comments for a post/page
|
* Get all comments for a post/page
|
||||||
*
|
*
|
||||||
|
|
@ -283,11 +280,12 @@ function getAllComments($page = null, $perpage = null)
|
||||||
|
|
||||||
$allComments = array();
|
$allComments = array();
|
||||||
|
|
||||||
|
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
$comments = getComments('', $file, true);
|
$comments = getComments('', $file, true);
|
||||||
|
$url = get_url_from_file($file);
|
||||||
foreach ($comments as $comment) {
|
foreach ($comments as $comment) {
|
||||||
$comment['file'] = $file;
|
$comment['file'] = $file;
|
||||||
|
$comment['url'] = $url;
|
||||||
$allComments[] = $comment;
|
$allComments[] = $comment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -308,6 +306,22 @@ function getAllComments($page = null, $perpage = null)
|
||||||
return $allComments;
|
return $allComments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getPublishedComments($limit = 5)
|
||||||
|
{
|
||||||
|
$comments = array();
|
||||||
|
$counter = 0;
|
||||||
|
$allComments = getAllComments();
|
||||||
|
foreach ($allComments as $comment) {
|
||||||
|
if ($comment['published'] == 1) {
|
||||||
|
$comments[] = $comment;
|
||||||
|
}
|
||||||
|
if (count($comments) >= $limit) break;
|
||||||
|
}
|
||||||
|
return $comments;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate unique comment ID
|
* Generate unique comment ID
|
||||||
*
|
*
|
||||||
|
|
@ -343,6 +357,26 @@ function buildCommentTree($comments, $parentId = null, $level = 0)
|
||||||
return $tree;
|
return $tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate seconds difference from now
|
||||||
|
*
|
||||||
|
* @param int/string $timestamp
|
||||||
|
* @return difference in seconds
|
||||||
|
*/
|
||||||
|
function secondsGenerationSubmit($timestamp) {
|
||||||
|
if (!is_numeric($timestamp)) {
|
||||||
|
return null; // invalid value
|
||||||
|
}
|
||||||
|
|
||||||
|
$timestampJS = (int) $timestamp;
|
||||||
|
$timestampServer = time();
|
||||||
|
|
||||||
|
return $timestampServer - $timestampJS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate comment data
|
* Validate comment data
|
||||||
*
|
*
|
||||||
|
|
@ -375,6 +409,13 @@ function validateComment($data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate js and time (if enabled) - minimum 2 seconds, maximum 600 seconds
|
||||||
|
if (comments_config('comments.jstime') === 'true') {
|
||||||
|
if (!$data['company'] || secondsGenerationSubmit($data['company']) < 3 || secondsGenerationSubmit($data['company']) > 3600) {
|
||||||
|
$errors[] = 'comment_submission_error_spam';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'valid' => empty($errors),
|
'valid' => empty($errors),
|
||||||
'errors' => $errors
|
'errors' => $errors
|
||||||
|
|
@ -442,9 +483,21 @@ function commentInsert($data, $url, $mdfile = null)
|
||||||
'message' => 'comment_submission_error'
|
'message' => 'comment_submission_error'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Subscription handling
|
||||||
|
if ($comment['notify']) {
|
||||||
|
setSubscription($comment['email'], 'subscribe');
|
||||||
|
}
|
||||||
|
|
||||||
// Send notifications
|
// Clearing cache if comment is published, otherwise doesn't display on page
|
||||||
sendCommentNotifications($url, $comment, $comments);
|
if ($comment['published']) {
|
||||||
|
rebuilt_cache('all');
|
||||||
|
clear_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Send notifications - notify admin always, notify subscribers only if published
|
||||||
|
sendCommentNotifications($url, $comment, $comments, true, $comment['published']);
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'success' => true,
|
'success' => true,
|
||||||
|
|
@ -453,6 +506,190 @@ function commentInsert($data, $url, $mdfile = null)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// action can be subscribe, confirm, unsubscribe
|
||||||
|
function setSubscription($email, $action) {
|
||||||
|
$subscriptions_dir = 'content/comments/.subscriptions';
|
||||||
|
if (!is_dir($subscriptions_dir)) {
|
||||||
|
mkdir($subscriptions_dir);
|
||||||
|
}
|
||||||
|
$subscription_file = $subscriptions_dir . '/' . encryptEmailForFilename($email, comments_config('comments.salt'));
|
||||||
|
|
||||||
|
$subscription = getSubscription($email);
|
||||||
|
|
||||||
|
if ($action == 'subscribe') {
|
||||||
|
if ($subscription['status'] == 'subscribed') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
elseif ($subscription['status'] == 'waiting') {
|
||||||
|
sendSubscriptionEmail($email);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$subscription['status'] = 'waiting';
|
||||||
|
$json = json_encode($subscription, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||||
|
file_put_contents($subscription_file, $json);
|
||||||
|
sendSubscriptionEmail($email);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
elseif ($action == 'confirm' && $subscription['status'] == 'waiting') {
|
||||||
|
$subscription['status'] = 'subscribed';
|
||||||
|
$json = json_encode($subscription, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||||
|
file_put_contents($subscription_file, $json);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
elseif ($action == 'unsubscribe') {
|
||||||
|
@unlink($subscription_file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// nothing here
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// returns array
|
||||||
|
function getSubscription($email) {
|
||||||
|
$subscriptions_dir = 'content/comments/.subscriptions';
|
||||||
|
$subscription_file = $subscriptions_dir . '/' . encryptEmailForFilename($email, comments_config('comments.salt'));
|
||||||
|
if (!file_exists($subscription_file)) {
|
||||||
|
$subscription['status'] = 'no';
|
||||||
|
$subscription['date'] = date('Y-m-d H:i:s');
|
||||||
|
$subscription['email'] = $email;
|
||||||
|
return $subscription;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$subscription = json_decode(file_get_data($subscription_file), true);
|
||||||
|
return $subscription;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function confirmSubscription($filename) {
|
||||||
|
$subscriptions_dir = 'content/comments/.subscriptions';
|
||||||
|
$subscription_file = $subscriptions_dir . '/' . $filename;
|
||||||
|
if (sanitizedSubscriptionFile($filename) && file_exists($subscription_file)) {
|
||||||
|
$subscription = json_decode(file_get_data($subscription_file), true);
|
||||||
|
setSubscription($subscription['email'], 'confirm');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function sanitizedSubscriptionFile($filename) {
|
||||||
|
// no path traversal, sanitizing filename
|
||||||
|
$filename = basename($filename);
|
||||||
|
if (!preg_match('/^[a-zA-Z0-9._-]+$/', $filename)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$subscriptions_dir = 'content/comments/.subscriptions';
|
||||||
|
$subscription_file = $subscriptions_dir . '/' . $filename;
|
||||||
|
|
||||||
|
// check if path is invalid
|
||||||
|
$real_file = realpath($subscription_file);
|
||||||
|
$real_dir = realpath($subscriptions_dir);
|
||||||
|
|
||||||
|
if ($real_file === false || $real_dir === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if path outside .subscriptions dir (we are DELETING files!)
|
||||||
|
if (strpos($real_file, $real_dir . DIRECTORY_SEPARATOR) !== 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function deleteSubscription($filename) {
|
||||||
|
$subscriptions_dir = 'content/comments/.subscriptions';
|
||||||
|
$subscription_file = $subscriptions_dir . '/' . $filename;
|
||||||
|
|
||||||
|
if (sanitizedSubscriptionFile($filename) && file_exists($subscription_file)) {
|
||||||
|
@unlink($subscription_file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function encryptEmailForFilename(string $email, string $secretKey) {
|
||||||
|
// Normalize email
|
||||||
|
$email = strtolower(trim($email));
|
||||||
|
// Create HMAC hash
|
||||||
|
$hash = hash_hmac('sha256', $email, $secretKey, true);
|
||||||
|
|
||||||
|
// URL-safe Base64 (filename-safe)
|
||||||
|
$safe = rtrim(strtr(base64_encode($hash), '+/', '-_'), '=');
|
||||||
|
return $safe;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function sendSubscriptionEmail($email) {
|
||||||
|
try {
|
||||||
|
$mail = new PHPMailer(true);
|
||||||
|
|
||||||
|
// Server settings
|
||||||
|
$mail->isSMTP();
|
||||||
|
$mail->Host = comments_config('comments.mail.host');
|
||||||
|
$mail->SMTPAuth = true;
|
||||||
|
$mail->Username = comments_config('comments.mail.username');
|
||||||
|
$mail->Password = comments_config('comments.mail.password');
|
||||||
|
$mail->Port = comments_config('comments.mail.port');
|
||||||
|
|
||||||
|
$encryption = comments_config('comments.mail.encryption');
|
||||||
|
if ($encryption === 'tls') {
|
||||||
|
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
|
||||||
|
} elseif ($encryption === 'ssl') {
|
||||||
|
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recipients
|
||||||
|
$mail->setFrom(
|
||||||
|
comments_config('comments.mail.from.email'),
|
||||||
|
comments_config('comments.mail.from.name')
|
||||||
|
);
|
||||||
|
$mail->addAddress($email);
|
||||||
|
|
||||||
|
// Content
|
||||||
|
$mail->isHTML(true);
|
||||||
|
$mail->CharSet = 'UTF-8';
|
||||||
|
|
||||||
|
$mail->Subject = i18n('comment_subscribe_confirmation') . ' '.config('blog.title');
|
||||||
|
$mail->Body = "
|
||||||
|
<h3>" . i18n('comment_subscribe_thread') . ": ".config('site.url')."</h3>
|
||||||
|
<p>" . i18n('comment_subscribe_request') . " ".config('blog.title')."</p>
|
||||||
|
<p>" . i18n('comment_subscribe_never_requested') . "</p>
|
||||||
|
<p>" . i18n('comment_subscribe_click') . " <a href=\"".config('site.url')."?subscribe=".encryptEmailForFilename($email, comments_config('comments.salt'))."\"><b>" . i18n('comment_subscribe_here') . "</b></a> " . i18n('comment_subscribe_confirm_message') . "</p>
|
||||||
|
<p> </p>
|
||||||
|
<p>" . i18n('comment_subscribe_unsubscribe_message') . " ".config('blog.title')." " . i18n('comment_subscribe_unsubscribe_anytime') . ": <a href=\"".config('site.url')."?unsubscribe=".encryptEmailForFilename($email, comments_config('comments.salt'))."\"><b>" . i18n('comment_unsubscribe') . "</b></a>.</p>
|
||||||
|
<p> </p>
|
||||||
|
";
|
||||||
|
|
||||||
|
$mail->send();
|
||||||
|
return true;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
error_log("Subscription notification email failed: {$mail->ErrorInfo}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Publish a comment (approve from moderation)
|
* Publish a comment (approve from moderation)
|
||||||
*
|
*
|
||||||
|
|
@ -480,8 +717,10 @@ function commentPublish($file, $commentId)
|
||||||
$comment['published'] = true;
|
$comment['published'] = true;
|
||||||
$updated = true;
|
$updated = true;
|
||||||
|
|
||||||
// Send notifications to other commenters
|
$url = get_url_from_file($file);
|
||||||
sendCommentNotifications($comment, $comments, false);
|
|
||||||
|
// Send notifications only to subscribers when publishing (admin already saw it in moderation)
|
||||||
|
sendCommentNotifications($url, $comment, $comments, false, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -491,6 +730,10 @@ function commentPublish($file, $commentId)
|
||||||
}
|
}
|
||||||
|
|
||||||
$json = json_encode($comments, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
$json = json_encode($comments, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||||
|
|
||||||
|
rebuilt_cache('all');
|
||||||
|
clear_cache();
|
||||||
|
|
||||||
return file_put_contents($file, $json, LOCK_EX) !== false;
|
return file_put_contents($file, $json, LOCK_EX) !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -525,6 +768,10 @@ function commentDelete($mdfile, $commentId)
|
||||||
$comments = array_values($comments);
|
$comments = array_values($comments);
|
||||||
|
|
||||||
$json = json_encode($comments, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
$json = json_encode($comments, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||||
|
|
||||||
|
rebuilt_cache('all');
|
||||||
|
clear_cache();
|
||||||
|
|
||||||
return file_put_contents($file, $json, LOCK_EX) !== false;
|
return file_put_contents($file, $json, LOCK_EX) !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -587,22 +834,24 @@ function commentModify($file, $commentId, $data)
|
||||||
* @param array $newComment The new comment
|
* @param array $newComment The new comment
|
||||||
* @param array $allComments All comments for this post
|
* @param array $allComments All comments for this post
|
||||||
* @param bool $notifyAdmin Notify admin (default true)
|
* @param bool $notifyAdmin Notify admin (default true)
|
||||||
|
* @param bool $notifySubscribers Notify subscribers (default true)
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
function sendCommentNotifications($url, $newComment, $allComments, $notifyAdmin = true)
|
function sendCommentNotifications($url, $newComment, $allComments, $notifyAdmin = true, $notifySubscribers = true)
|
||||||
{
|
{
|
||||||
// TODO: function to be fixed, still using postId variable
|
// Check if mail is enabled
|
||||||
|
if (comments_config('comments.mail.enabled') !== 'true') {
|
||||||
// Check if notifications are enabled
|
|
||||||
if (comments_config('comments.notify') !== 'true' ||
|
|
||||||
comments_config('comments.mail.enabled') !== 'true') {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$recipients = array();
|
$recipients = array();
|
||||||
|
|
||||||
// Add admin email
|
// Add admin email - notify if comments.notifyadmin = "true" OR comments.moderation = "true"
|
||||||
if ($notifyAdmin) {
|
if ($notifyAdmin) {
|
||||||
|
$shouldNotifyAdmin = (comments_config('comments.notifyadmin') === 'true') ||
|
||||||
|
(comments_config('comments.moderation') === 'true');
|
||||||
|
|
||||||
|
if ($shouldNotifyAdmin) {
|
||||||
$adminEmail = comments_config('comments.admin.email');
|
$adminEmail = comments_config('comments.admin.email');
|
||||||
if (!empty($adminEmail) && filter_var($adminEmail, FILTER_VALIDATE_EMAIL)) {
|
if (!empty($adminEmail) && filter_var($adminEmail, FILTER_VALIDATE_EMAIL)) {
|
||||||
$recipients[$adminEmail] = array(
|
$recipients[$adminEmail] = array(
|
||||||
|
|
@ -611,16 +860,18 @@ function sendCommentNotifications($url, $newComment, $allComments, $notifyAdmin
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
}
|
||||||
|
|
||||||
// TODO: this part is disabled until a spam-secured way for comment subscription is implemented
|
// Add subscribers only if notifySubscribers is true AND comments.notify is enabled
|
||||||
|
if ($notifySubscribers && comments_config('comments.notify') === 'true') {
|
||||||
// Add parent comment author (if replying)
|
// Add parent comment author (if replying)
|
||||||
if (!empty($newComment['parent_id'])) {
|
if (!empty($newComment['parent_id'])) {
|
||||||
foreach ($allComments as $comment) {
|
foreach ($allComments as $comment) {
|
||||||
if ($comment['id'] === $newComment['parent_id'] &&
|
if ($comment['id'] === $newComment['parent_id'] &&
|
||||||
$comment['notify'] &&
|
$comment['notify'] &&
|
||||||
$comment['email'] !== $newComment['email']) {
|
$comment['email'] !== $newComment['email']) {
|
||||||
|
$subscrition = getSubscription($comment['email']);
|
||||||
|
if ($subscrition['status'] == 'subscribed') {
|
||||||
$recipients[$comment['email']] = array(
|
$recipients[$comment['email']] = array(
|
||||||
'name' => $comment['name'],
|
'name' => $comment['name'],
|
||||||
'type' => 'parent'
|
'type' => 'parent'
|
||||||
|
|
@ -628,14 +879,15 @@ function sendCommentNotifications($url, $newComment, $allComments, $notifyAdmin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add other commenters in same thread who want notifications
|
// Add all commenters in same thread (same JSON file) who want notifications
|
||||||
foreach ($allComments as $comment) {
|
foreach ($allComments as $comment) {
|
||||||
if ($comment['notify'] &&
|
if ($comment['notify'] &&
|
||||||
$comment['email'] !== $newComment['email'] &&
|
$comment['email'] !== $newComment['email'] &&
|
||||||
$comment['id'] !== $newComment['id']) {
|
$comment['id'] !== $newComment['id']) {
|
||||||
// Same thread = same parent or no parent
|
$subscrition = getSubscription($comment['email']);
|
||||||
if ($comment['parent_id'] === $newComment['parent_id']) {
|
if ($subscrition['status'] == 'subscribed') {
|
||||||
$recipients[$comment['email']] = array(
|
$recipients[$comment['email']] = array(
|
||||||
'name' => $comment['name'],
|
'name' => $comment['name'],
|
||||||
'type' => 'thread'
|
'type' => 'thread'
|
||||||
|
|
@ -643,7 +895,8 @@ function sendCommentNotifications($url, $newComment, $allComments, $notifyAdmin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
}
|
||||||
|
|
||||||
// Send emails
|
// Send emails
|
||||||
foreach ($recipients as $email => $info) {
|
foreach ($recipients as $email => $info) {
|
||||||
sendCommentEmail($email, $info['name'], $url, $newComment, $info['type']);
|
sendCommentEmail($email, $info['name'], $url, $newComment, $info['type']);
|
||||||
|
|
@ -692,22 +945,30 @@ function sendCommentEmail($to, $toName, $url, $comment, $type = 'admin')
|
||||||
$mail->CharSet = 'UTF-8';
|
$mail->CharSet = 'UTF-8';
|
||||||
|
|
||||||
if ($type === 'admin') {
|
if ($type === 'admin') {
|
||||||
$mail->Subject = 'New comment awaiting moderation';
|
if (comments_config('comments.moderation') === 'true') {
|
||||||
|
$mail->Subject = i18n('comment_email_admin_awaiting') . " - " . config('blog.title');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$mail->Subject = i18n('comment_email_admin_new') . " - " . config('blog.title');
|
||||||
|
}
|
||||||
$mail->Body = "
|
$mail->Body = "
|
||||||
<h3>New comment on: {$url}</h3>
|
<h3>".i18n('comment_email_new').": {$url}</h3>
|
||||||
<p><strong>From:</strong> {$comment['name']} ({$comment['email']})</p>
|
<p><strong>" . i18n('comment_email_from') . ":</strong> {$comment['name']} ({$comment['email']})</p>
|
||||||
<p><strong>Comment:</strong></p>
|
<p><strong>" . i18n('comment') . ":</strong></p>
|
||||||
<p>" . nl2br(htmlspecialchars($comment['comment'])) . "</p>
|
<p>" . nl2br(htmlspecialchars($comment['comment'])) . "</p>
|
||||||
<p><a href='" . site_url() . "admin/comments'>Moderate comments</a></p>
|
<p><a href='" . site_url() . "admin/comments'>" . i18n('comment_email_moderate'). "</a></p>
|
||||||
";
|
";
|
||||||
} else {
|
} else {
|
||||||
$mail->Subject = 'New reply to your comment';
|
$mail->Subject = i18n('comment_email_new_subscribed') . " - " . config('blog.title');
|
||||||
$mail->Body = "
|
$mail->Body = "
|
||||||
<h3>Someone replied to your comment on: {$url}</h3>
|
<h3>" . i18n('comment_email_new_replied') .": " . site_url() . "{$url}</h3>
|
||||||
<p><strong>From:</strong> {$comment['name']}</p>
|
<p><strong>" . i18n('comment_email_from') . ":</strong> {$comment['name']}</p>
|
||||||
<p><strong>Comment:</strong></p>
|
<p><strong>" . i18n('comment') . ":</strong></p>
|
||||||
<p>" . nl2br(htmlspecialchars($comment['comment'])) . "</p>
|
<p>" . nl2br(htmlspecialchars($comment['comment'])) . "</p>
|
||||||
<p><a href='" . site_url() . "{$url}#comment-{$comment['id']}'>View comment</a></p>
|
<p><a href='" . site_url() . "{$url}#comment-{$comment['id']}'>" . i18n('comment_email_view_comment') . "</a></p>
|
||||||
|
<p> </p>
|
||||||
|
<p>" . i18n('comment_subscribe_unsubscribe_message') . " ".config('blog.title')." " . i18n('comment_subscribe_unsubscribe_anytime') . ": <a href=\"".config('site.url')."?unsubscribe=".encryptEmailForFilename($to, comments_config('comments.salt'))."\"><b>" . i18n('comment_unsubscribe') . "</b></a>.</p>
|
||||||
|
<p> </p>
|
||||||
";
|
";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -764,4 +1025,17 @@ function formatCommentText($text)
|
||||||
return $text;
|
return $text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (isset($_GET['subscribe'])) {
|
||||||
|
confirmSubscription($_GET['subscribe']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_GET['unsubscribe'])) {
|
||||||
|
deleteSubscription($_GET['unsubscribe']);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
28
system/includes/comments_readme.md
Normal file
28
system/includes/comments_readme.md
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
# HTMLy comment system
|
||||||
|
A commenting system integrated in HTMLy, featuring:
|
||||||
|
* threaded comments (comments and replies)
|
||||||
|
* antispam (with no external dependencies, no CAPTCHA)
|
||||||
|
* notification system and thread subscription
|
||||||
|
|
||||||
|
## 2025-12-26
|
||||||
|
Some major fixes to comment system:
|
||||||
|
* added English strings in notification emails (needs translations in all other languages)
|
||||||
|
* improved antispam system
|
||||||
|
* added subscription verification system
|
||||||
|
|
||||||
|
### Antispam
|
||||||
|
Antispam work using a honeyspot and js/token verification
|
||||||
|
|
||||||
|
* honeyspot: field "website" is added as hidden - spambot usually fill it, all comments with this field not empty are discarded as SPAM
|
||||||
|
* js: javascript must be enabled to have a comment being considered not SPAM - all modern browser have js enabled
|
||||||
|
* token: a token with encrypted timestamp is generated and added to "company" hidden field - a comment have to be submitted between 3 and 600 seconds from token generation (this should prevent automated submissions (before 3 seconds) and luckily forged tokens (converting in a number, probably resulting in less than 3 or more than 600 seconds difference)
|
||||||
|
|
||||||
|
Both methods can be enabled/disabled from comment system configuration page.
|
||||||
|
|
||||||
|
## Subscriptions
|
||||||
|
Users can ask for email notification when a new comment is published in a subscribed post thread. A confirmation email is sent to the user email, and subscription must be confirmed clicking on a link. Only confirmed subscription users will receive notification emails.
|
||||||
|
Notification email are sent on comment publish (if validation is enabled) or comment insert (if moderation is disabled, not recommended).
|
||||||
|
|
||||||
|
**TODO**: limit comment insert by time from same IP address
|
||||||
|
|
||||||
|
**TODO**: reworking backend functions to use HTMLy basic functions and avoid code duplication
|
||||||
|
|
@ -90,6 +90,13 @@ function i18n($key, $value = null)
|
||||||
$_i18n = parse_ini_file($value, true);
|
$_i18n = parse_ini_file($value, true);
|
||||||
else
|
else
|
||||||
$_i18n = parse_ini_file('lang/en_US.ini', true);
|
$_i18n = parse_ini_file('lang/en_US.ini', true);
|
||||||
|
$theme_path = parse_url(theme_path(), PHP_URL_PATH);
|
||||||
|
$theme_lang_file = $_SERVER['DOCUMENT_ROOT'] . $theme_path . 'lang/en_US.ini';
|
||||||
|
$_i18n_local = array();
|
||||||
|
if (file_exists($theme_lang_file)) {
|
||||||
|
$_i18n_local = parse_ini_file($theme_lang_file, true);
|
||||||
|
}
|
||||||
|
$_i18n = array_replace($_i18n, $_i18n_local);
|
||||||
} elseif ($value == null)
|
} elseif ($value == null)
|
||||||
return (isset($_i18n[$key]) ? $_i18n[$key] : $key);
|
return (isset($_i18n[$key]) ? $_i18n[$key] : $key);
|
||||||
else
|
else
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue