ListAllFiles Handler Documentation
Overview
The `ListAllFiles` class is a specialized HTTP handler that provides authenticated
users with a structured inventory of their website files. It serves as a critical
component of the file management system, enabling users to browse and organize their
content through the web-based administrative interface.
Purpose
This handler is designed for a multi-tenant hosting service where each registered
user manages their own domain and associated files. It allows authenticated users to
retrieve a categorized listing of all files within their account's directory structure,
facilitating file management operations through the web interface.
Core Functionality
1. Request Validation
- Only accepts POST requests (returns HTTP 405 for other methods)
- Expects JSON payload containing optional path information
- Validates all requests against active user sessions
2. Authentication & Authorization
- Extracts session ID from the request via `getJavaSessionId()`
- Validates the session through `SessionManager.getUsername()`
- Returns HTTP 403 (Forbidden) if the session is invalid or expired
- Ensures users can only access their own file directories
3. User Path Resolution
The handler determines the appropriate file path based on the authenticated user:
- Standard users: `/home/lukas/users/{username}/static/`
- Special case (`norlund_johan_lukas_com`): `/home/lukas/JavaServerProject/www/static/`
- Supports subdirectory navigation via the `path` parameter in the request JSON
4. File Categorization
Files are automatically categorized into seven distinct types:
- folder: Directories (identified by trailing `/`)
- html: HTML files (`.html`)
- php: PHP files (`.php`)
- css: Stylesheet files (`.css`)
- js: JavaScript files (`.js`)
- img: Image files (matches extensions in `IMAGE_EXTENSIONS` array)
- video: Video files (matches extensions in `VIDEO_EXTENSIONS` array)
5. JSON Response Structure
Returns a structured JSON response with files organized by category:
[{
"folder": ["directory1/", "directory2/"],
"html": ["index.html", "about.html"],
"php": ["contact.php"],
"css": ["style.css"],
"img": ["logo.png", "banner.jpg"],
"js": ["script.js"],
"video": ["intro.mp4"],
"status": "ok"
}]
6. Error Handling
- Returns `{"status": "fail"}` if the directory listing operation fails
- Catches and logs `RuntimeException` during file system operations
- Maintains service stability even when encountering permission or I/O errors
Request Format
Method: POST
Content-Type: application/json
Body:
{
"path": "subdirectory/path" // Optional: relative path within user's directory
}
Response Codes
- 200 OK: Successfully retrieved and categorized file listing
- 403 Forbidden: Invalid or missing session authentication
- 405 Method Not Allowed: Non-POST request attempted
Security Features
- Session-based authentication: All requests must include a valid session ID
- User isolation: Each user can only access their own directory structure
- Path validation: User-provided paths are appended to the base user directory, preventing directory traversal attacks
- No file content exposure: Only file names and types are returned, not file contents
Dependencies
This handler relies on several helper methods and components:
- `parseJsonToMap()`: Converts JSON request body to a key-value map
- `getJavaSessionId()`: Extracts session identifier from the request
- `SessionManager.getUsername()`: Validates session and retrieves username
- `filesList()`: Retrieves the list of files from the specified directory
- `IMAGE_EXTENSIONS` and `VIDEO_EXTENSIONS`: Arrays defining supported media file formats
Use Case
This handler is typically called by the administrative web interface when users:
- Navigate through their file directory structure
- Need to refresh the file listing after upload/delete operations
- Browse subdirectories within their account
- Manage their website content through the control panel
flowchart TD
A(["Start"]) --> B{"Request method
== POST?"}
B -->|No| C["Send 405 Method Not Allowed
Close response"]
B -->|Yes| D["Read request body
into String"]
D --> E["Parse JSON into Map
using parseJsonToMap"]
E --> F["Get sessionId from exchange
via getJavaSessionId"]
F --> G["Get username from
SessionManager.getUsername"]
G --> H{"Username
is null?"}
H -->|Yes| I["Send 403 Forbidden
Close response body"]
H -->|No| J["Set base userPath for user"]
J --> K{"Username ==
norlund_johan_lukas_com?"}
K -->|Yes| L["Set userPath =
ADMIN_DIR + /static/"]
K -->|No| M["Set userPath =
USER_DIR + user +/static/"]
L --> N
M --> N
N{"map.get(path) not
empty and not null?"}
N -->|Yes| O["Append map path to userPath"]
N -->|No| P["Keep userPath as is"]
O --> Q["Log: 'Listing files in: {userPath}'"]
P --> Q
Q --> R["Initialize StringBuilder json
Set success = true
Start JSON array and object"]
R --> S["TRY: Call filesList(userPath)"]
S --> T{"RuntimeException
thrown?"}
T -->|Yes| U["CATCH: Log error
Set response = failure JSON
Set success = false"]
T -->|No| V["Start iterating through types array:
folder, html, php, css, img, js, video"]
V --> W["Append type name to JSON
Start array for this type"]
W --> X["Iterate through all files
from filesList"]
X --> Y{"File matches
current type?"}
Y -->|folder| Z1["Check: file.endsWith('/')"]
Y -->|html/php/css/js| Z2["Check: file.endsWith('.type')"]
Y -->|img| Z3["Check against
IMAGE_EXTENSIONS array"]
Y -->|video| Z4["Check against
VIDEO_EXTENSIONS array"]
Z1 --> AA{"Match found?"}
Z2 --> AA
Z3 --> AA
Z4 --> AA
AA -->|Yes| AB["Append file to JSON array
with comma separator"]
AA -->|No| AC["Skip this file"]
AB --> AD{"More files for
this type?"}
AC --> AD
AD -->|Yes| X
AD -->|No| AE["Close JSON array for type
Add comma"]
AE --> AF{"More types to
process?"}
AF -->|Yes| V
AF -->|No| AG{"success
== true?"}
U --> AG
AG -->|Yes| AH["Append: 'status': 'ok'
Close JSON object and array
Set response = json.toString"]
AG -->|No| AI["Keep response = failure JSON"]
AH --> AJ["Log: 'Sending back: {response}'"]
AI --> AJ
AJ --> AK["Set Content-Type:
application/json"]
AK --> AL["Send 200 response
with response.length"]
AL --> AM["Write response bytes
to OutputStream"]
AM --> AN["Close OutputStream"]
AN --> AO(["End"])
C --> AO
I --> AO