FILE 1: /home/personalized-award-certificates.digitalprank.com/public_html/tool_config.json code JSON { "tool": { "identity": { "slug": "personalized-award-certificates", "name": "Personalized Award Certificates", "category": "prank", "tagline": "Create hilarious, realistic-looking custom awards in seconds!", "description": "Design and download custom award certificates for pranks, jokes, or lighthearted recognition. Choose from stylish templates, enter names and titles, and instantly get a downloadable award.", "keywords": ["custom certificate", "award generator", "funny awards", "joke certificate", "digital prank"] }, "features": { "bulk_enabled": false, "history_enabled": true, "export_enabled": true, "api_enabled": false }, "fields": [ { "id": "recipient_name", "type": "text", "label": "Recipient Name", "placeholder": "e.g., John Smith", "required": true, "validation": { "pattern": "^[a-zA-Z0-9\\s.'-]{3,60}$", "min_length": 3, "max_length": 60 }, "pro_only": false, "help_text": "Enter the name of the person receiving the award." }, { "id": "award_title", "type": "text", "label": "Award Title", "placeholder": "e.g., World's Best Dad", "required": true, "validation": { "pattern": "^.{5,100}$", "min_length": 5, "max_length": 100 }, "pro_only": false, "help_text": "Describe the award — make it funny, formal, or absurd!" }, { "id": "issuer_name", "type": "text", "label": "Presented By", "placeholder": "e.g., The Office of Totally Made-Up Achievements", "required": false, "pro_only": false, "help_text": "Optional: who is presenting this award?" }, { "id": "award_date", "type": "date", "label": "Date of Award", "required": false, "pro_only": false, "help_text": "Leave blank to use today’s date." }, { "id": "template_style", "type": "select", "label": "Certificate Style", "default": "classic_gold", "options": [ { "value": "classic_gold", "label": "Classic Gold Frame" }, { "value": "modern_blue", "label": "Modern Blue Border" }, { "value": "funny_cartoon", "label": "Funny Cartoon Style" }, { "value": "elegant_scroll", "label": "Elegant Scrollwork (Pro)" }, { "value": "dark_mode", "label": "Dark Mode (Pro)" } ], "pro_only": false, "help_text": "Choose the design layout for your certificate." }, { "id": "signature_image", "type": "file", "label": "Signature Image (Optional)", "required": false, "pro_only": true, "help_text": "Upload a signature to appear on the certificate. PNG recommended." }, { "id": "custom_logo", "type": "file", "label": "Custom Logo or Seal", "required": false, "pro_only": true, "help_text": "Upload your own logo or seal. PNG with transparency works best." }, { "id": "download_format", "type": "select", "label": "Download Format", "default": "png", "options": [ { "value": "png", "label": "Standard PNG" }, { "value": "pdf", "label": "High-Quality PDF (Pro)" } ], "pro_only": false, "help_text": "Choose the format you want to export the certificate in." } ], "limits": { "tier_daily": { "free": 3, "basic": 25, "gold": 200, "ultimate": -1 }, "rate_limit_per_minute": 5, "max_concurrent_requests": 2 }, "billing": { "credit_cost": 1, "one_off_enabled": true, "one_off_price_cents": 149, "bill_on": "success" }, "ui": { "theme": { "primary_color": "#0077CC", "secondary_color": "#f3f3f3" }, "layout": { "show_sidebar_ads": true, "form_style": "stepper", "result_display": "inline" } }, "dependencies": { "php_extensions": ["gd", "mbstring", "json", "imagick"], "system_packages": ["imagemagick", "ghostscript"], "python_packages": ["reportlab", "pillow"], "external_apis": [], "requires_internet": false }, "database": { "tool_specific_table": "award_certificate_history", "store_results": true, "enable_history": true, "retention_days": 90 }, "seo": { "meta_title": "Custom Award Certificate Generator | Make Funny Awards | DigitalPrank.com", "meta_description": "Create custom award certificates instantly! Customize recipient name, award title, date, and design. Download hilarious custom awards for free or upgrade for more options.", "canonical_url": "https://digitalprank.com/tools/personalized-award-certificates", "structured_data": { "type": "WebApplication", "category": "Entertainment" } }, "help": { "quick_start": [ "Step 1: Enter the name and award title.", "Step 2: Pick a template and optional extras.", "Step 3: Click 'Generate Certificate'.", "Step 4: Download and share your masterpiece!" ], "faq": [ { "question": "Can I print these certificates?", "answer": "Absolutely! They're high-resolution and print-ready." }, { "question": "Can I use my own logo?", "answer": "Yes, Pro users can upload a custom logo or seal." } ], "examples": [ { "title": "Most Likely to Be Late", "description": "A lighthearted office gag award.", "input": { "recipient_name": "Jason Reynolds", "award_title": "Most Likely to Show Up Late and Blame Traffic", "template_style": "funny_cartoon" } }, { "title": "World’s Best Cat Dad", "description": "A perfect gift for pet lovers.", "input": { "recipient_name": "Alex Moreno", "award_title": "World's Best Cat Dad", "template_style": "classic_gold" } } ] }, "monitoring": { "track_usage": true, "track_performance": true, "error_reporting": true, "analytics_events": [ "certificate_generated", "pro_upgrade", "download_clicked" ] }, "security": { "input_sanitization": true, "csrf_protection": true, "rate_limiting": true, "blocked_domains": [], "max_input_length": 500, "allowed_file_types": ["png", "jpg", "webp"] }, "version": { "schema": "3.0.0", "tool": "1.0.0", "api_version": "v1" } } } FILE 2: /home/personalized-award-certificates.digitalprank.com/public_html/processor.php code PHP setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); } catch (PDOException $e) { http_response_code(500); echo json_encode(['success' => false, 'message' => 'Database connection failed. Please try again later.']); exit; } // --- LOAD CONFIG --- $TOOL_SLUG = "personalized-award-certificates"; $config_path = __DIR__ . '/tool_config.json'; if (!file_exists($config_path)) { http_response_code(500); echo json_encode(['success' => false, 'message' => 'Configuration file is missing.']); exit; } $config = json_decode(file_get_contents($config_path), true); if (json_last_error() !== JSON_ERROR_NONE) { http_response_code(500); echo json_encode(['success' => false, 'message' => 'Invalid configuration file.']); exit; } // --- UNIVERSAL FUNCTIONS --- require_once '/home/cdn.digitalprank.com/public_html/php/universal_functions.php'; // --- INITIALIZE RESPONSE --- $response = [ 'success' => false, 'message' => 'An unknown error occurred.', 'data' => null, 'usage' => ['limit' => 0, 'remaining' => 0], 'access' => ['tier' => 'free', 'has_pro_access' => false], 'features' => $config['tool']['features'] ]; // --- MAIN PROCESSING LOGIC --- $startTime = microtime(true); // --- User and Input --- $user_id = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0; $user_ip = $_SERVER['REMOTE_ADDR']; $input = $_POST; $files = $_FILES; // --- Security: CSRF Check --- if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) { http_response_code(403); $response['message'] = 'Invalid session token. Please refresh the page.'; logUsage($pdo, $TOOL_SLUG, $user_ip, $user_id, 'csrf_fail', json_encode($input), null, 0); echo json_encode($response); exit; } // --- Access Level & Rate Limiting --- $access = getUserAccessLevel($pdo, $user_id, $TOOL_SLUG); $response['access'] = $access; $daily_limit = $config['tool']['limits']['tier_daily'][$access['tier']]; $response['usage']['limit'] = $daily_limit; if (!checkDailyUsage($pdo, $TOOL_SLUG, $user_ip, $user_id, $daily_limit)) { http_response_code(429); $response['message'] = 'You have exceeded your daily usage limit for this tool.'; logUsage($pdo, $TOOL_SLUG, $user_ip, $user_id, 'limit_exceeded', json_encode($input), null, 0); echo json_encode($response); exit; } // --- Database Overrides for Field Access --- $overrides = getToolOverrides($pdo, $TOOL_SLUG); // {{TOOL_PROCESSING_START}} function validate_input($input, $field_config) { if ($field_config['required'] && empty($input)) { return "{$field_config['label']} is required."; } if (!empty($input)) { if (isset($field_config['validation']['min_length']) && mb_strlen($input) < $field_config['validation']['min_length']) { return "{$field_config['label']} must be at least {$field_config['validation']['min_length']} characters."; } if (isset($field_config['validation']['max_length']) && mb_strlen($input) > $field_config['validation']['max_length']) { return "{$field_config['label']} must be no more than {$field_config['validation']['max_length']} characters."; } if (isset($field_config['validation']['pattern']) && !preg_match("/{$field_config['validation']['pattern']}/", $input)) { return "Invalid format for {$field_config['label']}."; } } return null; } function get_field_config($fields, $id) { foreach ($fields as $field) { if ($field['id'] === $id) { return $field; } } return null; } try { // --- Input Validation --- $errors = []; foreach ($config['tool']['fields'] as $field) { if ($field['type'] !== 'file') { $value = isset($input[$field['id']]) ? trim($input[$field['id']]) : ''; $error = validate_input($value, $field); if ($error) { $errors[] = $error; } } } if (!empty($errors)) { throw new Exception(implode(' ', $errors)); } // --- Sanitize Inputs --- $recipient_name = htmlspecialchars($input['recipient_name'], ENT_QUOTES, 'UTF-8'); $award_title = htmlspecialchars($input['award_title'], ENT_QUOTES, 'UTF-8'); $issuer_name = isset($input['issuer_name']) ? htmlspecialchars($input['issuer_name'], ENT_QUOTES, 'UTF-8') : 'DigitalPrank.com'; $award_date_str = !empty($input['award_date']) ? $input['award_date'] : date('Y-m-d'); $award_date = date('F jS, Y', strtotime($award_date_str)); $template_style = $input['template_style']; $download_format = $input['download_format']; // --- Permission Checks for Pro Features --- if ($download_format === 'pdf' && !$access['has_pro_access']) { throw new Exception("High-Quality PDF is a Pro feature. Please upgrade your account."); } $pro_templates = ['elegant_scroll', 'dark_mode']; if (in_array($template_style, $pro_templates) && !$access['has_pro_access']) { throw new Exception("This certificate style is a Pro feature. Please upgrade your account."); } if (!empty($files['signature_image']['tmp_name']) && !$access['has_pro_access']) { throw new Exception("Uploading a signature is a Pro feature. Please upgrade your account."); } if (!empty($files['custom_logo']['tmp_name']) && !$access['has_pro_access']) { throw new Exception("Uploading a custom logo is a Pro feature. Please upgrade your account."); } // --- File Upload Handling & Validation (Pro Only) --- $signature_path = null; $logo_path = null; $allowed_types = ['image/png', 'image/jpeg', 'image/webp']; if ($access['has_pro_access']) { if (isset($files['signature_image']) && $files['signature_image']['error'] === UPLOAD_ERR_OK) { if (in_array($files['signature_image']['type'], $allowed_types) && $files['signature_image']['size'] < 2000000) { $signature_path = $files['signature_image']['tmp_name']; } else { throw new Exception('Invalid signature file. Must be PNG, JPG, or WEBP under 2MB.'); } } if (isset($files['custom_logo']) && $files['custom_logo']['error'] === UPLOAD_ERR_OK) { if (in_array($files['custom_logo']['type'], $allowed_types) && $files['custom_logo']['size'] < 2000000) { $logo_path = $files['custom_logo']['tmp_name']; } else { throw new Exception('Invalid logo file. Must be PNG, JPG, or WEBP under 2MB.'); } } } // --- Image Generation using Imagick --- $template_path = __DIR__ . "/assets/templates/{$template_style}.png"; if (!file_exists($template_path)) { throw new Exception("Certificate template '{$template_style}' not found."); } $image = new Imagick($template_path); $image->setImageFormat('png'); // --- Define Template Layouts (Coordinates, Fonts, Sizes) --- // NOTE: These are example coordinates and would need to be fine-tuned for real templates. // Assumes 1200x849 pixel templates. Font paths assume standard Linux locations. $font_main = '/usr/share/fonts/truetype/dejavu/DejaVuSerif-Bold.ttf'; $font_body = '/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf'; if(!file_exists($font_main)) $font_main = '/usr/share/fonts/liberation/LiberationSerif-Bold.ttf'; // Fallback if(!file_exists($font_body)) $font_body = '/usr/share/fonts/liberation/LiberationSerif-Regular.ttf'; // Fallback $layouts = [ 'classic_gold' => [ 'recipient' => ['y' => 400, 'font' => $font_main, 'size' => 60, 'color' => '#2c3e50'], 'title' => ['y' => 500, 'font' => $font_body, 'size' => 32, 'color' => '#34495e'], 'issuer' => ['y' => 650, 'font' => $font_body, 'size' => 24, 'color' => '#34495e'], 'date' => ['y' => 650, 'font' => $font_body, 'size' => 24, 'color' => '#34495e'], 'logo' => ['x' => 1050, 'y' => 600, 'w' => 120, 'h' => 120], 'signature' => ['x' => 200, 'y' => 600, 'w' => 150, 'h' => 75] ], 'modern_blue' => [ 'recipient' => ['y' => 420, 'font' => $font_main, 'size' => 55, 'color' => '#003366'], 'title' => ['y' => 510, 'font' => $font_body, 'size' => 30, 'color' => '#0055a4'], 'issuer' => ['y' => 660, 'font' => $font_body, 'size' => 22, 'color' => '#333333'], 'date' => ['y' => 660, 'font' => $font_body, 'size' => 22, 'color' => '#333333'], 'logo' => ['x' => 1050, 'y' => 610, 'w' => 110, 'h' => 110], 'signature' => ['x' => 200, 'y' => 610, 'w' => 150, 'h' => 75] ], 'funny_cartoon' => [ 'recipient' => ['y' => 410, 'font' => '/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf', 'size' => 65, 'color' => '#e74c3c'], 'title' => ['y' => 520, 'font' => '/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf', 'size' => 35, 'color' => '#2c3e50'], 'issuer' => ['y' => 670, 'font' => '/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf', 'size' => 20, 'color' => '#34495e'], 'date' => ['y' => 670, 'font' => '/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf', 'size' => 20, 'color' => '#34495e'], 'logo' => ['x' => 1040, 'y' => 620, 'w' => 120, 'h' => 120], 'signature' => ['x' => 210, 'y' => 620, 'w' => 150, 'h' => 75] ], // Pro templates 'elegant_scroll' => [ 'recipient' => ['y' => 415, 'font' => $font_main, 'size' => 58, 'color' => '#6a4a2f'], 'title' => ['y' => 515, 'font' => $font_body, 'size' => 30, 'color' => '#8b6b4f'], 'issuer' => ['y' => 655, 'font' => $font_body, 'size' => 23, 'color' => '#6a4a2f'], 'date' => ['y' => 655, 'font' => $font_body, 'size' => 23, 'color' => '#6a4a2f'], 'logo' => ['x' => 1050, 'y' => 605, 'w' => 115, 'h' => 115], 'signature' => ['x' => 200, 'y' => 605, 'w' => 150, 'h' => 75] ], 'dark_mode' => [ 'recipient' => ['y' => 400, 'font' => $font_main, 'size' => 60, 'color' => '#ecf0f1'], 'title' => ['y' => 500, 'font' => $font_body, 'size' => 32, 'color' => '#bdc3c7'], 'issuer' => ['y' => 650, 'font' => $font_body, 'size' => 24, 'color' => '#bdc3c7'], 'date' => ['y' => 650, 'font' => $font_body, 'size' => 24, 'color' => '#bdc3c7'], 'logo' => ['x' => 1050, 'y' => 600, 'w' => 120, 'h' => 120], 'signature' => ['x' => 200, 'y' => 600, 'w' => 150, 'h' => 75] ], ]; $layout = $layouts[$template_style]; // --- Draw Text --- $draw = new ImagickDraw(); $draw->setGravity(Imagick::GRAVITY_NORTH); // Center horizontally // Recipient Name $draw->setFont($layout['recipient']['font']); $draw->setFontSize($layout['recipient']['size']); $draw->setFillColor($layout['recipient']['color']); $image->annotateImage($draw, 0, $layout['recipient']['y'], 0, $recipient_name); // Award Title $draw->setFont($layout['title']['font']); $draw->setFontSize($layout['title']['size']); $draw->setFillColor($layout['title']['color']); // Word wrap for long titles $metrics = $image->queryFontMetrics($draw, $award_title); if ($metrics['textWidth'] > 900) { // 900px max width $wrapped_title = wordwrap($award_title, 40, "\n"); $image->annotateImage($draw, 0, $layout['title']['y'], 0, $wrapped_title); } else { $image->annotateImage($draw, 0, $layout['title']['y'], 0, $award_title); } // Issuer and Date $draw->setFont($layout['issuer']['font']); $draw->setFontSize($layout['issuer']['size']); $draw->setFillColor($layout['issuer']['color']); $draw->setGravity(Imagick::GRAVITY_SOUTHWEST); $image->annotateImage($draw, 150, 150, 0, $issuer_name); $draw->setGravity(Imagick::GRAVITY_SOUTHEAST); $image->annotateImage($draw, 150, 150, 0, $award_date); // --- Add Signature & Logo (Pro Only) --- if ($signature_path) { $signature = new Imagick($signature_path); $signature->resizeImage($layout['signature']['w'], $layout['signature']['h'], Imagick::FILTER_LANCZOS, 1, true); $image->compositeImage($signature, Imagick::COMPOSITE_OVER, $layout['signature']['x'], $layout['signature']['y']); $signature->destroy(); } if ($logo_path) { $logo = new Imagick($logo_path); $logo->resizeImage($layout['logo']['w'], $layout['logo']['h'], Imagick::FILTER_LANCZOS, 1, true); $image->compositeImage($logo, Imagick::COMPOSITE_OVER, $layout['logo']['x'], $layout['logo']['y']); $logo->destroy(); } // --- Save File --- $output_dir = __DIR__ . '/output'; if (!is_dir($output_dir)) { mkdir($output_dir, 0755, true); } $filename = uniqid('cert_', true); if ($download_format === 'pdf') { $image->setImageFormat('pdf'); $filepath = $output_dir . '/' . $filename . '.pdf'; } else { $image->setImageFormat('png'); $filepath = $output_dir . '/' . $filename . '.png'; } $image->writeImage($filepath); $image->destroy(); $file_url = "https://{$_SERVER['HTTP_HOST']}/output/{$filename}.{$download_format}"; // --- Store in History Table --- if ($config['tool']['database']['store_results']) { $sql = "INSERT INTO award_certificate_history (user_id, recipient_name, award_title, issuer_name, award_date, template_style, file_path, download_format) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; $stmt = $pdo->prepare($sql); $stmt->execute([$user_id, $recipient_name, $award_title, $issuer_name, $award_date_str, $template_style, $filepath, $download_format]); } $response['success'] = true; $response['message'] = 'Certificate generated successfully!'; $response['data'] = ['file_url' => $file_url, 'format' => $download_format]; } catch (Exception $e) { http_response_code(400); $response['message'] = $e->getMessage(); logUsage($pdo, $TOOL_SLUG, $user_ip, $user_id, 'processing_error', json_encode($input), json_encode(['error' => $e->getMessage()]), microtime(true) - $startTime); echo json_encode($response); exit; } // {{TOOL_PROCESSING_END}} // --- Finalize and Log --- $processing_time = microtime(true) - $startTime; if ($response['success']) { logUsage($pdo, $TOOL_SLUG, $user_ip, $user_id, 'success', json_encode($input), json_encode($response['data']), $processing_time, 1); $response['usage']['remaining'] = $daily_limit - getTodaysUsage($pdo, $TOOL_SLUG, $user_ip, $user_id); } else { logUsage($pdo, $TOOL_SLUG, $user_ip, $user_id, 'failed', json_encode($input), json_encode(['message' => $response['message']]), $processing_time); $response['usage']['remaining'] = $daily_limit - getTodaysUsage($pdo, $TOOL_SLUG, $user_ip, $user_id); } // --- Output Response --- echo json_encode($response); ?> FILE 3: /home/personalized-award-certificates.digitalprank.com/public_html/tool_form.php code PHP <?php echo htmlspecialchars($tool_name); ?> - DigitalPrank

