Questioning Everything Propaganda

Home Tags
Login RSS
v208Changelog

Changelog

All notable changes to Bookgram will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[2.08.0] - 2025-11-15

Added

  • Optional Password Protection for Private Articles

    • New optional password field for private pages as an additional security layer
    • Password input field in article editor (templates/edit.php:71-91)
    • Password protection works in conjunction with share tokens
    • Visitors need BOTH the share link AND correct password to access protected pages
    • Authors and admins can view their own private pages without password
    • Password prompt template for guest authentication (templates/password-prompt.php)
    • New /verify-password route for password verification (index.php:161-197)
    • Session-based password authentication (stays authenticated for the session)
    • Password removal option in editor interface
  • Navigation Enhancement

    • "Back to Folder" button on article pages (templates/page.php:81)
    • Returns user to the current folder/directory level
    • Positioned on left side of page actions bar
    • Automatically calculates parent folder from article path
    • Returns to root browser if article is at top level

Changed

  • Data Model Updates

    • Page JSON schema now includes:
      • password_hash (string) - BCrypt/Argon2 hash of the optional password
    • Updated save_page_content() function signature to accept $password parameter (app/core/functions.php:367)
    • Enhanced can_view_private_page() to check password authentication (app/core/functions.php:199-238)
    • Added verify_page_password() function for secure password verification (app/core/functions.php:246-267)
  • User Experience Improvements

    • Password prompt shown automatically when accessing password-protected pages
    • Clear error messages on incorrect password attempts
    • Visual indicators show when password protection is enabled (🔒 icon with text)
    • Authors see password status in both edit and view modes
    • Inline JavaScript toggle for password field visibility in editor

Security

  • Password Hashing

    • Passwords hashed using PHP's password_hash() with PASSWORD_DEFAULT (currently Argon2id or BCrypt)
    • Password verification uses password_verify() to prevent timing attacks
    • Passwords never stored in plaintext
    • Session-based authentication prevents repeated password entry
    • CSRF protection on password submission
  • Access Control Flow

    1. Check if page is private
    2. Check if user is author/admin (bypass all checks)
    3. Verify share token is valid
    4. If password is set, verify password via session or prompt
    5. Grant access only if all conditions met

Technical Details

Password Protection Implementation

  • Password field is optional - private pages can have token-only or token+password protection
  • Passwords are hashed immediately upon save
  • Empty password field preserves existing password
  • "Remove password" checkbox explicitly clears password protection
  • Password verification stores authentication in $_SESSION['authenticated_pages'] array

File Locations Modified

/app/core/functions.php        - Password hashing and verification functions
/templates/edit.php            - Password input field with toggle (lines 71-103)
/templates/page.php            - Password protection indicators (lines 45-56)
/templates/password-prompt.php - Password entry form (NEW)
/index.php                     - Password handling in save and verify routes
/CHANGELOG.md                  - This file (UPDATED)
/VERSION.txt                   - Version number update

Database Schema Changes

For existing pages, the password field will be automatically initialized:

  • password_hash: '' (empty string = no password)

Backward Compatibility

  • Fully backward compatible with v2.07
  • Existing private pages without passwords continue to work with token-only access
  • Public pages unaffected
  • No data migration required

Usage Example

Setting up a password-protected page:

  1. Edit or create a page
  2. Check "Make this page private"
  3. Enter a password in the "Optional Password Protection" field
  4. Save the page
  5. Copy the share link
  6. Share both the link AND password with intended recipients

Accessing a password-protected page:

  1. Click the share link (includes token in URL)
  2. Enter the password when prompted
  3. Submit to view the page
  4. Password authentication persists for the session

Known Limitations

  • Password authentication is session-based only (no persistent "remember me")
  • No password strength requirements enforced
  • No password reset mechanism (author must change it manually)
  • Session expires when browser is closed
  • Multiple failed password attempts are not rate-limited

[2.07.0] - 2025-11-15

