<?php
ini_set('display_errors', 0);
error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING & ~E_DEPRECATED & ~E_USER_DEPRECATED);
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/bcg_error.log');
// admin/BCG/html/image.php  (improved)
// - uses __DIR__ to build safe include paths
// - more robust validation and error reporting (toggle DEBUG)
// - falls back to error.png if generation fails

// Toggle debug during development (set to false in production)
define('DEBUG', true);

function showErrorImage($msg = '') {
    // If you have an actual error.png, prefer to show it. Otherwise send text/plain for debugging.
    $errorImg = __DIR__ . DIRECTORY_SEPARATOR . 'error.png';
    if (file_exists($errorImg) && !DEBUG) {
        header('Content-Type: image/png');
        readfile($errorImg);
        exit;
    } else {
        header('Content-Type: text/plain; charset=utf-8');
        echo "Barcode generation error.\n";
        if ($msg) echo "Details: " . $msg . "\n";
        exit;
    }
}

// required keys from the original script (text is critical)
$requiredKeys = array('code', 'filetype', 'dpi', 'scale', 'rotation', 'font_family', 'font_size', 'text');

// quick presence check
foreach ($requiredKeys as $key) {
    if (!isset($_GET[$key])) {
        showErrorImage("Missing parameter: $key");
    }
}

// 'code' refers to a config filename (e.g. BCGcode128). allow letters, numbers, underscore
$code = $_GET['code'];
if (!preg_match('/^[A-Za-z0-9_]+$/', $code)) {
    showErrorImage("Invalid code parameter");
}

// expected config file path: BCG/html/config/<code>.php
$configFile = __DIR__ . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . $code . '.php';
if (!file_exists($configFile)) {
    showErrorImage("Config file not found: $configFile");
}

// include the config first (it typically defines $classFile, $className, $baseClassFile, etc.)
if (!@include_once($configFile)) {
    showErrorImage("Failed to include config file: $configFile");
}

// classes are in BCG/html/class/ relative to this file
$class_dir = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'class';

// verify class files exist
$needed = array('BCGColor.php','BCGBarcode.php','BCGDrawing.php','BCGFontFile.php');
foreach ($needed as $f) {
    $p = $class_dir . DIRECTORY_SEPARATOR . $f;
    if (!file_exists($p)) {
        showErrorImage("Missing BCG class file: $p");
    }
}

// require the class files
require_once($class_dir . DIRECTORY_SEPARATOR . 'BCGColor.php');
require_once($class_dir . DIRECTORY_SEPARATOR . 'BCGBarcode.php');
require_once($class_dir . DIRECTORY_SEPARATOR . 'BCGDrawing.php');
require_once($class_dir . DIRECTORY_SEPARATOR . 'BCGFontFile.php');

// include the specific barcode implementation class (e.g. BCGcode128.barcode.php)
// $classFile should be set by the config file included above
if (empty($classFile)) {
    showErrorImage("Config did not set \$classFile");
}
$classFilePath = $class_dir . DIRECTORY_SEPARATOR . $classFile;

if (!file_exists($classFilePath)) {
    showErrorImage("Barcode class file not found: $classFilePath");
}
if (!@include_once($classFilePath)) {
    showErrorImage("Failed to include barcode class file: $classFilePath");
}

// include base class file if config provided
if (!empty($baseClassFile)) {
    $baseClassPath = __DIR__ . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . $baseClassFile;
    if (file_exists($baseClassPath)) {
        include_once($baseClassPath);
    } else {
        // not fatal; some configs don't need this in this location
    }
}

// map filetypes (case-insensitive)
$filetypes = array('PNG' => BCGDrawing::IMG_FORMAT_PNG, 'JPEG' => BCGDrawing::IMG_FORMAT_JPEG, 'GIF' => BCGDrawing::IMG_FORMAT_GIF);

// Now try to create the barcode
$drawException = null;
try {
    $color_black = new BCGColor(0, 0, 0);
    $color_white = new BCGColor(255, 255, 255);

    // className should be defined in the config file (e.g., BCGcode128)
    if (empty($className) || !class_exists($className)) {
        showErrorImage("Class not defined or missing: " . (string)$className);
    }

    $code_generated = new $className();

    // If the config defines these setup functions, call them
    if (function_exists('baseCustomSetup')) {
        baseCustomSetup($code_generated, $_GET);
    }
    if (function_exists('customSetup')) {
        customSetup($code_generated, $_GET);
    }

    // set scale and colors
    $scale = max(1, min(4, intval($_GET['scale'])));
    $code_generated->setScale($scale);
    $code_generated->setBackgroundColor($color_white);
    $code_generated->setForegroundColor($color_black);

    // parse text parameter (use raw 'text' value from GET)
    $text = (string)$_GET['text'];
    if ($text !== '') {
        $code_generated->parse($text);
    }
} catch (Exception $e) {
    $drawException = $e;
}

// Prepare drawing and output
$drawing = new BCGDrawing('', $color_white);

if ($drawException) {
    // draw exception image (fallback)
    $drawing->drawException($drawException);
} else {
    $drawing->setBarcode($code_generated);
    // rotation
    $rotation = intval($_GET['rotation']);
    $drawing->setRotationAngle($rotation);
    // dpi: allow 'NULL' or numeric
    $dpiParam = $_GET['dpi'];
    $dpi = ($dpiParam === 'NULL') ? null : max(72, min(300, intval($dpiParam)));
    $drawing->setDPI($dpi);
    $drawing->draw();
}

// Choose content-type / finish
$ft = strtoupper($_GET['filetype']);
if (!array_key_exists($ft, $filetypes)) {
    showErrorImage("Unsupported filetype: $ft");
}

switch ($ft) {
    case 'PNG':
        header('Content-Type: image/png');
        break;
    case 'JPEG':
        header('Content-Type: image/jpeg');
        break;
    case 'GIF':
        header('Content-Type: image/gif');
        break;
}

header('Content-Type: image/png');
$drawing->finish(BCGDrawing::IMG_FORMAT_PNG);
exit;
?>