"; break; case 'select': echo ""; break; case 'file': $allowed_types = implode(', ', $config['tool']['security']['allowed_file_types']); echo ""; break; } ?>

FILE 4: /home/personalized-award-certificates.digitalprank.com/public_html/diagnostic.php code PHP 403 Forbidden

Access denied.

'); } ini_set('display_errors', 1); error_reporting(E_ALL); function check_status($condition, $success_msg = 'OK', $fail_msg = 'FAIL') { if ($condition) { return "{$success_msg}"; } return "{$fail_msg}"; } function check_shell_command($command) { if (!function_exists('shell_exec')) { return false; } $path = trim(shell_exec("which $command")); return !empty($path) && is_executable(trim($path)); } $results = []; // 1. Configuration File Validation $config_path = __DIR__ . '/tool_config.json'; $results['config_file']['File Exists'] = file_exists($config_path); $config_content = file_get_contents($config_path); $config = json_decode($config_content, true); $results['config_file']['JSON Valid'] = json_last_error() === JSON_ERROR_NONE; $results['config_file']['Identity Section Exists'] = isset($config['tool']['identity']); $results['config_file']['Fields Section Exists'] = isset($config['tool']['fields']); $results['config_file']['Dependencies Section Exists'] = isset($config['tool']['dependencies']); // 2. Database Connectivity $db_host = 'localhost'; $db_name = 'digitalprank_db'; $db_user = 'dp_user'; $db_pass = '#$Dealer2355'; $pdo = null; $db_error = ''; try { $pdo = new PDO("mysql:host=$db_host;dbname=$db_name;charset=utf8mb4", $db_user, $db_pass); $results['database']['Connection'] = true; } catch (PDOException $e) { $results['database']['Connection'] = false; $db_error = $e->getMessage(); } // 3. Required Tables Check if ($pdo) { $required_tables = [ 'wp_digitalprank_tools', 'wp_digitalprank_usage', 'wp_digitalprank_usage_log', 'wp_pms_member_subscriptions', 'wp_digitalprank_entitlements', 'wp_digitalprank_tool_overrides', $config['tool']['database']['tool_specific_table'] ?? 'award_certificate_history' ]; foreach ($required_tables as $table) { try { $result = $pdo->query("SELECT 1 FROM {$table} LIMIT 1"); $results['database_tables'][$table] = (bool)$result; } catch (Exception $e) { $results['database_tables'][$table] = false; } } } // 4. Dependencies Checking if (isset($config['tool']['dependencies'])) { // PHP Extensions foreach ($config['tool']['dependencies']['php_extensions'] as $ext) { $results['dependencies_php']["PHP Extension: {$ext}"] = extension_loaded($ext); } // System Packages foreach ($config['tool']['dependencies']['system_packages'] as $pkg) { $results['dependencies_system']["System Package: {$pkg}"] = check_shell_command($pkg); } // Python Packages if(!empty($config['tool']['dependencies']['python_packages'])){ $python_check_script = 'import sys;'; foreach($config['tool']['dependencies']['python_packages'] as $pkg) { $python_check_script .= "import {$pkg};"; } $python_check = shell_exec("python3 -c \"{$python_check_script}\" 2>&1"); $results['dependencies_python']['All Packages Importable'] = empty($python_check); } } // 5. Tool-specific Functionality Test $results['tool_specific']['Imagick Test'] = false; if (extension_loaded('imagick')) { try { $imagick = new Imagick(); $imagick->newImage(10, 10, new ImagickPixel('red')); $imagick->setImageFormat('png'); $png_data = $imagick->getImageBlob(); $results['tool_specific']['Imagick Test'] = !empty($png_data); $imagick->destroy(); } catch(Exception $e) { $results['tool_specific']['Imagick Test'] = false; } } $results['tool_specific']['Asset Directory Exists'] = is_dir(__DIR__ . '/assets/templates'); $results['tool_specific']['Output Directory Writable'] = is_writable(__DIR__ . '/output') || is_writable(__DIR__); ?> Diagnostic Report: Personalized Award Certificates

