403Webshell
Server IP : 158.247.231.215  /  Your IP : 216.73.216.33
Web Server : Apache/2.4.41 (Ubuntu)
System : Linux CTMS 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64
User : www-data ( 33)
PHP Version : 8.0.30
Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /mnt/blockstorage/ctms/api/custom-api/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /mnt/blockstorage/ctms/api/custom-api/vr-content-update.php
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, PUT, OPTIONS');
header("Access-Control-Allow-Headers: X-Requested-With, Content-Type, Authorization");

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit();
}

// Load WordPress and auth helper
require_once('/mnt/blockstorage/ctms/wp-load.php');
require_once('auth-helper.php');

include('../database.php');

// Verify JWT token
$user_id = verify_jwt_token();

if (!$user_id) {
    send_error_response('User not authenticated', 401);
}

/**
 * Upload file for VR content
 */
function upload_vr_file($file, $content_id, $type = 'thumbnail', $index = null) {
    if (!isset($file) || $file['error'] !== UPLOAD_ERR_OK) {
        return array('success' => false, 'message' => 'File upload error: ' . $file['error']);
    }

    // Validate file type
    $allowed_types = array(
        'thumbnail' => array('image/jpeg', 'image/png', 'image/gif', 'image/webp'),
        'video' => array('video/mp4', 'video/webm', 'video/ogg', 'video/quicktime'),
        'gallery' => array('image/jpeg', 'image/png', 'image/gif', 'image/webp')
    );

    if (!isset($allowed_types[$type]) || !in_array($file['type'], $allowed_types[$type])) {
        return array('success' => false, 'message' => 'Invalid file type for ' . $type);
    }

    // Create directory for content
    $content_dir = '/mnt/blockstorage/ctms/vr-content-uploads/contents/' . $content_id;
    if (!file_exists($content_dir)) {
        mkdir($content_dir, 0755, true);
        chown($content_dir, 'www-data');
        chgrp($content_dir, 'www-data');
    }

    // Generate filename
    $extension = pathinfo($file['name'], PATHINFO_EXTENSION);
    if ($index !== null) {
        $filename = $type . '_' . $index . '_' . time() . '.' . $extension;
    } else {
        $filename = $type . '.' . $extension;
    }
    $file_path = $content_dir . '/' . $filename;

    // Delete old file if exists (only for single files like thumbnail/video)
    if ($index === null && file_exists($file_path)) {
        unlink($file_path);
    }

    // Move uploaded file
    if (!move_uploaded_file($file['tmp_name'], $file_path)) {
        return array('success' => false, 'message' => 'Failed to move uploaded file');
    }

    // Set permissions
    chmod($file_path, 0644);
    chown($file_path, 'www-data');
    chgrp($file_path, 'www-data');

    // Return relative path
    $relative_path = 'contents/' . $content_id . '/' . $filename;
    $url = 'https://training.contentsda.kr/vr-content-uploads/' . $relative_path;

    return array('success' => true, 'path' => $relative_path, 'url' => $url);
}

