This project is a full-stack PHP web application that acts as an FTP-style media portal for an ISP. The ISP stores movies, music, software, eBooks, and other files on the platform. Subscribers (called Members) can visit the site and freely browse, search, filter, and download any available content without creating an account.
- Admin - has full control. Can add or remove Moderators, upload or delete any content, view all requests, and see the dashboard.
- Moderator - can upload and delete content, and review or respond to Member requests.
The project was built as a group assignment for the Web Technologies course (CSE 4101), Spring 2025โ2026, Section A. Four students each built one part of the system.
| Student ID | Task | Responsibility |
|---|---|---|
| 23-50434-1 | Task 1 | Authentication, Profile Page, Home Page, Category Navigation |
| 23-50453-1 | Task 2 | Admin - Manage Moderators & Contents (Full CRUD) |
| 23-50637-1 | Task 3 | Moderator - Add/Delete Contents, View & Update Requests |
| 23-50674-1 | Task 4 | Member - Browse, Search, Filter, Request Box, Download |
- Registration for Admin and Moderator accounts only
- Login with session management (
$_SESSION['user_id'],['name'],['role']) - Remember Me - secure 30-day auto-login using a random token stored as a SHA-256 hash in the database and an HttpOnly cookie in the browser
- Password hashing with
password_hash()(bcrypt) andpassword_verify() - CSRF token on every form - generated in the shared header, verified in every controller
- Profile page - update name, email, profile picture, change password
- Role-aware navbar - Admin, Moderator, and Guest see different links
- Logout - destroys session, clears Remember Me token from DB and cookie
- Upload new media files (same validation as Admin)
- Delete own uploaded content (Admin can delete any content)
- View the full content library in a table
- View all content requests from Members
- Update request status (fulfilled / rejected) via AJAX, no page reload (
api/requests_update.php) - AJAX JSON response with inline badge update in the table
- No login required - any visitor is a Member
- Browse content by top-level category (Movies, Music, Software, eBooks, etc.)
- Filter by sub-category (e.g. Movies โ Action, Drama)
- AJAX live search - results appear as you type, with 350ms debounce (
api/search.php) - Download files โ PHP streams the file safely, the original file path is never exposed
- Download counter โ increments once per real download
- Content Request Box โ Members submit requests via AJAX form with instant feedback (
api/request_add.php)
| Feature | How it works |
|---|---|
| SQL Injection Prevention | Every query uses mysqli_prepare() with bound parameters โ no string-concatenated SQL |
| XSS Prevention | Every output is wrapped in htmlspecialchars() |
| CSRF Protection | Random 32-byte token per session, hidden field in every POST form, verified in every controller |
| Secure Passwords | password_hash(PASSWORD_BCRYPT) for storage, password_verify() for login |
| Remember Me Security | Plain token only in browser cookie. SHA-256 hash stored in DB. Stale cookies deleted immediately |
| File Upload Security | finfo_file() detects real MIME type. Extension whitelist check. Max 100 MB enforced |
| Upload Directory Protection | .htaccess blocks PHP execution inside /public/uploads/ |
| Role-Based Access Control | Every protected page checks $_SESSION['role'] at the top and redirects unauthorized users |
| Layer | Technology | Notes |
|---|---|---|
| Backend | PHP 8 (Procedural MVC) | No framework - plain PHP |
| Database | MySQL 5.7+ / MariaDB 10+ | All queries use prepared statements |
| Frontend | HTML5 + CSS3 (custom) | No CSS framework |
| JavaScript | Plain JS / XMLHttpRequest | No jQuery, React, or Vue |
| Authentication | PHP Sessions + Cookies | bcrypt + Remember Me token |
| File Detection | PHP fileinfo extension |
Server-side MIME check |
| Version Control | Git / GitHub | Feature branches + Pull Requests |
| Local Server | XAMPP / Apache | Development environment |
- Visit the home page - browse category tabs and featured content cards
- Click Browse to filter content by category and sub-category
- Click Search to find content by title or description (live, as you type)
- Click Download on any card to download the file
- Click Request Content to ask for something not yet in the library
- Log in โ land on the Moderator Dashboard
- Upload new media files with title, description, category, and file
- Delete files you uploaded yourself
- Open Requests - mark pending ones as Fulfilled or Rejected (updates live without page reload)
- Log in โ land on the Admin Dashboard with stat cards
- Click Refresh on the moderator quick-list to load it via AJAX
- Add or remove Moderators
- Upload, view, or delete any content
- Manage all content requests from Members
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
api/categories.php |
None | Returns all top-level categories |
GET |
api/admin_moderators.php |
Admin | Returns the full moderator list |
POST |
api/requests_update.php |
Admin / Mod | Updates a request's status |
GET |
api/search.php?q=keyword |
None | Returns matching content items |
POST |
api/request_add.php |
None | Saves a new content request |
All endpoints return Content-Type: application/json with a success field.
Example - GET api/search.php?q=inception:
{
"success": true,
"keyword": "inception",
"count": 1,
"results": [
{
"id": 5,
"title": "Inception (2010)",
"file_path": "1779034740_abc123.mkv",
"category_name": "Movies",
"download_count": 14
}
]
}After installation, check these:
- Home page loads and category tabs appear via AJAX
- Browse page shows content with category and sub-category filter tabs
- Search returns results as you type (live)
- Request form submits without page reload and shows success message
- Login works with
admin@ftp.local/password - Admin dashboard shows correct stat counts
- Moderator list loads on dashboard via the Refresh button (AJAX)
- File upload saves to
public/uploads/contents/and inserts a DB row - Download increments the counter by exactly 1 per click
- Deleting content removes both the DB row and the physical file
- Request Fulfill / Reject updates the badge without page reload (AJAX)
- Logout clears the session and cookie
- Remember Me auto-logs in on the next browser visit
- Email verification after registration, confirm account before it becomes active
- Category management UI - let Admins create, rename, and delete categories from a panel
- Content editing - change title, description, or category without re-uploading the file
- Pagination on content lists. Avoid loading everything at once
- File type filter on the search page filter by video, audio, PDF, etc.
- Request history for Members - show past requests using IP or a local cookie
- File preview - thumbnail or in-browser preview for images and PDFs
- Admin analytics - a simple chart showing downloads over time per category
- Two-factor login for Admin - extra security for the most powerful account
- Dark mode toggle - CSS custom properties are already in place, easy to add
- No framework - plain procedural PHP with a simple MVC pattern. No Laravel, CodeIgniter, or Symfony.
- No Composer - no external PHP packages. Only built-in PHP functions.
- No JS library - all AJAX uses native
XMLHttpRequest. No jQuery, React, or Vue. - All file paths use
__DIR__instead of relative strings like'/../'to avoid path issues on Windows vs Linux. - PHP sessions are file-based by default. If AJAX feels slow, consider calling
session_write_close()on pages before serving files.
This project was created as an academic group assignment for the Web Technologies course (CSE 4101) at American International University-Bangladesh (AIUB), Spring 2025โ2026.
It is shared here for educational reference only. You are welcome to study the code and learn from it. Please do not submit it as your own academic work.
This project covers the full life cycle of a real web application from user authentication and role-based access to file uploads, AJAX interactions, and database-driven content management. Each of the four team members built one self-contained module that connects to the shared database, making the whole system work together as one complete platform.
The code is kept simple and readable on purpose so anyone learning PHP, MySQL, and JavaScript can follow it without needing to know a framework. Every security measure CSRF tokens, bcrypt hashing, prepared statements, MIME validation, and HttpOnly cookies is built from scratch using only PHP's built-in tools.
Made with โค๏ธ by Team FTP โ AIUB Web Technologies Spring 2025โ2026