Technical Blueprint: Gallery Protect System

Master Technical Index (Sections 0-17 Unabridged)

0. Quick Start & Manifest (Core File Inventory and Install Instructions)

/nphotos/auth.php: The central engine. Handles session_start(), verifies credentials against users.txt, and serves the Orange Login UI. Now logs 🔴 LOGOUT actions before destroying sessions.

/nphotos/config.php: Configuration hub. Sets $MY_FOLDER_ID = "nphotos" and physical path constants. Required for every PHP script.

/nphotos/protect.php: Content Gatekeeper. Specifically for /protected_html/. Includes the Dynamic Logout logic which unsets last_page and redirects back to the current URI.

/nphotos/change_password.php: User Utility. Updates users.txt via LOCK_EX and forces a re-login to ensure credential synchronization.

/nphotos/user_info.php: AJAX endpoint for h5ai. Read-only session identity provider.

/nphotos/monitor.php: Admin Dashboard. Includes Auto-Trim (2000 lines), Smart Dates, and Scrollable History (Last 100 hits).

/nphotos/logout.php: Global session terminator. Supports ?from_monitor=1 context.

/nphotos/users.txt: Case-insensitive user database (user:pass). Restricted access.

/nphotos/global_activity.log: Activity log (timestamp|folder|user|ip|action|login_start).

/nphotos/avatar: Directory to place pictures of users (username.jpg or username. png) to be used to show a small picture in the logoff widget

/protected_html: Targeted directory for custom HTML projects. Uses protect.php to wrap content fragments (e.g., _content.php) with the gallery's security session.

/nphotos/albums: Directory for all the original h5ai stuff including your album directories and the modifications done for this project.

/nphotos/albums/_h5ai/public/ext/custom_ui.js: Injection script for h5ai

/nphotos/albums/_h5ai/private/conf/options.json: json for the h5ai injection

/nphotos/incl_docs/: The SSI included files of this documentation, included by docs.shtml

Install Instructions

  1. Copy all files and sub directories to your target directory (which should be placed in your site root).
  2. Edit all the above files and replace any hard coded occurences of "nphotos" in the target to the name of the your directory, do not forget the .htacess files showed in section 16. If you integrate with h5ai do not forget to update the related files showed in section 16. In future releases of this package the edit of the php files will be avoided.
  3. Check config.php where the variable $MY_FOLDER_ID should be set to the name of your directory .
  4. If you plan to use the h5ai integration, replace the album subdirectories with your content of pictures or other content files.
  5. If you plan to use only or also use the protected_html directory integration. Edit all the contained files and replace any hard coded occurences of "nphotos" to the name of the folder id.
  6. Check and allow the webserver to read and write to: users.txt, global_activity.log and the /albums/_h5ai/public/cache and subfolders (thumbs by h5ai are cashed here)
  7. Test your set-up!

1. Architecture Deep-Dive & Namespacing

The system operates on a Synchronous Gatekeeping strategy. Instead of a heavy SQL database, it uses the server's memory (Sessions) and the file system (.htaccess) to create a multi-layered perimeter.

A. Layer 1: The Request Interceptor (.htaccess)

Protection begins before PHP even initializes. The server level handles the "Hard Perimeter":

B. Layer 2: Namespace Isolation & Session Logic

To allow multiple independent galleries (e.g., /nphotos/ and /vacation/) to exist on the same server without "cross-talking," the system uses Namespace Isolation. Every session key is prefixed with a unique folder ID.

// Variables are dynamically built using $MY_FOLDER_ID
$auth_key = "auth_" . $MY_FOLDER_ID;         // Validation Token
$user_key = "active_user_" . $MY_FOLDER_ID;  // Identity Token
$path_key = "last_page_" . $MY_FOLDER_ID;    // Return-Path Memory

The "Kill" Protocol: Every protected page includes the auth.php engine at Line 1. If the $auth_key is missing or expired (default 24h), the script executes exit;. This kills the process instantly, ensuring no content bytes are sent to the browser until authentication is confirmed.