// Main processing
if ($_SERVER['REQUEST_METHOD'] === 'POST' || $_SERVER['REQUEST_METHOD'] === 'PUT') {
    try {
        $id = isset($_POST['id']) ? intval($_POST['id']) : 0;

        if ($id <= 0) {
            throw new Exception('Valid content ID is required');
        }

        // Check if content exists
        $check_sql = "SELECT * FROM vr_contents WHERE id = $id";
        $check_result = $conn->query($check_sql);

        if (!$check_result || $check_result->num_rows === 0) {
            throw new Exception('Content not found');
        }

        $existing = $check_result->fetch_assoc();

        // Prepare update data
        $update_parts = array();

        if (isset($_POST['title'])) {
            $title = $conn->real_escape_string(trim($_POST['title']));
            if (empty($title)) {
                throw new Exception('Title cannot be empty');
            }
            $update_parts[] = "title = '$title'";
        }

        if (isset($_POST['description'])) {
            $description = $conn->real_escape_string(trim($_POST['description']));
            $update_parts[] = "description = '$description'";
        }

        if (isset($_POST['status']) && in_array($_POST['status'], array('active', 'inactive'))) {
            $status = $_POST['status'];
            $update_parts[] = "status = '$status'";
        }

        // Handle thumbnail upload (save to vr_content_images table)
        if (isset($_FILES['thumbnail']) && $_FILES['thumbnail']['error'] === UPLOAD_ERR_OK) {
            $result = upload_vr_file($_FILES['thumbnail'], $id, 'thumbnail');
            if ($result['success']) {
                // Delete old thumbnail from vr_content_images
                $old_thumbnail_sql = "SELECT * FROM vr_content_images WHERE content_id = $id AND image_type = 'thumbnail'";
                $old_thumbnail_result = $conn->query($old_thumbnail_sql);
                if ($old_thumbnail_result && $old_thumbnail_result->num_rows > 0) {
                    $old_thumbnail = $old_thumbnail_result->fetch_assoc();
                    // Delete physical file
                    $old_file_path = '/mnt/blockstorage/ctms/vr-content-uploads/' . $old_thumbnail['image_path'];
                    if (file_exists($old_file_path)) {
                        unlink($old_file_path);
                    }
                    // Delete from database
                    $conn->query("DELETE FROM vr_content_images WHERE content_id = $id AND image_type = 'thumbnail'");
                }

                // Insert new thumbnail
                $image_path = $conn->real_escape_string($result['path']);
                $insert_sql = "INSERT INTO vr_content_images (content_id, image_path, image_type, display_order)
                               VALUES ($id, '$image_path', 'thumbnail', -1)";
                $conn->query($insert_sql);
                $update_parts[] = "updated_at = NOW()";
            }
        }

        // Handle video deletion
        if (isset($_POST['delete_video']) && ($_POST['delete_video'] === 'true' || $_POST['delete_video'] === '1')) {
            // Delete old video file
            if (!empty($existing['video_path'])) {
                $old_file_path = '/mnt/blockstorage/ctms/vr-content-uploads/' . $existing['video_path'];
                if (file_exists($old_file_path)) {
                    unlink($old_file_path);
                }
            }
            $update_parts[] = "video_path = NULL";
        }
        // Handle video upload
        else if (isset($_FILES['video']) && $_FILES['video']['error'] === UPLOAD_ERR_OK) {
            // Delete old video file before uploading new one
            if (!empty($existing['video_path'])) {
                $old_file_path = '/mnt/blockstorage/ctms/vr-content-uploads/' . $existing['video_path'];
                if (file_exists($old_file_path)) {
                    unlink($old_file_path);
                }
            }
            $result = upload_vr_file($_FILES['video'], $id, 'video');
            if ($result['success']) {
                $update_parts[] = "video_path = '" . $conn->real_escape_string($result['path']) . "'";
            }
        }

        // ========== Complete Gallery Image Management ==========
        // Handle existing images (deletion + reordering)
        $existing_images = null;
        $deleted_count = 0;
        $reordered_count = 0;

        // Get existing_images parameter (JSON format)
        if (isset($_POST['existing_images'])) {
            error_log("🔍 existing_images received: " . $_POST['existing_images']);
            // Remove escape slashes if present
            $existing_images_json = stripslashes($_POST['existing_images']);
            error_log("🔍 existing_images after stripslashes: " . $existing_images_json);
            $existing_images = json_decode($existing_images_json, true);
            error_log("🔍 existing_images decoded: " . print_r($existing_images, true));
            error_log("🔍 json_decode error: " . json_last_error_msg());
            error_log("🔍 is_array check: " . ($existing_images !== null ? "not null" : "null") . ", is_array: " . (is_array($existing_images) ? "true" : "false"));
        } else {
            error_log("⚠️ existing_images NOT received in POST");
        }

        if ($existing_images !== null && is_array($existing_images)) {
            // Start transaction for complex operations
            $conn->begin_transaction();

            try {
                // Get current images from DB
                $current_images_sql = "SELECT id, image_path FROM vr_content_images WHERE content_id = $id";
                $current_images_result = $conn->query($current_images_sql);
                $current_images = array();
                while ($row = $current_images_result->fetch_assoc()) {
                    $current_images[intval($row['id'])] = $row['image_path'];
                }
                error_log("🔍 Current images in DB: " . print_r(array_keys($current_images), true));

                // Extract IDs from existing_images
                $keep_ids = array();
                foreach ($existing_images as $img) {
                    if (isset($img['id'])) {
                        $keep_ids[] = intval($img['id']);
                    }
                }
                error_log("🔍 Keep IDs from existing_images: " . print_r($keep_ids, true));

                // Delete images not in the keep list
                foreach ($current_images as $img_id => $img_path) {
                    if (!in_array($img_id, $keep_ids)) {
                        error_log("🗑️ Deleting image ID: $img_id");
                        // Delete from database
                        $delete_sql = "DELETE FROM vr_content_images WHERE id = $img_id";
                        if ($conn->query($delete_sql) === TRUE) {
                            error_log("✅ Successfully deleted image ID $img_id from DB");
                            // Delete physical file
                            $full_path = '/mnt/blockstorage/ctms/vr-content-uploads/' . $img_path;
                            if (file_exists($full_path)) {
                                unlink($full_path);
                                error_log("✅ Successfully deleted file: $full_path");
                            } else {
                                error_log("⚠️ File not found: $full_path");
                            }
                            $deleted_count++;
                        } else {
                            error_log("❌ Failed to delete image ID $img_id: " . $conn->error);
                        }
                    }
                }

                // Update display_order for existing images
                foreach ($existing_images as $img) {
                    if (isset($img['id']) && isset($img['display_order'])) {
                        $img_id = intval($img['id']);
                        $display_order = intval($img['display_order']);

                        // Verify this image belongs to this content
                        if (isset($current_images[$img_id])) {
                            $update_order_sql = "UPDATE vr_content_images
                                               SET display_order = $display_order
                                               WHERE id = $img_id AND content_id = $id";
                            if ($conn->query($update_order_sql) === TRUE) {
                                $reordered_count++;
                            }
                        }
                    }
                }

                $conn->commit();
                $update_parts[] = "updated_at = NOW()"; // Force update timestamp

            } catch (Exception $e) {
                $conn->rollback();
                throw new Exception('Failed to manage existing images: ' . $e->getMessage());
            }
        }

        // Handle new gallery images (add new images)
        $gallery_images = array();
        if (isset($_FILES['images']) && is_array($_FILES['images']['tmp_name'])) {
            // Get current max display_order
            $max_order_sql = "SELECT MAX(display_order) as max_order FROM vr_content_images WHERE content_id = $id";
            $max_order_result = $conn->query($max_order_sql);
            $max_order = 0;
            if ($max_order_result && $max_order_result->num_rows > 0) {
                $row = $max_order_result->fetch_assoc();
                $max_order = intval($row['max_order']) + 1;
            }

            $file_count = count($_FILES['images']['tmp_name']);

            for ($i = 0; $i < $file_count; $i++) {
                // Skip if no file or error
                if (!isset($_FILES['images']['tmp_name'][$i]) || $_FILES['images']['error'][$i] !== UPLOAD_ERR_OK) {
                    continue;
                }

                // Prepare file array for upload_vr_file function
                $file = array(
                    'name' => $_FILES['images']['name'][$i],
                    'type' => $_FILES['images']['type'][$i],
                    'tmp_name' => $_FILES['images']['tmp_name'][$i],
                    'error' => $_FILES['images']['error'][$i],
                    'size' => $_FILES['images']['size'][$i]
                );

                $result = upload_vr_file($file, $id, 'gallery', $max_order + $i);

                if ($result['success']) {
                    // Insert into vr_content_images table
                    $image_path = $conn->real_escape_string($result['path']);
                    $display_order = $max_order + $i;
                    $insert_sql = "INSERT INTO vr_content_images (content_id, image_path, image_type, display_order)
                                   VALUES ($id, '$image_path', 'gallery', $display_order)";

                    if ($conn->query($insert_sql) === TRUE) {
                        $gallery_images[] = array(
                            'id' => $conn->insert_id,
                            'url' => $result['url'],
                            'display_order' => $display_order
                        );
                        $update_parts[] = "updated_at = NOW()"; // Force update timestamp
                    }
                } else {
                    error_log('Gallery image upload failed: ' . $result['message']);
                }
            }
        }

        if (empty($update_parts)) {
            throw new Exception('No data to update');
        }

        // Remove duplicate updated_at entries
        $update_parts = array_unique($update_parts);

        // Update content
        $update_sql = "UPDATE vr_contents SET " . implode(', ', $update_parts) . " WHERE id = $id";

        if ($conn->query($update_sql) !== TRUE) {
            throw new Exception('Failed to update content: ' . $conn->error);
        }

        // Get updated content
        $result = $conn->query("SELECT * FROM vr_contents WHERE id = $id");
        $updated = $result->fetch_assoc();

        $thumbnail_url = null;
        if ($updated['thumbnail_path']) {
            $thumbnail_url = 'https://training.contentsda.kr/vr-content-uploads/' . $updated['thumbnail_path'];
        }

        $video_url = null;
        if ($updated['video_path']) {
            $video_url = 'https://training.contentsda.kr/vr-content-uploads/' . $updated['video_path'];
        }

        // Get all gallery images
        $all_images_sql = "SELECT * FROM vr_content_images WHERE content_id = $id ORDER BY display_order";
        $all_images_result = $conn->query($all_images_sql);
        $all_gallery_images = array();
        while ($img_row = $all_images_result->fetch_assoc()) {
            $all_gallery_images[] = array(
                'id' => intval($img_row['id']),
                'url' => 'https://training.contentsda.kr/vr-content-uploads/' . $img_row['image_path'],
                'image_type' => $img_row['image_type'],
                'display_order' => intval($img_row['display_order'])
            );
        }

        $response = array(
            'status' => 'success',
            'message' => 'Content updated successfully',
            'data' => array(
                'id' => intval($updated['id']),
                'title' => $updated['title'],
                'description' => $updated['description'],
                'video_url' => $video_url,
                'all_images' => $all_gallery_images,
                'images_count' => count($all_gallery_images),
                'status' => $updated['status'],
                'updated_at' => $updated['updated_at'],
                'changes' => array(
                    'images_deleted' => $deleted_count,
                    'images_reordered' => $reordered_count,
                    'images_added' => count($gallery_images)
                )
            )
        );

        header('Content-Type: application/json');
        echo json_encode($response);

    } catch (Exception $e) {
        $response = array(
            'status' => 'error',
            'message' => $e->getMessage()
        );
        header('Content-Type: application/json');
        http_response_code(400);
        echo json_encode($response);
    }

    $conn->close();

} else {
    $response = array(
        'status' => 'error',
        'message' => 'Only POST or PUT requests are allowed'
    );
    header('Content-Type: application/json');
    http_response_code(405);
    echo json_encode($response);
}
?>

Youez - 2016 - github.com/yon3zu
LinuXploit