Diagnostic Report: Personalized Award Certificates

Configuration File

$value): ?>
CheckStatus

Database

CheckStatus
Database Connection

Database Tables

$exists): ?>
Table NameStatus

Dependencies

$value): ?> $value): ?> $value): ?>
TypeCheckStatus
PHP
System
Python

Tool-Specific Checks

$value): ?>
CheckStatus
FILE 5: /home/personalized-award-certificates.digitalprank.com/public_html/help.md code Markdown # Help: Custom Award Certificate Generator Design and download custom award certificates for pranks, jokes, or lighthearted recognition. Choose from stylish templates, enter names and titles, and instantly get a downloadable award. ## Quick Start Guide Here’s how to create your award in under a minute: 1. **Step 1:** Enter the recipient's name and the title of the award. Make it as funny or serious as you like! 2. **Step 2:** Pick a certificate style from the dropdown menu. Pro users have access to exclusive designs. You can also add optional details like the presenter's name and the date. 3. **Step 3:** Click the 'Generate Certificate' button. 4. **Step 4:** Your certificate will appear on the screen. Click the 'Download' button to save it to your device and share your masterpiece! ## Features * **Multiple Templates:** Choose from a variety of styles, from classic and professional to modern and hilarious. * **Easy Customization:** Quickly add a recipient, award title, presenter, and date. * **Instant Download:** Get your generated certificate immediately in PNG format. * **Pro Features:** Upgrade to a Pro account to unlock exclusive templates, PDF downloads for high-quality printing, and the ability to upload your own signature and logo for a truly custom touch. ## Frequently Asked Questions (FAQ) **Q: Can I print these certificates?** A: Absolutely! They're high-resolution and print-ready. For best results, Pro users can download in PDF format, which is ideal for printing. **Q: Can I use my own logo?** A: Yes, Pro users can upload a custom logo or seal. This is perfect for creating awards that look like they came from a real organization or for adding a personal touch. ## Usage Examples ### Example 1: Most Likely to Be Late A lighthearted office gag award perfect for a coworker who is always running a few minutes behind. * **Description:** A perfect gag for office parties or team-building events. * **Input:** * Recipient Name: `Jason Reynolds` * Award Title: `Most Likely to Show Up Late and Blame Traffic` * Certificate Style: `Funny Cartoon Style` ### Example 2: World’s Best Cat Dad A sweet and funny gift for a friend or family member who adores their pet. * **Description:** A perfect gift for pet lovers on their birthday, Father's Day, or just for fun. * **Input:** * Recipient Name: `Alex Moreno` * Award Title: `World's Best Cat Dad` * Certificate Style: `Classic Gold Frame` FILE 6: /home/digitalprank.com/public_html/blog/data/tools/personalized-award-certificates.json code JSON { "@context": "https://schema.org", "@type": "WebApplication", "name": "Custom Award Certificate Generator", "description": "Create and download hilarious, realistic-looking custom award certificates for pranks, gags, and fun. Fully customizable with templates, text, and pro features like custom logos.", "applicationCategory": "EntertainmentApplication", "operatingSystem": "Any (Web-based)", "url": "https://personalized-award-certificates.digitalprank.com", "screenshot": "https://cdn.digitalprank.com/images/screenshots/personalized-award-certificates.jpg", "offers": { "@type": "Offer", "price": "0.00", "priceCurrency": "USD", "category": "free" }, "additionalProperty": [ { "@type": "PropertyValue", "name": "Pro Features", "value": [ "High-Quality PDF Downloads", "Exclusive Certificate Templates (Elegant Scroll, Dark Mode)", "Upload Custom Signature Image", "Upload Custom Logo or Seal" ] } ], "featureList": [ "Multiple free certificate templates (Classic, Modern, Funny)", "Customizable Recipient Name and Award Title", "Optional fields for 'Presented By' and Date", "Instant PNG download", "Print-ready high resolution output", "User-friendly interface", "Mobile and desktop compatible" ], "potentialAction": { "@type": "CreateAction", "description": "Generate a new custom award certificate." }, "mainEntity": { "@type": "WebAPI", "name": "Custom Award Certificate API", "description": "API for programmatic generation of certificates (Ultimate Plan only).", "documentation": "https://docs.digitalprank.com/api/personalized-award-certificates" }, "publisher": { "@type": "Organization", "name": "DigitalPrank.com", "url": "https://wp.digitalprank.com" }, "keywords": "custom certificate, award generator, funny awards, joke certificate, digital prank, prank generator, custom award", "detailedDescription": { "articleBody": "The Custom Award Certificate Generator is a premier online tool for creating convincing and humorous awards for any occasion. Whether you're planning an office party, a family roast, or just want to pull a clever prank, this tool lets you design a professional-looking certificate in seconds. Users can choose from several free templates, including a classic gold-framed design, a modern blue-bordered style, and a whimsical cartoon theme. Customization is simple: just type in the recipient's name and the made-up achievement. For users seeking advanced capabilities, the Pro version unlocks premium templates, allows for high-resolution PDF downloads perfect for printing, and enables the uploading of custom images for signatures and logos, adding a new level of authenticity to your prank." }, "userGuide": { "@type": "HowTo", "name": "How to Create a Custom Award Certificate", "step": [ { "@type": "HowToStep", "name": "Enter Details", "text": "Fill in the 'Recipient Name' and 'Award Title' fields on the form. These are the most important parts of your certificate." }, { "@type": "HowToStep", "name": "Customize Style", "text": "Select your desired look from the 'Certificate Style' dropdown. Optionally, you can add a presenter's name and a specific date." }, { "@type": "HowToStep", "name": "Upload (Pro Users)", "text": "If you have a Pro account, you can upload a PNG image of a signature or a custom logo to make the certificate even more unique." }, { "@type": "HowToStep", "name": "Generate and Download", "text": "Click the 'Generate Certificate' button. Your award will be displayed instantly. Click the 'Download' button to save the file to your computer or mobile device." } ] } } ```### FILE 7: /home/personalized-award-certificates.digitalprank.com/public_html/deploy.sh ```bash #!/bin/bash set -e # --- Configuration --- TOOL_SLUG="personalized-award-certificates" TOOL_DIR="/home/${TOOL_SLUG}.digitalprank.com/public_html" VHOST_CONF_DIR="/usr/local/lsws/conf/vhosts" DB_NAME="digitalprank_db" DB_USER="dp_user" DB_PASS="#$Dealer2355" PHP_VERSION="8.1" # Adjust if necessary echo "--- Starting deployment for ${TOOL_SLUG} ---" # 1. System Package Installation echo "Updating package lists..." apt-get update -y echo "Installing required system packages: imagemagick, ghostscript..." apt-get install -y imagemagick ghostscript # 2. PHP Extension Installation echo "Installing PHP extensions: gd, mbstring, json, imagick..." apt-get install -y php${PHP_VERSION}-gd php${PHP_VERSION}-mbstring php${PHP_VERSION}-imagick # 3. Python Virtual Environment and Package Installation if [ -f "${TOOL_DIR}/tool_config.json" ] && [ $(jq '.tool.dependencies.python_packages | length' "${TOOL_DIR}/tool_config.json") -gt 0 ]; then echo "Setting up Python virtual environment..." python3 -m venv "${TOOL_DIR}/venv" echo "Activating virtual environment and installing packages..." source "${TOOL_DIR}/venv/bin/activate" pip install --upgrade pip pip install reportlab pillow deactivate echo "Python environment setup complete." else echo "No Python packages required, skipping venv setup." fi # 4. Directory Structure and Permissions echo "Creating required directories..." mkdir -p "${TOOL_DIR}/assets/templates" mkdir -p "${TOOL_DIR}/output" echo "Setting permissions for ${TOOL_DIR}..." chown -R www-data:www-data "${TOOL_DIR}" chmod -R 755 "${TOOL_DIR}" chmod 775 "${TOOL_DIR}/output" # Ensure www-data can write here echo "NOTE: Manually add template PNG files to ${TOOL_DIR}/assets/templates/" # 5. Database Table Creation echo "Creating tool-specific database table 'award_certificate_history'..." SQL_CREATE_TABLE="CREATE TABLE IF NOT EXISTS \`award_certificate_history\` ( \`id\` BIGINT PRIMARY KEY AUTO_INCREMENT, \`user_id\` BIGINT NOT NULL, \`recipient_name\` VARCHAR(100) NOT NULL, \`award_title\` VARCHAR(255) NOT NULL, \`issuer_name\` VARCHAR(100), \`award_date\` DATE, \`template_style\` VARCHAR(50) NOT NULL, \`file_path\` VARCHAR(512) NOT NULL, \`download_format\` VARCHAR(10) NOT NULL, \`created_at\` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX \`user_id_idx\` (\`user_id\`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;" mysql -u"${DB_USER}" -p"${DB_PASS}" -hlocalhost "${DB_NAME}" -e"${SQL_CREATE_TABLE}" echo "Database table check/creation complete." # 6. OpenLiteSpeed Virtual Host Configuration VHOST_CONF_PATH="${VHOST_CONF_DIR}/${TOOL_SLUG}.conf" echo "Creating OpenLiteSpeed virtual host configuration at ${VHOST_CONF_PATH}..." cat > "${VHOST_CONF_PATH}" << EOF docRoot \$SERVER_ROOT/${TOOL_SLUG}/public_html/ vhDomain ${TOOL_SLUG}.digitalprank.com vhAliases www.${TOOL_SLUG}.digitalprank.com adminEmails admin@digitalprank.com enableGzip 1 errorlog \$SERVER_ROOT/logs/\$VH_NAME.error.log { useServer 0 logLevel ERROR rollingSize 10M } accesslog \$SERVER_ROOT/logs/\$VH_NAME.access.log { useServer 0 logFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" rollingSize 10M keepDays 10 compressArchive 1 } extprocessor php { type lsapi address uds://tmp/lshttpd/php.sock maxConns 35 env PHP_LSAPI_CHILDREN=35 initTimeout 60 retryTimeout 0 persistConn 1 respBuffer 0 autoStart 1 path /usr/local/lsws/lsphp${PHP_VERSION//.}/bin/lsphp backlog 100 instances 1 } scripthandler { add lsapi:php .php } rewrite { enable 1 autoLoadHtaccess 1 } vhssl { keyFile /etc/letsencrypt/live/digitalprank.com/privkey.pem certFile /etc/letsencrypt/live/digitalprank.com/fullchain.pem certChain 1 sslProtocol 24 ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH } EOF echo "Virtual host configuration created." # 7. Log Rotation LOGROTATE_CONF="/etc/logrotate.d/${TOOL_SLUG}" echo "Setting up log rotation at ${LOGROTATE_CONF}" cat > "${LOGROTATE_CONF}" << EOF /usr/local/lsws/logs/${TOOL_SLUG}.*.log { daily missingok rotate 14 compress delaycompress notifempty create 640 root adm sharedscripts postrotate /usr/local/lsws/bin/lswsctrl restart endscript } EOF echo "Log rotation configured." # 8. Service Restart and Health Check echo "Restarting OpenLiteSpeed to apply changes..." /usr/local/lsws/bin/lswsctrl restart echo "Waiting for service to come online..." sleep 5 echo "Performing health check..." if curl -s --head "https://${TOOL_SLUG}.digitalprank.com" | head -n 1 | grep "HTTP/1.[1|2|3] [23].." > /dev/null; then echo "Health check PASSED. Site is online." else echo "Health check FAILED. Please check OpenLiteSpeed logs." exit 1 fi echo "--- Deployment for ${TOOL_SLUG} completed successfully! ---" Google Search Suggestions Display of Search Suggestions is required when using Grounding with Google Search. Learn more Google logo Model ThinkingThoughts (experimental) Auto Expand to view model thoughts chevron_right FILE 8: /home/personalized-award-certificates.digitalprank.com/public_html/assets/templates/README.md code Markdown # Certificate Templates This directory should contain the base image templates for the certificate generator. The filenames must correspond to the `value` properties in the `template_style` field options within `tool_config.json`. ## Required Files - `classic_gold.png` - `modern_blue.png` - `funny_cartoon.png` - `elegant_scroll.png` (Pro) - `dark_mode.png` (Pro) ## Image Specifications - **Format:** PNG (for best quality with transparency if needed) - **Recommended Dimensions:** 1200px width x 849px height (A4 paper ratio) - **Resolution:** 150 DPI or higher is recommended for good print quality. The `processor.php` script relies on these exact filenames. Ensure they are present before deploying the tool. Model ThinkingThoughts (experimental) Auto Expand to view model thoughts chevron_right An internal error has occurred. Model ThinkingThoughts (experimental) Auto Expand to view model thoughts chevron_right FILE 9: /home/cdn.digitalprank.com/public_html/php/universal_functions.php code PHP 'free', 'has_pro_access' => false, 'plan_id' => null ]; if ($user_id === 0) { return $access; } try { // Check for an active subscription in Paid Member Subscriptions $stmt = $pdo->prepare( "SELECT subscription_plan_id FROM wp_pms_member_subscriptions WHERE user_id = ? AND status = 'active' ORDER BY subscription_plan_id DESC LIMIT 1" ); $stmt->execute([$user_id]); $subscription = $stmt->fetch(PDO::FETCH_ASSOC); if ($subscription) { $plan_id = (int)$subscription['subscription_plan_id']; $access['plan_id'] = $plan_id; // Basic Tier IDs: 174, 184 if (in_array($plan_id, [174, 184])) { $access['tier'] = 'basic'; $access['has_pro_access'] = true; } // Gold Tier IDs: 175, 185 elseif (in_array($plan_id, [175, 185])) { $access['tier'] = 'gold'; $access['has_pro_access'] = true; } // Ultimate Tier IDs: 176, 186 elseif (in_array($plan_id, [176, 186])) { $access['tier'] = 'ultimate'; $access['has_pro_access'] = true; } } } catch (PDOException $e) { // Log error, but don't break execution. Default to free tier. error_log("PDO Exception in getUserAccessLevel: " . $e->getMessage()); } return $access; } /** * Gets the number of times a tool has been used today by a user or IP. * * @param PDO $pdo The database connection object. * @param string $tool_slug The tool's slug. * @param string $user_ip The user's IP address. * @param int $user_id The user's ID (0 for guest). * @return int The total usage count for the current day. */ function getTodaysUsage(PDO $pdo, string $tool_slug, string $user_ip, int $user_id): int { try { if ($user_id > 0) { // Logged-in users are tracked by user_id $sql = "SELECT COUNT(*) FROM wp_digitalprank_usage WHERE user_id = ? AND tool_slug = ? AND DATE(timestamp) = CURDATE() AND credits_used > 0"; $stmt = $pdo->prepare($sql); $stmt->execute([$user_id, $tool_slug]); } else { // Guests are tracked by IP address $sql = "SELECT COUNT(*) FROM wp_digitalprank_usage WHERE ip_address = ? AND user_id = 0 AND tool_slug = ? AND DATE(timestamp) = CURDATE() AND credits_used > 0"; $stmt = $pdo->prepare($sql); $stmt->execute([$user_ip, $tool_slug]); } return (int)$stmt->fetchColumn(); } catch (PDOException $e) { error_log("PDO Exception in getTodaysUsage: " . $e->getMessage()); return 9999; // Return a high number to prevent further use on error } } /** * Checks if the user is within their daily usage limit. * * @param PDO $pdo The database connection object. * @param string $tool_slug The tool's slug. * @param string $user_ip The user's IP address. * @param int $user_id The user's ID (0 for guest). * @param int $limit The daily limit for the user's tier (-1 for unlimited). * @return bool True if usage is allowed, false otherwise. */ function checkDailyUsage(PDO $pdo, string $tool_slug, string $user_ip, int $user_id, int $limit): bool { if ($limit === -1) { return true; // Unlimited usage } $todays_usage = getTodaysUsage($pdo, $tool_slug, $user_ip, $user_id); return $todays_usage < $limit; } /** * Logs a tool usage event to the database. * * @param PDO $pdo The database connection object. * @param string $tool_slug The tool's slug. * @param string $user_ip The user's IP address. * @param int $user_id The user's ID (0 for guest). * @param string $action_type The type of action (e.g., 'success', 'failed'). * @param string|null $input_data JSON encoded input data. * @param string|null $output_data JSON encoded output data. * @param float $processing_time The script execution time in seconds. * @param int $credits_used The number of credits this action consumed. * @return void */ function logUsage(PDO $pdo, string $tool_slug, string $user_ip, int $user_id, string $action_type, ?string $input_data, ?string $output_data, float $processing_time, int $credits_used = 0): void { try { $pdo->beginTransaction(); $sql_log = "INSERT INTO wp_digitalprank_usage_log (user_id, tool_slug, action_type, ip_address, session_id, user_agent, input_data, output_data, processing_time, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; $stmt_log = $pdo->prepare($sql_log); $status = ($action_type === 'success') ? 'success' : 'failed'; $stmt_log->execute([ $user_id, $tool_slug, $action_type, $user_ip, session_id(), $_SERVER['HTTP_USER_AGENT'] ?? 'N/A', $input_data, $output_data, $processing_time, $status ]); $sql_usage = "INSERT INTO wp_digitalprank_usage (user_id, tool_slug, action, credits_used, processing_time, ip_address, session_id, user_agent) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; $stmt_usage = $pdo->prepare($sql_usage); $stmt_usage->execute([ $user_id, $tool_slug, $action_type, $credits_used, $processing_time, $user_ip, session_id(), $_SERVER['HTTP_USER_AGENT'] ?? 'N/A' ]); $pdo->commit(); } catch (PDOException $e) { if ($pdo->inTransaction()) { $pdo->rollBack(); } error_log("PDO Exception in logUsage: " . $e->getMessage()); } } /** * Retrieves field-specific tier overrides for a tool. * * @param PDO $pdo The database connection object. * @param string $tool_slug The slug of the tool. * @return array An associative array of field_id => tier_required. */ function getToolOverrides(PDO $pdo, string $tool_slug): array { $overrides = []; try { $stmt = $pdo->prepare( "SELECT t.field_id, t.tier_required FROM wp_digitalprank_tool_overrides t JOIN wp_digitalprank_tools tl ON t.tool_id = tl.tool_id WHERE tl.slug = ? AND t.is_active = 1 AND t.override_type = 'tier'" ); $stmt->execute([$tool_slug]); $results = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($results as $row) { $overrides[$row['field_id']] = $row['tier_required']; } } catch (PDOException $e) { error_log("PDO Exception in getToolOverrides: " . $e->getMessage()); } return $overrides; } ?> FILE 10: /home/personalized-award-certificates.digitalprank.com/public_html/assets/css/style.css code CSS /* --- Universal Tool Form Styles --- */ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; line-height: 1.6; color: #333; max-width: 800px; margin: 20px auto; padding: 0 15px; background-color: #f9f9f9; } .container { background-color: #ffffff; padding: 25px 30px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); } h1 { text-align: center; color: #0077CC; /* From JSON ui.theme.primary_color */ margin-bottom: 5px; } p.tagline { text-align: center; color: #555; margin-top: 0; margin-bottom: 30px; } /* --- Form Group Styling --- */ .form-group { margin-bottom: 22px; } .form-group label { display: block; margin-bottom: 8px; font-weight: bold; color: #444; } .form-group input[type="text"], .form-group input[type="date"], .form-group select { width: 100%; padding: 12px; border: 1px solid #ccc; border-radius: 5px; box-sizing: border-box; transition: border-color 0.2s, box-shadow 0.2s; } .form-group input[type="text"]:focus, .form-group input[type="date"]:focus, .form-group select:focus { outline: none; border-color: #0077CC; box-shadow: 0 0 0 2px rgba(0, 119, 204, 0.2); } .form-group input[type="file"] { padding: 8px; border: 1px solid #ccc; border-radius: 5px; width: 100%; box-sizing: border-box; } .form-group .help-text { font-size: 0.9em; color: #777; margin-top: 6px; } /* --- Badges and Indicators --- */ .pro-badge { background-color: #ffd700; color: #333; font-size: 0.7em; padding: 3px 6px; border-radius: 4px; margin-left: 8px; font-weight: bold; vertical-align: middle; text-transform: uppercase; } /* --- Buttons --- */ button#submit-button { background-color: #0077CC; color: #ffffff; padding: 14px 20px; border: none; border-radius: 5px; cursor: pointer; width: 100%; font-size: 1.1em; font-weight: bold; transition: background-color 0.2s; } button#submit-button:hover { background-color: #005fa3; } button#submit-button:disabled { background-color: #cccccc; cursor: not-allowed; } /* --- Results and Feedback --- */ .feedback-container { margin-top: 25px; text-align: center; } .hidden { display: none; } #loading-indicator { font-weight: bold; color: #0077CC; } #error-message { color: #d9534f; background-color: #f2dede; padding: 12px; border: 1px solid #ebccd1; border-radius: 4px; } #result-container { margin-top: 30px; text-align: center; border-top: 1px solid #eeeeee; padding-top: 25px; } #result-container h2 { color: #333; margin-bottom: 20px; } #result-image { max-width: 100%; border: 1px solid #dddddd; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } a.download-button { display: inline-block; margin-top: 20px; padding: 12px 25px; background-color: #28a745; color: #ffffff; text-decoration: none; border-radius: 5px; font-weight: bold; transition: background-color 0.2s; } a.download-button:hover { background-color: #218838; } FILE 3: /home/personalized-award-certificates.digitalprank.com/public_html/tool_form.php (REVISED) code PHP <?php echo htmlspecialchars($tool_name); ?> - DigitalPrank