C. Layer 3: The Flat-File Database (users.txt)

The "Safe" is a simple, high-speed text parser that follows strict integrity protocols:

D. Content Gatekeeping Methods

The protection is applied differently based on the content type:

E. The Request Lifecycle (Visual Flow)

To troubleshoot access issues, follow the path of a single image request:

  1. The Entry: Browser requests /albums/photo.jpg.
  2. Perimeter Check (Apache): .htaccess checks the HTTP_REFERER.
    Result: No referer? → 302 Redirect to access_denied.php.
  3. Identity Check (PHP): If referer is valid, auth.php checks for $_SESSION['auth_nphotos'].
    Result: No session? → 302 Redirect to login UI.
  4. Content Delivery: If both are valid, the server streams the bytes to the browser.

4. Credentials Logic

$lines = file("users.txt", FILE_IGNORE_NEW_LINES);
foreach ($lines as $line) {
    if (strpos($line, '#') === 0 || empty($line)) continue;
    list($u, $p) = explode(':', $line);
    if (strtolower($input_user) === strtolower($u) && $input_pass === $p) {
        $_SESSION['auth_nphotos'] = true;
        $_SESSION['active_user_nphotos'] = $u;
    }
}

5. Troubleshooting (Path Resolution & Browser Cache)

A. Path & Redirect Issues

B. UI & Widget Persistence (The "Edge" Problem)

Because the system uses AJAX to fetch user info for the h5ai widget, aggressive browser caching (especially in Microsoft Edge) can cause old code or typos to persist even after server-side fixes.

6. Logout & "Admin-Stay" Logic

if (isset($_GET['from_monitor'])) {
    session_destroy();
    header("Location: monitor.php");
} else {
    $redirect = $_SESSION['last_page_nphotos'] ?? '/';
    session_destroy();
    header("Location: " . $redirect);
}

7. Multi-Tab Session Suppression

user_info.php is prohibited from writing to $_SESSION['last_page_nphotos'].

8. Help Modal

Uses toggleModal(true) and backdrop-filter: blur(10px).

9. Avatar System

Priority: .png -> .jpg -> CSS Initials.

10. Admin Overlay

Debug via ?admin_view=true to dump $_SESSION.

11. Bridge Script (custom_ui.js)

$(function () {
    const pollUser = () => {
        $.getJSON('/nphotosjj/user_info.php', function (data) {
            if (data.user && data.user !== 'Guest') {
                // Update h5ai identity widget
            }
        });
    };
    pollUser();
    setInterval(pollUser, 60000);
});

12. Bridge Config (options.json)

"resources": {
    "scripts": ["../nphotosjj/custom_ui"],
    "styles": ["../nphotosjj/custom_style"]
}

13. Monitoring (Logic & Auto-Trim)

Auto-Trim: Slices global_activity.log to 2000 lines if count exceeds 2200.

Smart Date: "H:i" for today, "d M, H:i" for older entries.

14. CSS & Branding

Primary: #005A9C. Accent: #d35400.

15. Detailed Path Mapping

ComponentPathAccess Rule
Master Gate/nphotosjj/auth.phpPublic
Protect Script/nphotosjj/protect.phpInternal Include
Credentials/nphotosjj/users.txtDENIED (403)

16. Full .htaccess and h5a integration files Repository (Unabridged)

A. Root Directory (/.htaccess)

Options -Indexes
# Direct 403 errors to the authentication gate
ErrorDocument 403 /nphotosjj/auth.php?error=403

B. System Core (/nphotosjj/.htaccess)

# 1. BLOCK SENSITIVE DATA
# Prevents direct URL access to credentials and activity logs
<FilesMatch "\.(txt|log|conf|sh|inc)$">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
    <IfModule !mod_authz_core.c>
        Order Allow,Deny
        Deny from all
    </IfModule>
</FilesMatch>

