Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Database Configuration
DB_HOST=mysql
DB_NAME=blog
DB_USER=bloguser
DB_PASSWORD=blogpassword

# Authentication Configuration
AUTH_USERNAME=roberto
# AUTH_PASSWORD is MD5 hash of the password
# Default: 3bc2e28ca8940090c3d80c851784a5d5 (MD5 of "password")
AUTH_PASSWORD=3bc2e28ca8940090c3d80c851784a5d5

# MySQL Root Password (for docker-compose)
MYSQL_ROOT_PASSWORD=rootpassword
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/vendor/
.env
composer.lock
.DS_Store
*.log
29 changes: 29 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FROM php:8.2-apache

# Install PDO MySQL extension
RUN docker-php-ext-install pdo pdo_mysql

# Enable Apache mod_rewrite
RUN a2enmod rewrite

# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Set working directory
WORKDIR /var/www/html

# Copy application files
COPY . /var/www/html/

# Install Composer dependencies
RUN composer install --no-dev --optimize-autoloader

# Set permissions
RUN chown -R www-data:www-data /var/www/html \
&& chmod -R 755 /var/www/html

# Expose port 80
EXPOSE 80

# Start Apache
CMD ["apache2-foreground"]
200 changes: 200 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
# PHPBlog - Modern PHP Blog Application

A modernized PHP blog application with secure database operations, session-based authentication, and Docker support.

## Features

- **Modern PHP**: Built with PHP 8.2+ and object-oriented architecture
- **Secure Database**: PDO with prepared statements to prevent SQL injection
- **Session Authentication**: Secure session-based user authentication
- **Environment Configuration**: Externalized configuration using environment variables
- **Docker Ready**: Complete Docker and docker-compose setup
- **Composer Integration**: PSR-4 autoloading for clean code organization

## Requirements

- PHP 8.0 or higher
- MySQL 8.0 or higher
- Composer
- Docker and Docker Compose (for containerized deployment)

## Quick Start with Docker

1. **Copy the environment file:**
```bash
cp .env.example .env
```

2. **Edit `.env` with your configuration** (optional, defaults work for development)

3. **Start the application:**
```bash
docker-compose up -d
```

4. **Access the blog:**
- Blog: http://localhost:8080
- Default credentials:
- Username: `roberto`
- Password: Check AUTH_PASSWORD in .env (default MD5 hash provided)

5. **Stop the application:**
```bash
docker-compose down
```

## Manual Installation

1. **Install dependencies:**
```bash
composer install
```

2. **Configure environment variables:**
```bash
cp .env.example .env
# Edit .env with your database credentials
```

3. **Create the database:**
```sql
CREATE DATABASE blog;
USE blog;
SOURCE init.sql;
```

4. **Configure your web server** to point to the phpblog directory

5. **Access the application** through your web server

## Environment Variables

All configuration is managed through environment variables:

| Variable | Description | Default |
|----------|-------------|---------|
| DB_HOST | Database host | localhost |
| DB_NAME | Database name | blog |
| DB_USER | Database user | root |
| DB_PASSWORD | Database password | (empty) |
| AUTH_USERNAME | Admin username | roberto |
| AUTH_PASSWORD | Admin password (MD5 hash) | 3bc2e28ca8940090c3d80c851784a5d5 |
| MYSQL_ROOT_PASSWORD | MySQL root password (Docker only) | rootpassword |

## Project Structure

```
phpblog/
├── admin/ # Admin panel pages
│ ├── add_new_post.php
│ ├── index.php
│ └── new_post.php
├── config/ # Configuration files
│ └── config.php
├── src/ # PHP classes (PSR-4)
│ ├── Database.php # PDO database wrapper
│ └── Posts.php # Post management
├── backend.php # Core backend logic
├── index.php # Public homepage
├── login.php # Login handler
├── logout.php # Logout handler
├── composer.json # Composer configuration
├── Dockerfile # Docker image definition
├── docker-compose.yml # Docker services definition
├── init.sql # Database initialization
└── .env.example # Environment template
```

## Usage

### Viewing Posts

Visit the homepage to see all published blog posts.

### Admin Access

1. Log in using the login form on the homepage
2. Default credentials: `roberto` / password (see .env for hash)
3. Access the admin panel to:
- View all posts
- Create new posts
- Manage content

### Adding a New Post

1. Log in to the admin panel
2. Click "New post"
3. Fill in the title and text
4. Submit the form

## Security Features

- **SQL Injection Protection**: All database queries use prepared statements
- **XSS Prevention**: All output is properly escaped with `htmlspecialchars()`
- **Session Security**: Secure session-based authentication with proper cleanup
- **Access Control**: Admin pages check for valid authentication
- **No Hardcoded Secrets**: All sensitive data in environment variables