"; break; case 'select': echo ""; break; case 'file': $allowed_types_str = implode(',', array_map(fn($t) => '.'.$t, $config['tool']['security']['allowed_file_types'])); echo ""; break; } ?>

Model ThinkingThoughts (experimental) Auto Expand to view model thoughts chevron_right FILE 11: /home/personalized-award-certificates.digitalprank.com/public_html/install.sql code SQL -- This script registers the 'Personalized Award Certificates' tool into the DigitalPrank platform. -- It should be run once during the initial deployment. -- Tool configuration data extracted from tool_config.json -- Slug: personalized-award-certificates -- Name: Personalized Award Certificates -- Category: prank -- Tagline: Create hilarious, realistic-looking custom awards in seconds! -- Description: Design and download custom award certificates for pranks, jokes, or lighthearted recognition. Choose from stylish templates, enter names and titles, and instantly get a downloadable award. -- Daily Limits from JSON: -- Free: 3 -- Basic: 25 -- Gold: 200 -- Ultimate: -1 (unlimited) -- The features_json is a minified version of the 'features' block from the config. INSERT INTO `wp_digitalprank_tools` ( `slug`, `name`, `subdomain`, `category`, `tagline`, `description`, `features_json`, `free_monthly_limit`, `basic_monthly_limit`, `gold_monthly_limit`, `ultimate_monthly_limit`, `is_active`, `created_at`, `updated_at` ) VALUES ( 'personalized-award-certificates', 'Personalized Award Certificates', 'personalized-award-certificates', 'prank', 'Create hilarious, realistic-looking custom awards in seconds!', 'Design and download custom award certificates for pranks, jokes, or lighthearted recognition. Choose from stylish templates, enter names and titles, and instantly get a downloadable award.', '{"bulk_enabled": false, "history_enabled": true, "export_enabled": true, "api_enabled": false}', 3 * 30, -- Approximating monthly from daily 25 * 30, 200 * 30, -1, 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP ) ON DUPLICATE KEY UPDATE `name` = VALUES(`name`), `subdomain` = VALUES(`subdomain`), `category` = VALUES(`category`), `tagline` = VALUES(`tagline`), `description` = VALUES(`description`), `features_json` = VALUES(`features_json`), `free_monthly_limit` = VALUES(`free_monthly_limit`), `basic_monthly_limit` = VALUES(`basic_monthly_limit`), `gold_monthly_limit` = VALUES(`gold_monthly_limit`), `ultimate_monthly_limit` = VALUES(`ultimate_monthly_limit`), `is_active` = VALUES(`is_active`), `updated_at` = CURRENT_TIMESTAMP; FILE 12: /home/personalized-award-certificates.digitalprank.com/public_html/assets/js/main.js```javascript document.addEventListener('DOMContentLoaded', function () { const form = document.getElementById('tool-form'); if (!form) return; code Code const submitButton = document.getElementById('submit-button'); const loadingIndicator = document.getElementById('loading-indicator'); const errorMessage = document.getElementById('error-message'); const resultContainer = document.getElementById('result-container'); const resultImage = document.getElementById('result-image'); const downloadLink = document.getElementById('download-link'); form.addEventListener('submit', function (event) { event.preventDefault(); // Use browser's built-in validation feedback if (!form.checkValidity()) { form.reportValidity(); return; } // --- UI Reset --- submitButton.disabled = true; submitButton.textContent = 'Generating...'; loadingIndicator.classList.remove('hidden'); errorMessage.classList.add('hidden'); resultContainer.classList.add('hidden'); const formData = new FormData(form); fetch('processor.php', { method: 'POST', body: formData, headers: { 'Accept': 'application/json' } }) .then(response => { // Handle non-OK responses by parsing the JSON error message if (!response.ok) { return response.json().then(errorData => { throw new Error(errorData.message || `Server responded with status: ${response.status}`); }); } return response.json(); }) .then(data => { if (data.success && data.data.file_url) { // Success: Display the result resultImage.onload = () => { resultContainer.classList.remove('hidden'); }; resultImage.src = data.data.file_url; downloadLink.href = data.data.file_url; // Suggest a filename const urlParts = data.data.file_url.split('/'); downloadLink.download = `award-certificate-${urlParts[urlParts.length - 1]}`; } else { // Handle logical errors returned with a 200 OK status throw new Error(data.message || 'An unknown error occurred.'); } }) .catch(error => { console.error('Submission Error:', error); errorMessage.textContent = error.message; errorMessage.classList.remove('hidden'); }) .finally(() => { // --- UI Restoration --- submitButton.disabled = false; submitButton.textContent = 'Generate Certificate'; loadingIndicator.classList.add('hidden'); }); }); }); code Code ### FILE 3: /home/personalized-award-certificates.digitalprank.com/public_html/tool_form.php (FINAL REVISION) ```php <?php echo htmlspecialchars($tool_name); ?> - DigitalPrank

"; break; case 'select': echo ""; break; case 'file': $allowed_types_str = implode(',', array_map(fn($t) => '.'.$t, $config['tool']['security']['allowed_file_types'])); echo ""; break; } ?>