# 2. ALLOW WEB ASSETS
# Specifically allow the assets needed for the UI and Avatars
<FilesMatch "\.(php|jpg|JPG|png|css|js|svg)$">
    <IfModule mod_authz_core.c>
        Require all granted
    </IfModule>
    <IfModule !mod_authz_core.c>
        Order Deny,Allow
        Allow from all
    </IfModule>
</FilesMatch>

# 3. ANTI-CACHING FOR DYNAMIC ASSETS
# Forces browsers to fetch fresh versions of UI logic and Gatekeepers.
# Prevents the "Old Widget" or "Old Styles" issue in Edge/Mobile.
<FilesMatch "\.(php|js|css)$">
    Header set Cache-Control "no-cache, no-store, must-revalidate"
    Header set Pragma "no-cache"
    Header set Expires 0
</FilesMatch>
B.1 System Core, the full content of the adjusted file (/nphotosjj/.htaccess)
# ----------------------------------------------------------------------
# h5ai stuff
# ----------------------------------------------------------------------

AddType text/html .shtml
AddType image/svg+xml .svg .svgz
AddHandler server-parsed .shtml
Options Indexes FollowSymLinks Includes
# 1. SET DEFAULT DIRECTORY PAGE

DirectoryIndex index.shtml index.html index.php /nphotosjj/albums/_h5ai/public/index.php
SSILegacyExprParser on


# 2. PROTECT SENSITIVE CORE FILES
# This blocks people from seeing your password list and logs
<FilesMatch "\.(txt|log|conf|sh|inc)$">

    <IfModule mod_authz_core.c>

        Require all denied
    </IfModule>
    <IfModule !mod_authz_core.c>

        Order Allow,Deny
        Deny from all
    </IfModule>

</FilesMatch>


# 3. ALLOW SHELL AND GATEKEEPER FILES
# We specifically allow .php and .jpg (for avatars)
<FilesMatch "\.(php|jpg|JPG|png|css|js)$">

    <IfModule mod_authz_core.c>

        Require all granted
    </IfModule>
    <IfModule !mod_authz_core.c>
        Order Deny,Allow
        Allow from all
    </IfModule>
</FilesMatch>

# 4. PREVENT CACHING ON THE GATEKEEPER
# Ensures the logout/login status is always fresh
<Files "protect.php">

    Header set Cache-Control "no-cache, no-store, must-revalidate"
    Header set Pragma "no-cache"
    Header set Expires 0
</Files>

C. Protected Content (/protected_html/.htaccess)

# 1. SET DEFAULT DIRECTORY PAGE
DirectoryIndex index.php index.html

# 2. PROTECT SENSITIVE CORE FILES
# Blocks direct access to passwords, logs, and include fragments
<FilesMatch "\.(txt|log|conf|sh|inc)$">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
    <IfModule !mod_authz_core.c>
        Order Allow,Deny
        Deny from all
    </IfModule>
</FilesMatch>

# 3. FRAGMENT PROTECTION (Gatekeeper Bypass Prevention)
# Specifically blocks files like "about_content.php" from direct browsing
<FilesMatch "_content\.php$">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
    <IfModule !mod_authz_core.c>
        Order Allow,Deny
        Deny from all
    </IfModule>
</FilesMatch>

# 4. PREVENT CACHING ON THE GATEKEEPER
<Files "protect.php">
    Header set Cache-Control "no-cache, no-store, must-revalidate"
    Header set Pragma "no-cache"
    Header set Expires 0
</Files>
C.1 Protected Content, the full content of the adjusted file (/protected_html/.htaccess)
 # 1. SET DEFAULT DIRECTORY PAGE
DirectoryIndex index.php index.html

# 2. PROTECT SENSITIVE CORE FILES
# This blocks people from seeing your password list and logs
<FilesMatch "\.(txt|log|conf|sh|inc)$">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
    <IfModule !mod_authz_core.c>
        Order Allow,Deny
        Deny from all
    </IfModule>
</FilesMatch>

