Merging 2.2.6 release candidate
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Ultra-Simple Profile Picture Management Script
|
||||
# Handles direct file uploads without base64 encoding
|
||||
# Author: dr-dolomite
|
||||
# Date: 2025-08-04
|
||||
|
||||
# Set content type and CORS headers
|
||||
echo "Content-Type: application/json"
|
||||
echo "Access-Control-Allow-Origin: *"
|
||||
echo "Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS"
|
||||
echo "Access-Control-Allow-Headers: Content-Type, Authorization"
|
||||
echo ""
|
||||
|
||||
# Configuration
|
||||
PROFILE_DIR="/www/assets/profile"
|
||||
PROFILE_IMAGE="$PROFILE_DIR/profile.jpg"
|
||||
TEMP_DIR="/tmp"
|
||||
LOG_FILE="/tmp/profile_picture.log"
|
||||
|
||||
# Logging function
|
||||
log_message() {
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
|
||||
}
|
||||
|
||||
# Error response function
|
||||
send_error() {
|
||||
local error_code="$1"
|
||||
local error_message="$2"
|
||||
log_message "ERROR: $error_message"
|
||||
echo "{\"status\":\"error\",\"code\":\"$error_code\",\"message\":\"$error_message\"}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Success response function
|
||||
send_success() {
|
||||
local message="$1"
|
||||
local data="$2"
|
||||
log_message "SUCCESS: $message"
|
||||
if [ -n "$data" ]; then
|
||||
echo "{\"status\":\"success\",\"message\":\"$message\",\"data\":$data}"
|
||||
else
|
||||
echo "{\"status\":\"success\",\"message\":\"$message\"}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Get file size
|
||||
get_file_size() {
|
||||
local file="$1"
|
||||
if [ -f "$file" ]; then
|
||||
stat -c%s "$file" 2>/dev/null || wc -c < "$file"
|
||||
else
|
||||
echo 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Create profile directory if it doesn't exist
|
||||
ensure_profile_directory() {
|
||||
if [ ! -d "$PROFILE_DIR" ]; then
|
||||
mkdir -p "$PROFILE_DIR"
|
||||
if [ $? -ne 0 ]; then
|
||||
send_error "DIRECTORY_ERROR" "Failed to create profile directory"
|
||||
fi
|
||||
chmod 755 "$PROFILE_DIR"
|
||||
log_message "Created profile directory: $PROFILE_DIR"
|
||||
fi
|
||||
}
|
||||
|
||||
# Handle GET request - Fetch profile picture
|
||||
handle_get() {
|
||||
log_message "GET request received"
|
||||
|
||||
if [ -f "$PROFILE_IMAGE" ]; then
|
||||
# Get file information
|
||||
local file_size=$(get_file_size "$PROFILE_IMAGE")
|
||||
local file_modified=$(stat -c %Y "$PROFILE_IMAGE" 2>/dev/null || echo "0")
|
||||
|
||||
# Return file information and base64 encoded image
|
||||
local base64_image=""
|
||||
if command -v base64 >/dev/null 2>&1; then
|
||||
base64_image=$(base64 -w 0 "$PROFILE_IMAGE" 2>/dev/null)
|
||||
elif command -v openssl >/dev/null 2>&1; then
|
||||
base64_image=$(openssl base64 -in "$PROFILE_IMAGE" | tr -d '\n' 2>/dev/null)
|
||||
elif command -v python3 >/dev/null 2>&1; then
|
||||
base64_image=$(python3 -c "
|
||||
import base64
|
||||
try:
|
||||
with open('$PROFILE_IMAGE', 'rb') as f:
|
||||
data = f.read()
|
||||
encoded = base64.b64encode(data).decode('ascii')
|
||||
print(encoded)
|
||||
except Exception as e:
|
||||
pass
|
||||
" 2>/dev/null)
|
||||
elif command -v busybox >/dev/null 2>&1; then
|
||||
base64_image=$(busybox base64 "$PROFILE_IMAGE" | tr -d '\n' 2>/dev/null)
|
||||
fi
|
||||
|
||||
if [ -n "$base64_image" ]; then
|
||||
local file_type=$(file -b --mime-type "$PROFILE_IMAGE" 2>/dev/null || echo "image/jpeg")
|
||||
send_success "Profile picture found" "{\"exists\":true,\"size\":$file_size,\"modified\":$file_modified,\"type\":\"$file_type\",\"data\":\"data:$file_type;base64,$base64_image\"}"
|
||||
else
|
||||
send_success "Profile picture found but could not encode" "{\"exists\":true,\"size\":$file_size,\"modified\":$file_modified,\"data\":null}"
|
||||
fi
|
||||
else
|
||||
log_message "No profile picture found"
|
||||
echo "{\"status\":\"error\",\"code\":\"NO_IMAGE_FOUND\",\"message\":\"No profile picture found\"}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Handle POST request - Direct file upload (no base64)
|
||||
handle_post() {
|
||||
log_message "POST request received"
|
||||
ensure_profile_directory
|
||||
|
||||
# Create temporary file with unique name
|
||||
local temp_file="$TEMP_DIR/profile_upload_$$"
|
||||
|
||||
log_message "Content-Type: ${CONTENT_TYPE:-unknown}"
|
||||
log_message "Content-Length: ${CONTENT_LENGTH:-unknown}"
|
||||
|
||||
# Read the raw uploaded file data directly to temp file
|
||||
cat > "$temp_file"
|
||||
|
||||
# Check if file was created and has content
|
||||
if [ ! -f "$temp_file" ]; then
|
||||
send_error "UPLOAD_ERROR" "Failed to receive uploaded file"
|
||||
fi
|
||||
|
||||
local temp_size=$(get_file_size "$temp_file")
|
||||
log_message "Received file size: $temp_size bytes"
|
||||
|
||||
if [ "$temp_size" -eq 0 ]; then
|
||||
rm -f "$temp_file"
|
||||
send_error "UPLOAD_ERROR" "Received empty file"
|
||||
fi
|
||||
|
||||
# Simply move the uploaded file to profile location (rename operation)
|
||||
if mv "$temp_file" "$PROFILE_IMAGE"; then
|
||||
chmod 644 "$PROFILE_IMAGE"
|
||||
local file_size=$(get_file_size "$PROFILE_IMAGE")
|
||||
log_message "Profile picture saved successfully, size: $file_size bytes"
|
||||
send_success "Profile picture uploaded successfully" "{\"size\":$file_size,\"path\":\"$PROFILE_IMAGE\"}"
|
||||
else
|
||||
rm -f "$temp_file"
|
||||
send_error "SAVE_ERROR" "Failed to save profile picture"
|
||||
fi
|
||||
}
|
||||
|
||||
# Handle DELETE request - Remove profile picture
|
||||
handle_delete() {
|
||||
log_message "DELETE request received"
|
||||
|
||||
if [ -f "$PROFILE_IMAGE" ]; then
|
||||
if rm "$PROFILE_IMAGE"; then
|
||||
send_success "Profile picture deleted successfully"
|
||||
else
|
||||
send_error "DELETE_ERROR" "Failed to delete profile picture"
|
||||
fi
|
||||
else
|
||||
send_error "NO_IMAGE_FOUND" "No profile picture found to delete"
|
||||
fi
|
||||
}
|
||||
|
||||
# Handle OPTIONS request for CORS preflight
|
||||
handle_options() {
|
||||
echo "Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS"
|
||||
echo "Access-Control-Allow-Headers: Content-Type, Authorization"
|
||||
echo "Access-Control-Max-Age: 86400"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Main execution
|
||||
log_message "Profile picture script called with method: ${REQUEST_METHOD:-GET}"
|
||||
|
||||
# Handle different HTTP methods
|
||||
case "${REQUEST_METHOD:-GET}" in
|
||||
GET)
|
||||
handle_get
|
||||
;;
|
||||
POST)
|
||||
handle_post
|
||||
;;
|
||||
DELETE)
|
||||
handle_delete
|
||||
;;
|
||||
OPTIONS)
|
||||
handle_options
|
||||
;;
|
||||
*)
|
||||
send_error "METHOD_NOT_ALLOWED" "HTTP method ${REQUEST_METHOD} not supported"
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user