Added

  • Private Articles with Share Links

    • New privacy control for articles - pages can now be marked as private
    • Private pages are only accessible via a unique, auto-generated share link
    • Privacy checkbox added to article editor (templates/edit.php:62-68)
    • Share link display in edit mode for private pages (templates/edit.php:70-83)
    • Share link display on page view for authors/admins (templates/page.php:43-62)
    • Private pages are hidden from:
      • Directory browser unless viewed by author/admin
      • Search results unless viewed by author/admin
      • RSS feeds unless viewed by author/admin
    • Access control:
      • Authors can always view their own private pages
      • Admins can view all private pages
      • Anyone with the share token URL can view the page
      • 403 Forbidden error for unauthorized access attempts
  • Code Block Rendering Fix

    • Fixed markdown code blocks to properly preserve line breaks and formatting
    • Added CSS styling for <pre> elements with white-space: pre (public/css/style.css:239-254)
    • Improved monospace font rendering for code blocks
    • Added proper styling for inline code vs. multi-line code blocks
    • Print stylesheet also updated to handle code blocks correctly

Changed

  • Data Model Updates

    • Page JSON schema now includes:
      • is_private (boolean) - privacy status flag
      • share_token (string) - unique 32-character hex token for private access
    • Updated save_page_content() function signature to accept $is_private parameter (app/core/functions.php:367)
    • Privacy settings preserved during page reverts (app/core/functions.php:891)
  • Function Enhancements

    • get_directory_contents() - Now filters private pages based on user permissions (app/core/functions.php:571-574)
    • search_pages() - Excludes private pages from search unless user has permission (app/core/functions.php:929-932)
    • get_all_pages_sorted_by_date() - Filters private pages from RSS/listings (app/core/functions.php:990-993)
    • Added can_view_private_page() helper function (app/core/functions.php:199-226)
    • Added generate_share_token() utility function (app/core/functions.php:190-192)

Technical Details

Privacy Implementation

  • Share tokens are generated using bin2hex(random_bytes(16)) for cryptographic security
  • Token validation uses hash_equals() to prevent timing attacks
  • Tokens are automatically generated when a page is first marked private
  • Tokens are cleared when a page is made public
  • Token parameter passed via URL query string: ?token={32-char-hex}

File Locations Modified

/public/css/style.css          - Code block styling (lines 239-254)
/app/core/functions.php        - Privacy functions and data filtering
/templates/edit.php            - Privacy checkbox and share link UI
/templates/page.php            - Private page notice and share link display
/index.php                     - Privacy parameter handling in save route (line 120)
/CHANGELOG.md                  - This file (NEW)

Database Schema Changes

No database migrations required (file-based storage).

For existing pages, the privacy fields will be automatically initialized to default values:

  • is_private: false
  • share_token: '' (empty string)

Security Notes

  • Share tokens are 32 characters (128 bits of entropy)
  • Private pages return HTTP 403 for unauthorized access
  • Share links do not expire (manual regeneration requires toggling privacy off/on)
  • Authors cannot see other authors' private pages without the share link
  • Admins have full access to all pages regardless of privacy settings

Backward Compatibility

  • All changes are fully backward compatible with v2.06
  • Existing pages will default to public (is_private = false)
  • No data migration required
  • Pages without privacy fields will be treated as public

Known Limitations

  • Share tokens do not expire and cannot be regenerated without toggling privacy
  • No analytics on who accessed a private page via share link
  • Private pages still increment view counts when accessed via share link
  • No bulk privacy operations available in admin panel

[2.06.0] - Previous Version

Initial release of v2.06 with:

  • File-based content management system
  • Markdown support via Parsedown
  • User authentication (Admin/Editor roles)
  • Page revision history
  • UUID-based permanent links
  • Feature image support
  • Directory/folder organization
  • Full-text search
  • RSS feed
  • Profile pages
  • Hit tracking (total and unique views)
  • Print-friendly styling
  • IBM OS/2 Warp 3 retro theme
  • Mobile responsive design
  • Movable launchpad navigation

Original Author: admin

Views: 31 (Unique: 28)

Page ID ( Copy Link): page_69189cdc833881.76959100-f15788af7b9c4d8e

Page History (1 revisions):

  • 2025-11-15 15:31:40 (Viewing)