# 3. ALLOW SHELL AND GATEKEEPER FILES
# We specifically allow .php and .jpg (for avatars)
<FilesMatch "\.(php|jpg|JPG|png|css|js)$">
    <IfModule mod_authz_core.c>
        Require all granted
    </IfModule>
    <IfModule !mod_authz_core.c>
        Order Deny,Allow
        Allow from all
    </IfModule>
</FilesMatch>
# SPECIFIC PROTECTION: Block files containing "_content" (e.g., test_content.php)
# This prevents direct URL access but ALLOWS PHP "include" to work.
<FilesMatch "_content\.php$">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
    <IfModule !mod_authz_core.c>
        Order Allow,Deny
        Deny from all
    </IfModule>
</FilesMatch>

# 4. PREVENT CACHING ON THE GATEKEEPER
# Ensures the logout/login status is always fresh
<Files "protect.php">
    Header set Cache-Control "no-cache, no-store, must-revalidate"
    Header set Pragma "no-cache"
    Header set Expires 0
</Files>

D. Protected Content h5ai (/nphotosjj/albums/.htaccess)

# ----------------------------------------------------------------------
# ANTI-HOTLINKING & DEEP-LINK PROTECTION
# ----------------------------------------------------------------------

# Protect all common file types (Images, Video, Documents, Audio, Archives)
<FilesMatch "(?i)\.(jpg|jpeg|png|gif|webp|avif|heic|pdf|doc|docx|xls|xlsx|ppt|pptx|txt|mov|mp4|avi|mkv|wmv|mp3|wav|flac|zip|rar|7z|exe|msi|cr2|nef|arw)$">
    
    # 1. Block if the referrer doesn't match your specific domain
    <If "%{HTTP_REFERER} !~ /alf\.homelinux\.net/">
        Redirect 302 https://alf.homelinux.net/nphotosjj/access_denied.php
    </If>
    
    # 2. Block if the referrer is completely empty (Direct URL access/Sneak peek)
    <If "-z %{HTTP_REFERER}">
        Redirect 302 https://alf.homelinux.net/nphotosjj/access_denied.php
    </If>

</FilesMatch>

E. Integration files for h5ai

h5ai custom_ui.js

/nphotosjj/albums/_h5ai/public/ext/custom_ui.js

h5ai options.json

/nphotosjj/albums/_h5ai/private/conf/options.json (Refer to Section 12 for the specific configuration)

17. Password Management & Input Hardening

The change_password.php utility and auth.php UI implement a v10.60 Unicode-Aware Validation layer to support Swedish national characters while maintaining strict database integrity.

A. Security Filters & Character Logic

B. Universal UI Toggle (The "Eye" Logic)

The system utilizes a parameter-based JavaScript function to handle multiple password fields (Login, Old, New, Confirm) without ID conflicts:

// auth.php - Universal Toggle Function
function togglePass(fieldId, eyeId) {
    var p = document.getElementById(fieldId);
    var e = document.getElementById(eyeId);
    if (!p || !e) return;
    
    p.type = (p.type === "password") ? "text" : "password";
    e.innerText = (p.type === "password") ? "👁️" : "🙈";
}

C. Processing & File Integrity

// change_password.php - Atomic Write with Error Logging
if ($updated) {
    if (file_put_contents($USER_FILE, implode("\n", $new_content), LOCK_EX)) {
        // Log success for monitor.php
        file_put_contents('global_activity.log', $log_line, FILE_APPEND | LOCK_EX);
    }
}

D. Protected Accounts

Accounts marked with a * suffix in users.txt are recognized as "Read-Only" by the change utility. The script strips the * for login comparison but detects it during change requests to block unauthorized password modifications to admin accounts.

18. Cloning & Deployment Checklist (Migration Guide)

When duplicating this system to a new directory (e.g., from /nphotosjj/ to /travel/), use this checklist to ensure all hardcoded paths are updated. Search and Replace is your best tool for this process.

A. The PHP Layer

B. The Apache Layer (.htaccess)

C. The h5ai Bridge

D. Permission Audit