| Server IP : 139.59.63.204 / Your IP : 216.73.217.62 Web Server : Apache/2.4.58 (Ubuntu) System : Linux ubuntu-s-1vcpu-1gb-blr1-01 6.8.0-110-generic #110-Ubuntu SMP PREEMPT_DYNAMIC Thu Mar 19 15:09:20 UTC 2026 x86_64 User : root ( 0) PHP Version : 8.3.6 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/abyogasms.com/html/iyd/ |
Upload File : |
<?php
/**
* Certificate Generator — International Yoga Day 2026 (ABYOGASMS)
* ---------------------------------------------------------------
* Overlays participant name CENTERED below "It is certified that"
* using PHP GD library.
*
* URL usage:
* generate_certificate.php?mobile=9876543210 → view inline
* generate_certificate.php?mobile=9876543210&download → force download
* generate_certificate.php?name=Dileep+Awasthi → direct (testing)
*/
ini_set('display_errors', 0); // Keep OFF in production (errors would corrupt image header)
error_reporting(E_ALL);
// ── CONFIG ──────────────────────────────────────────────────────────
require_once __DIR__ . '/config.php'; // defines DB_HOST, DB_NAME, DB_USER, DB_PASS
define('CERT_TEMPLATE', __DIR__ . '/assets/certyog.jpeg');
define('FONT_FILE', __DIR__ . '/assets/fonts/static/Lora-BoldItalic.ttf');
// ── TEXT PLACEMENT (measured for 1599 × 1133 image) ─────────────────
// Blank zone between "It is certified that" (ends y≈469)
// and "has participated" (starts y≈578). Baseline at y=515.
// X is calculated dynamically to center the name horizontally.
define('NAME_BASELINE_Y', 527); // GD baseline Y (imagettftext uses baseline)
define('FONT_SIZE', 23); // Points — prominent, matches certificate style
define('TEXT_R', 10); // Near-black
define('TEXT_G', 10);
define('TEXT_B', 10);
// ── HELPERS ──────────────────────────────────────────────────────────
function db_connect(): PDO {
$dsn = 'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8mb4';
return new PDO($dsn, DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
}
function send_error(int $code, string $msg): void {
http_response_code($code);
header('Content-Type: text/html; charset=utf-8');
echo '<!DOCTYPE html><html><head><title>Error ' . $code . '</title>'
. '<style>body{font-family:sans-serif;padding:40px;color:#c0392b;}'
. 'h2{margin-bottom:8px;}</style></head><body>'
. '<h2>⚠ Certificate Error (' . $code . ')</h2>'
. '<p>' . htmlspecialchars($msg) . '</p>'
. '</body></html>';
exit;
}
// ── 1. RESOLVE PARTICIPANT ───────────────────────────────────────────
$title = '';
$fullname = '';
$mobile = trim($_REQUEST['mobile'] ?? '');
if ($mobile !== '') {
// Validate mobile format
if (!preg_match('/^\d{10}$/', $mobile)) {
send_error(400, 'Invalid mobile number. Please enter a valid 10-digit number.');
}
try {
$pdo = db_connect();
$stmt = $pdo->prepare(
"SELECT title, fullname FROM registrations WHERE mobile = ? LIMIT 1"
);
$stmt->execute([$mobile]);
$row = $stmt->fetch();
} catch (PDOException $e) {
send_error(500, 'Database error: ' . $e->getMessage());
}
if (!$row) {
send_error(404,
'No registration found for mobile number ' . htmlspecialchars($mobile) . '. '
. 'Please register first on the main page.'
);
}
$title = trim($row['title']);
$fullname = trim($row['fullname']);
} elseif (!empty($_REQUEST['name'])) {
// Direct mode (admin / testing only)
$fullname = trim($_REQUEST['name']);
$title = trim($_REQUEST['title'] ?? '');
} else {
send_error(400, 'Please provide a mobile number: ?mobile=XXXXXXXXXX');
}
// Build display name: "Title Fullname"
$display_name = trim(($title !== '' ? $title . ' ' : '') . $fullname);
if ($display_name === '') {
send_error(400, 'Name is empty. Cannot generate certificate.');
}
// ── 2. VALIDATE FILES ────────────────────────────────────────────────
if (!file_exists(CERT_TEMPLATE)) {
send_error(500, 'Certificate template not found: ' . CERT_TEMPLATE);
}
if (!file_exists(FONT_FILE)) {
send_error(500,
'Font file not found: ' . FONT_FILE . PHP_EOL
. 'Download "Lora" from https://fonts.google.com/specimen/Lora '
. 'and place Lora-BoldItalic.ttf in assets/fonts/static/'
);
}
// ── 3. LOAD IMAGE ────────────────────────────────────────────────────
$img = @imagecreatefromjpeg(CERT_TEMPLATE);
if (!$img) {
send_error(500, 'Failed to load certificate template. Ensure it is a valid JPEG.');
}
$img_w = imagesx($img); // 1599
$img_h = imagesy($img); // 1133
// ── 4. CALCULATE CENTERED X POSITION ────────────────────────────────
// imagettfbbox returns bounding box of the text string at given size/font/angle
// Returns: [lower-left x, lower-left y, lower-right x, lower-right y,
// upper-right x, upper-right y, upper-left x, upper-left y]
$bbox = imagettfbbox(FONT_SIZE, 0, FONT_FILE, $display_name);
if ($bbox === false) {
send_error(500, 'imagettfbbox() failed. Check that the font file is valid.');
}
$text_w = abs($bbox[4] - $bbox[0]); // width of text
$name_x = (int)(($img_w - $text_w) / 2) - $bbox[0]; // center + left-bearing correction
// ── 5. DRAW NAME ─────────────────────────────────────────────────────
$color = imagecolorallocate($img, TEXT_R, TEXT_G, TEXT_B);
imagettftext(
$img,
FONT_SIZE,
0, // angle
$name_x,
NAME_BASELINE_Y,
$color,
FONT_FILE,
$display_name
);
// ── 6. OUTPUT ────────────────────────────────────────────────────────
$safe_name = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $fullname);
$safe_filename = 'ABYOGASMS2026_Certificate_' . $safe_name . '.jpg';
$is_download = isset($_REQUEST['download']);
header('Content-Type: image/jpeg');
header('Content-Disposition: ' . ($is_download ? 'attachment' : 'inline')
. '; filename="' . $safe_filename . '"');
header('Cache-Control: no-store, no-cache');
imagejpeg($img, null, 95);
imagedestroy($img);
exit;