- Updated 39 pages from old header01.php and header02.php includes
- All pages now use single configurable header.php with $headerStyle variable
- Light style (default): Most pages (login, register, trips, courses, etc.)
- Dark style: Coming from header01 original usage
Pages updated:
- Admin pages: admin_*.php (10 files)
- Booking pages: bookings.php, campsite_booking.php, etc.
- Content pages: blog.php, blog_details.php, contact.php, events.php, etc.
- User pages: account_settings.php, membership*.php, register.php, etc.
- Utility pages: 404.php, payment_confirmation.php, reset_password.php, etc.
All pages now maintain single header template source - easier to update navigation, styles, and functionality across the entire site.
- index.php: Changed from header01.php to new unified header.php with dark style
- about.php: Changed from header02.php to new unified header.php with light style
- Both pages now use single configurable header template
- Eliminates dependency on separate header files
Test these pages in browser to verify header renders correctly before updating remaining pages
- Single source of truth for header code (consolidates header01.php and header02.php)
- Configurable styling via $headerStyle variable ('dark' or 'light')
- Conditional CSS and asset loading based on style
- Logo and text colors automatically switch based on style
- Eliminates 95% code duplication between two header files
- JavaScript consolidated for profile menu and dropdowns
- Navigation menu maintained in one place for easier updates
Usage:
$headerStyle = 'dark'; // Dark header with white text
require_once("header.php");
OR
$headerStyle = 'light'; // Light header with dark text
require_once("header.php");
Next: Update all pages from header01.php/header02.php to use this new template
Changed countRecentFailedAttempts() to use MySQL DATE_SUB(NOW(), INTERVAL ? MINUTE)
instead of PHP-calculated cutoff time. This ensures consistent datetime comparison
on the database server without timezone mismatches between PHP and MySQL.
This fixes the issue where the AND attempted_at condition was filtering out all
recent attempts due to timestamp comparison inconsistencies.
The countRecentFailedAttempts() function was requiring BOTH email AND ip_address to match, which caused failed attempts from different IPs to not count together. This prevented account lockout from working properly.
Changed to count failed attempts by email only. IP address is still recorded for audit purposes but doesn't affect the failed attempt count.
This ensures:
- Failed attempts accumulate correctly regardless of IP changes
- Accounts lock after 5 failed attempts within 15 minutes
- Prevents attackers from bypassing by changing IP
Updated forms with hidden CSRF token fields:
- comment_box.php - Comment form
- course_details.php - Course booking form
- campsites.php - Campsite addition modal form
- bar_tabs.php - Bar tab creation modal form
- membership_application.php - Membership application form
Updated backend processors with CSRF validation:
- create_bar_tab.php - Bar tab AJAX processor
- add_campsite.php - Campsite form processor
- submit_order.php - Order submission processor
All forms now require validated CSRF tokens before processing, preventing cross-site request forgery attacks.