Skip to content

Commit 1cdae77

Browse files
authored
Merge pull request #22 from Darknetzz/dev
prep v1.5.0
2 parents f2ad324 + 5e8537d commit 1cdae77

File tree

12 files changed

+931
-192
lines changed

12 files changed

+931
-192
lines changed

.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ APP_NAME = "mp3-web"
33
AUTHOR = "Darknetzz"
44
URL = "https://github.com/Darknetzz/mp3-web"
55
ENV = "dev"
6-
VERSION = "v1.4.4"
6+
VERSION = "v1.5.0"

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ index_files
44
@eaDir
55
!config.php
66
config.*
7+
!config.default.php
78
.ht*
89
vendor
910
composer.lock
1011
deleted
1112
scripts
12-
session/*
13+
session/*
14+
debug.log

Dockerfile

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,43 @@
1-
FROM debian
2-
RUN apt-get -y update && apt-get -y install php8.2 php8.2-mbstring php8.2-curl apache2 libapache2-mod-php curl git
3-
RUN sed -i 's/^file_uploads = .*/file_uploads = On/' /etc/php/8.2/apache2/php.ini && \
4-
sed -i 's/^upload_max_filesize = .*/upload_max_filesize = 50M/' /etc/php/8.2/apache2/php.ini && \
5-
sed -i 's/^post_max_size = .*/post_max_size = 50M/' /etc/php/8.2/apache2/php.ini || \
6-
{ echo "file_uploads = On" >> /etc/php/8.2/apache2/php.ini; \
7-
echo "upload_max_filesize = 50M" >> /etc/php/8.2/apache2/php.ini; \
8-
echo "post_max_size = 50M" >> /etc/php/8.2/apache2/php.ini; }
9-
RUN rm -rf /var/www/html && \
10-
git clone https://github.com/Darknetzz/mp3-web.git /var/www/html && \
11-
cd /var/www/html && \
12-
git fetch origin && \
13-
git pull && \
14-
curl -sS https://getcomposer.org/installer -o composer-setup.php && \
15-
php composer-setup.php --install-dir=/usr/local/bin --filename=composer && \
16-
composer self-update && \
17-
composer install && \
18-
chown -R www-data:www-data /var/www/html && \
19-
a2enmod rewrite
20-
EXPOSE 80 443
21-
CMD ["apachectl", "-D", "FOREGROUND"]
1+
# Use official PHP (latest stable) with Apache (includes latest Apache 2.x)
2+
FROM php:8.3-apache
3+
4+
# Install system dependencies and common PHP extensions (adjust as needed)
5+
RUN apt-get update \
6+
&& apt-get install -y --no-install-recommends \
7+
libzip-dev libicu-dev libonig-dev libpng-dev libjpeg-dev libfreetype6-dev libxml2-dev git unzip curl git \
8+
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
9+
&& docker-php-ext-install -j$(nproc) pdo pdo_mysql mysqli intl zip gd opcache \
10+
&& a2enmod rewrite headers expires \
11+
&& rm -rf /var/lib/apt/lists/*
12+
13+
# Set recommended PHP settings (tune as necessary)
14+
RUN { \
15+
echo "memory_limit=256M"; \
16+
echo "upload_max_filesize=50M"; \
17+
echo "post_max_size=50M"; \
18+
echo "file_uploads = On"; \
19+
echo "max_execution_time=300"; \
20+
echo "date.timezone=UTC"; \
21+
echo "opcache.enable=1"; \
22+
echo "opcache.validate_timestamps=1"; \
23+
echo "opcache.max_accelerated_files=20000"; \
24+
} > /usr/local/etc/php/conf.d/custom.ini
25+
26+
RUN set -eux; \
27+
rm -rf /var/www/html/*; \
28+
git clone --depth=1 --branch main --recurse-submodules https://github.com/Darknetzz/mp3-web.git /var/www/html && \
29+
chown -R www-data:www-data /var/www/html
30+
31+
# Install composer (global)
32+
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
33+
RUN composer --version
34+
RUN composer install -d /var/www/html --no-dev --optimize-autoloader
35+
36+
# Set working directory
37+
WORKDIR /var/www/html
38+
39+
EXPOSE 80
40+
HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost/ || exit 1
41+
42+
# Default command (from base image)
43+
CMD ["apache2-foreground"]

IMPROVEMENTS.md

Lines changed: 301 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,301 @@
1+
# Codebase Improvements Recommendations
2+
3+
## 🔒 Security Issues
4+
5+
### 1. **Path Traversal Vulnerability in `remove()` function** (Critical)
6+
**Location:** `functions.php:205-222`
7+
8+
**Issue:** The function uses `urldecode()` on user input and concatenates it directly with the audio path without proper validation. This allows directory traversal attacks like `../../../etc/passwd`.
9+
10+
**Fix:**
11+
```php
12+
function remove($file) {
13+
$file = urldecode($file);
14+
$file = basename($file); // Prevent path traversal
15+
$audioPath = getConfig("audio_path");
16+
$filePath = realpath($audioPath . '/' . $file);
17+
$audioPathReal = realpath($audioPath);
18+
19+
// Verify file is within audio path directory
20+
if ($filePath === false || strpos($filePath, $audioPathReal) !== 0) {
21+
return apiResponse("error", "Invalid file path.");
22+
}
23+
// ... rest of function
24+
}
25+
```
26+
27+
### 2. **Missing Path Traversal Protection in `getDuration()`**
28+
**Location:** `functions.php:36-50`
29+
30+
**Issue:** Function accepts file paths without validation. Could be exploited if called with user-controlled input.
31+
32+
**Recommendation:** Add path validation or ensure it's only called with sanitized paths.
33+
34+
### 3. **XSS Vulnerability in HTML Output**
35+
**Location:** Multiple locations (e.g., `functions.php:213, 216, 322`)
36+
37+
**Issue:** Error messages containing user input are wrapped in `<code>` tags but user input isn't escaped before being inserted.
38+
39+
**Fix:** Use `htmlspecialchars()` on all user-provided values before output:
40+
```php
41+
return apiResponse("error", "The directory <code>".htmlspecialchars(CONFIG["audio_path"], ENT_QUOTES, 'UTF-8')."</code> is not writable.");
42+
```
43+
44+
### 4. **File Upload Security Enhancement**
45+
**Location:** `functions.php:319`
46+
47+
**Issue:** While `basename()` is used, the filename could still contain dangerous characters. Also, MIME type validation is missing.
48+
49+
**Recommendation:**
50+
- Validate MIME type against file extension
51+
- Sanitize filename more aggressively
52+
- Consider using a whitelist of allowed characters
53+
54+
### 5. **Missing Input Validation in API**
55+
**Location:** `api.php:32-34, 37-39, 87-89`
56+
57+
**Issue:** User input from `$_GET` and `$_POST` is used without validation or sanitization.
58+
59+
**Recommendation:** Add validation functions for all inputs.
60+
61+
## 🐛 Bug Fixes
62+
63+
### 6. **Logic Error in `getDuration()`**
64+
**Location:** `functions.php:41-43`
65+
66+
**Issue:** If file doesn't exist, the function sets `$duration` to an error message but continues execution, overwriting it on line 45.
67+
68+
**Fix:**
69+
```php
70+
if (!file_exists($file)) {
71+
return "File not found"; // or handle error appropriately
72+
}
73+
```
74+
75+
### 7. **Inconsistent Configuration Access**
76+
**Location:** Multiple files
77+
78+
**Issue:** Code mixes `CONFIG["key"]["value"]` and `getConfig("key")` patterns.
79+
80+
**Recommendation:** Standardize on `getConfig("key")` for consistency and better error handling.
81+
82+
### 8. **Missing Null Check in `joinSession()` and `createSession()`**
83+
**Location:** `api.php:82-89`
84+
85+
**Issue:** Functions are called without parameters but may need them. Missing validation.
86+
87+
### 9. **Unused Variable `$fileType`**
88+
**Location:** `functions.php:325`
89+
90+
**Issue:** Variable is defined but never used.
91+
92+
### 10. **Potential Issue in `saveConfig()` - Array Handling**
93+
**Location:** `functions.php:138`
94+
95+
**Issue:** Array values in config are concatenated without proper escaping for nested arrays or special characters.
96+
97+
## 💻 Code Quality Improvements
98+
99+
### 11. **Missing Type Declarations**
100+
**Recommendation:** Add type hints to all function parameters and return types for better IDE support and error detection:
101+
```php
102+
function getDuration(string $file): string
103+
function apiResponse(string $status, string $response, array $data = []): void
104+
```
105+
106+
### 12. **Code Duplication**
107+
**Location:** `functions.php:278-303`
108+
109+
**Issue:** The switch statement with `break;` after each `return` is redundant.
110+
111+
**Fix:** Remove unnecessary `break;` statements after `return`.
112+
113+
### 13. **Mixed Responsibilities**
114+
**Location:** `functions.php:225-252`
115+
116+
**Issue:** `listSongs()` generates HTML strings, mixing business logic with presentation.
117+
118+
**Recommendation:** Return data arrays only, move HTML generation to view layer.
119+
120+
### 14. **Hardcoded Permissions**
121+
**Location:** `functions.php:210, 379-380`
122+
123+
**Issue:** Using `0777` permissions is a security risk.
124+
125+
**Recommendation:** Use more restrictive permissions like `0755` or `0750`.
126+
127+
### 15. **Global State Usage**
128+
**Location:** `functions.php:346, 391`
129+
130+
**Issue:** Functions use `global $_SESSION` instead of proper dependency injection.
131+
132+
**Recommendation:** Consider passing session data as parameters or using a session handler class.
133+
134+
### 16. **Inconsistent String Concatenation**
135+
**Location:** Throughout codebase
136+
137+
**Issue:** Mix of string concatenation with `.` and interpolation.
138+
139+
**Recommendation:** Standardize on one approach (preferably interpolation for readability).
140+
141+
### 17. **Missing Error Handling**
142+
**Location:** `functions.php:44`
143+
144+
**Issue:** `Mp3Info` constructor could throw exceptions, but they're not caught.
145+
146+
**Recommendation:**
147+
```php
148+
try {
149+
$mp3info = new wapmorgan\Mp3Info\Mp3Info($file);
150+
$duration = $mp3info->duration;
151+
} catch (Exception $e) {
152+
return "0:00"; // or log error
153+
}
154+
```
155+
156+
## ⚡ Performance Improvements
157+
158+
### 18. **Inefficient File Operations**
159+
**Location:** `functions.php:231-251`
160+
161+
**Issue:** `getDuration()` is called for every file in a loop, which involves file I/O and MP3 parsing.
162+
163+
**Recommendation:**
164+
- Cache duration values
165+
- Process files in batches
166+
- Consider storing metadata in a database
167+
168+
### 19. **Redundant Array Operations**
169+
**Location:** `functions.php:231`
170+
171+
**Issue:** `array_diff(scandir(...), array('..', '.'))` creates intermediate arrays.
172+
173+
**Recommendation:** Use `array_filter` or directory iterator with filtering.
174+
175+
### 20. **No Caching**
176+
**Recommendation:** Implement caching for:
177+
- Configuration values
178+
- File listings
179+
- MP3 duration metadata
180+
181+
## 🏗️ Architecture Improvements
182+
183+
### 21. **Separation of Concerns**
184+
**Recommendation:**
185+
- Create separate classes for:
186+
- Configuration management
187+
- File operations
188+
- Session management
189+
- HTML rendering
190+
191+
### 22. **API Response Wrapper**
192+
**Location:** `api.php:94-100`
193+
194+
**Issue:** The response handling is confusing - calling `apiResponse()` twice.
195+
196+
**Recommendation:** Refactor to have a single, consistent response pattern.
197+
198+
### 23. **Error Handling Strategy**
199+
**Recommendation:**
200+
- Implement proper exception handling
201+
- Add logging mechanism
202+
- Create error codes/enums instead of strings
203+
204+
### 24. **Configuration Management**
205+
**Recommendation:**
206+
- Use a configuration class instead of global arrays
207+
- Implement validation for configuration values
208+
- Add type checking for config values
209+
210+
### 25. **Dependency Injection**
211+
**Recommendation:** Instead of global functions, use classes with dependency injection for better testability.
212+
213+
## 📝 Documentation
214+
215+
### 26. **Missing PHPDoc Comments**
216+
**Recommendation:** Add PHPDoc comments to all functions:
217+
```php
218+
/**
219+
* Gets the duration of an MP3 file
220+
*
221+
* @param string $file Path to the MP3 file
222+
* @return string Duration in format "M:SS" or "0:00" on error
223+
* @throws Exception If file cannot be read
224+
*/
225+
```
226+
227+
### 27. **Code Comments**
228+
**Recommendation:** Add inline comments explaining complex logic and business rules.
229+
230+
## 🔧 Additional Recommendations
231+
232+
### 28. **Add Unit Tests**
233+
**Recommendation:** Create unit tests for critical functions, especially:
234+
- File upload validation
235+
- Path sanitization
236+
- Configuration management
237+
238+
### 29. **Environment-Specific Configuration**
239+
**Recommendation:** Ensure sensitive data (paths, permissions) are environment-specific and not hardcoded.
240+
241+
### 30. **Add Input Sanitization Helper**
242+
**Recommendation:** Create helper functions:
243+
```php
244+
function sanitizePath(string $path): string
245+
function sanitizeFilename(string $filename): string
246+
function validateFileExtension(string $file, array $allowed): bool
247+
```
248+
249+
### 31. **CSRF Protection**
250+
**Recommendation:** Add CSRF tokens for state-changing operations (upload, delete, config changes).
251+
252+
### 32. **Rate Limiting**
253+
**Recommendation:** Implement rate limiting for API endpoints to prevent abuse.
254+
255+
### 33. **Logging**
256+
**Recommendation:** Add proper logging for:
257+
- File operations
258+
- Configuration changes
259+
- Errors and exceptions
260+
- Security events
261+
262+
### 34. **Constants Instead of Magic Strings**
263+
**Location:** Throughout codebase
264+
265+
**Recommendation:** Define constants for:
266+
- Action names
267+
- Error messages
268+
- File paths
269+
270+
### 35. **Remove Dead Code**
271+
**Location:** `functions.php:190-202`
272+
273+
**Issue:** Commented out `download()` function.
274+
275+
**Recommendation:** Remove or implement.
276+
277+
---
278+
279+
## Priority Summary
280+
281+
**Critical (Fix Immediately):**
282+
- #1 Path Traversal in `remove()`
283+
- #3 XSS vulnerabilities
284+
- #4 File upload security
285+
286+
**High Priority:**
287+
- #6 Logic error in `getDuration()`
288+
- #11 Type declarations
289+
- #17 Exception handling
290+
- #21 Separation of concerns
291+
292+
**Medium Priority:**
293+
- #7 Configuration consistency
294+
- #13 Mixed responsibilities
295+
- #18 Performance optimizations
296+
- #22 API response handling
297+
298+
**Low Priority:**
299+
- #12 Code cleanup (redundant breaks)
300+
- #26 Documentation
301+
- #34 Constants

0 commit comments

Comments
 (0)