## Modernization Details

This application has been modernized from legacy PHP code:

### Database Layer
- Replaced deprecated `mysql_*` functions with PDO
- Implemented prepared statements throughout
- Created Database class for connection management

### Authentication
- Migrated from cookie-based to session-based authentication
- Improved session security and cleanup

### Architecture
- Refactored from procedural to object-oriented code
- Implemented PSR-4 autoloading
- Separated concerns into logical classes

### Configuration
- Externalized all configuration to environment variables
- No hardcoded credentials in source code

### Deployment
- Added Docker support for easy deployment
- Created docker-compose setup for full stack

## Development

### Running Tests
```bash
# Add your tests here
```

### Building Docker Image
```bash
docker build -t phpblog:latest .
```

### Accessing Database
```bash
# Via docker-compose
docker-compose exec mysql mysql -u bloguser -p blog
```

## Troubleshooting

### Can't connect to database
- Check DB_HOST, DB_USER, DB_PASSWORD in .env
- Ensure MySQL is running
- Verify database and user exist

### Can't log in
- Check AUTH_USERNAME and AUTH_PASSWORD in .env
- AUTH_PASSWORD should be MD5 hash of your password
- Generate MD5: `echo -n "yourpassword" | md5sum`

### Permission errors
- Ensure web server has read access to all files
- Check Docker volume permissions if using containers

## License

This is a modernized version of the original phpblog application.
22 changes: 16 additions & 6 deletions admin/add_new_post.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
<?php
include_once "../backend.php";
session_start();

$title = $_POST['title'];
$text = $_POST['text'];
if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) {
echo "You shouldn't be here";
echo "<br/><a href='../index.php'>Go to index</a>";
exit;
}

echo $title;
echo $text;
add_new_post($title,$text);
include_once "../backend.php";

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['title']) && isset($_POST['text'])) {
$title = $_POST['title'];
$text = $_POST['text'];

add_new_post($title, $text);
} else {
echo "Invalid request";
}
?>
41 changes: 22 additions & 19 deletions admin/index.php
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
<?php

include_once "../backend.php";

if (!isset($_COOKIE['username'])) {
echo "You shouldn't be here";
}
session_start();

include_once "../backend.php";

if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) {
echo "You shouldn't be here";
echo "<br/><a href='../index.php'>Go to index</a>";
exit;
}
?>

<html>
<head>
</head>
<body>
<p>Welcome <?php echo $_COOKIE['username'];?> <a href='../index.php'>Go home</a></p>
<h1>Listing posts</h1>
<table border="0" cellspacing="5" cellpadding="5">
<tr><th>Title</th><th>Actions</th></tr>
<?php while ($row = mysql_fetch_assoc($result)) {
echo "<tr><td>".$row['title']."</td><td><a href=''>Edit</a> | <a href=''>Delete</a></tr>";
} ?>
</table>
<h1>Options</h1>
<a href='new_post.php'>New post</a><br/>
<a href='../logout.php'>Log out</a>
<p>Welcome <?php echo htmlspecialchars($_SESSION['username']);?> <a href='../index.php'>Go home</a></p>
<h1>Listing posts</h1>
<table border="0" cellspacing="5" cellpadding="5">
<tr><th>Title</th><th>Actions</th></tr>
<?php foreach ($result as $row) {
echo "<tr><td>" . htmlspecialchars($row['title']) . "</td><td><a href=''>Edit</a> | <a href=''>Delete</a></tr>";
} ?>
</table>
<h1>Options</h1>
<a href='new_post.php'>New post</a><br/>
<a href='../logout.php'>Log out</a>
</body>
21 changes: 15 additions & 6 deletions admin/new_post.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
<?php
session_start();

if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) {
echo "You shouldn't be here";
echo "<br/><a href='../index.php'>Go to index</a>";
exit;
}
?>
<html>
<head>
</head>
<body>
<h1>New Post</h1>
<form action="add_new_post.php" method="post">
<label for="title">Title:</label> <input type="text" name="title"></input><br/>
<label for="text">Text:</label> <textarea name="text" rows="8" cols="40"></textarea><br/>
<input type="submit"/>
</form>
<h1>New Post</h1>
<form action="add_new_post.php" method="post">
<label for="title">Title:</label> <input type="text" name="title"></input><br/>
<label for="text">Text:</label> <textarea name="text" rows="8" cols="40"></textarea><br/>
<input type="submit"/>
</form>
</body>
</html>
Loading