cancionero-web/res_gen/static/generar_pdf.php

209 lines
6.7 KiB
PHP

<?php
$errorlist = array();
function delTree($dir) {
$files = array_diff(scandir($dir), array('.', '..'));
foreach ($files as $file) {
if (!is_dir("$dir/$file")) {
unlink("$dir/$file");
}
}
return rmdir($dir);
}
function param_conversion($name, $type) {
global $errorlist;
if (validParam($name, "string")) {
if (!is_numeric($_POST[$name])) {
$errorlist[] = "El parámetro $name debería ser numérico, y es: " . $_POST[$name];
} else {
if ($type == "integer")
$_POST[$name] = intval($_POST[$name]);
else if ($type == "double")
$_POST[$name] = doubleval($_POST[$name]);
else {
$errorlist[] = "$type es un tipo inválido al que convertir el parámetro $name";
return false;
}
return true;
}
}
return false;
}
function validParam($name, $type) {
global $errorlist;
if (!isset($_POST[$name]))
$errorlist[] = "No se ha incluido el parámetro '$name'";
else if (($realtype = gettype($_POST[$name])) != $type)
$errorlist[] = "El parámetro '$name' debería ser de tipo $type, y es de tipo $realtype";
else
return true;
return false;
}
function validEmptyBool($name) {
if (!isset($_POST[$name]))
$_POST[$name] = "false";
return validBool($name);
}
function validBool($name) {
if (validParam($name, "string")) {
if ($_POST[$name] != "true")
$_POST[$name] = "false";
return true;
}
return false;
}
function validInt($name, $min, $max) {
global $errorlist;
if (param_conversion($name, "integer") && validParam($name, "integer")) {
if ($_POST[$name] < $min || $_POST[$name] > $max)
$errorlist[] = "El parámetro numérico '$name' tiene un valor fuera de rango. Valor: " . $_POST[$name] . ". Rango válido: [$min, $max].";
else
return true;
}
return false;
}
function validDouble($name, $min, $max) {
global $errorlist;
if (param_conversion($name, "double") && validParam($name, "double")) {
if ($_POST[$name] < $min || $_POST[$name] > $max)
$errorlist[] = "El parámetro numérico '$name' tiene un valor fuera de rango. Valor: " . $_POST[$name] . ". Rango válido: [$min, $max].";
else
return true;
}
return false;
}
$TEX_ERROR = "Fatal error occurred, no output PDF file produced!";
$error = false;
// Check fields and their correctness
$error |= !validBool("chorded");
if (!$error && $_POST["chorded"] != "true") {
$error |= !validInt("paperheight", 1, 9999);
$error |= !validInt("paperwidth", 1, 9999);
$error |= !validDouble("margin", 0.01, 999);
$error |= !validInt("fontsize", 8, 100);
$error |= !validInt("titlefontsize", 8, 100);
$error |= !validInt("subtitlefontsize", 8, 100);
}
$error |= !validEmptyBool("ifcolumns");
if (!$error && $_POST["ifcolumns"] == "true") {
$error |= !validInt("columns", 1, 20);
}
$error |= !validEmptyBool("ifcolumnsep");
if (!$error && $_POST["ifcolumnsep"] == "true") {
$error |= !validDouble("columnsep", 0.01, 999);
}
$error |= !validInt("breaksallowed", 0, 3);
$error |= !validParam("title", "string");
$error |= !validParam("songs", "array");
if (!$error) {
foreach ($_POST["songs"] as $song) {
if (!str_starts_with($song, "canciones/") || str_contains($song, "..")) {
$error = true;
$errorlist[] = "La canción $song no cumple los requisitos.";
}
}
}
// Create tmp dir and copy/link necessary files
if (!$error) {
$resdir = getcwd() . "/res";
$tmpdir = substr(shell_exec("mktemp -d"), 0, -1); // remove trailing newline
symlink("$resdir/songs.sty", "$tmpdir/songs.sty");
symlink("$resdir/estilo.sty", "$tmpdir/estilo.sty");
symlink("$resdir/acordes.sty", "$tmpdir/acordes.sty");
symlink("$resdir/canciones", "$tmpdir/canciones");
symlink("$resdir/changepage.sty", "$tmpdir/changepage.sty");
symlink("$resdir/tocloft.sty", "$tmpdir/tocloft.sty");
symlink("$resdir/uarial.sty", "$tmpdir/uarial.sty");
}
// Generate and fill template
if (!$error) {
$lines = file("$resdir/template.tex");
if ($_POST["chorded"] == "true") {
$lines = preg_replace('/%CHORDED%/', '', $lines);
} else {
$lines = preg_replace('/%LYRICS%/', '', $lines);
$lines = preg_replace('/%PAPERHEIGHT%/', $_POST["paperheight"], $lines);
$lines = preg_replace('/%PAPERWIDTH%/', $_POST["paperwidth"], $lines);
$lines = preg_replace('/%MARGIN%/', $_POST["margin"], $lines);
if ($_POST["ifcolumns"] == "true") {
$lines = preg_replace('/%SONGCOLUMNS%/', '', $lines);
$lines = preg_replace('/%SONGCOLNUM%/', "\\songcolumns{" . $_POST["columns"] . "}", $lines);
} else {
$lines = preg_replace('/%SONGCOLUMNS%/', 'onesongcolumn', $lines);
}
$lines = preg_replace('/%FONTSIZE%/', $_POST["fontsize"], $lines);
$lines = preg_replace('/%LINESKIP%/', $_POST["fontsize"] + 4, $lines);
$lines = preg_replace('/%TITLEFONTSIZE%/', $_POST["titlefontsize"], $lines);
$lines = preg_replace('/%TITLELINESKIP%/', $_POST["titlefontsize"] + 4, $lines);
$lines = preg_replace('/%SUBTITLEFONTSIZE%/', $_POST["subtitlefontsize"], $lines);
}
$lines = preg_replace('/%TITLE%/', $_POST["title"], $lines);
if ($_POST["ifcolumnsep"] == "true") {
$lines = preg_replace('/%IFCOLUMNSEP%/', '', $lines);
$lines = preg_replace('/%COLUMNSEP%/', $_POST["columnsep"], $lines);
}
$songinput = "";
foreach ($_POST["songs"] as $song) {
$songinput .= '\input{' . $song . "}\n";
}
$lines = preg_replace('/%SONGLIST%/', $songinput, $lines);
$fwrite = file_put_contents("$tmpdir/cancionero.tex", $lines);
if (!$fwrite) {
$error = true;
$errorlist[] = "No se pudo escribir el archivo LaTeX.";
}
}
// Compile PDF
if (!$error) {
chdir($tmpdir);
do {
$latexlog = shell_exec("/usr/bin/pdflatex -interaction=nonstopmode cancionero.tex");
if (str_contains($latexlog, $TEX_ERROR)) {
$error = true;
$errorlist[] = "Ha sucedido un error en la ejecución, véase el log más abajo.";
break;
}
} while (str_contains($latexlog, "(rerunfilecheck)"));
}
// Return PDF or error page
if (!$error && file_exists($pdffile = "$tmpdir/cancionero.pdf")) {
header("Content-Type: application/pdf");
header('Content-Disposition: inline;filename=cancionero.pdf');
header('Content-Length: ' . filesize($pdffile));
readfile($pdffile);
} else {
echo '<h1>Ha ocurrido un error...</h1>';
echo '<p>No se ha podido generar el cancionero.</p>';
echo '<p><strong>Por favor,</strong> guarda (Ctrl+S) o imprime (Ctrl+P) esta página y envíasela a Carlos, para que lo pueda solucionar.</p>';
echo '<h2>Errores individuales</h2>';
echo '<ul>';
foreach ($errorlist as $errormsg) {
echo "<li>$errormsg</li>";
}
echo '</ul>';
if (isset($tmpdir) && file_exists("$tmpdir/cancionero.log")) {
echo '<h2>Detalles del error</h2>';
echo '<pre>';
readfile("$tmpdir/cancionero.log");
echo '</pre>';
}
echo '<p>Fin de la página.</p>';
}
// Cleanup
if (isset($tmpdir) && file_exists($tmpdir))
delTree($tmpdir);
?>