organic: Add pdf signature check
This commit is contained in:
@@ -40,73 +40,47 @@ function jenc($data): string {
|
|||||||
return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$file = tmpfile();
|
||||||
|
$headerfile = tmpfile();
|
||||||
|
if (!$file || !$headerfile) {
|
||||||
|
header('Status: 500');
|
||||||
|
header('Content-Length: 0');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
$filename = stream_get_meta_data($file)['uri'];
|
||||||
|
$headerfilename = stream_get_meta_data($headerfile)['uri'];
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$stdin = fopen("php://input", "rb");
|
||||||
|
while (!feof($stdin)) {
|
||||||
|
if (($data = fread($stdin, 8192)) === false)
|
||||||
|
break;
|
||||||
|
fwrite($file, $data);
|
||||||
|
}
|
||||||
|
fclose($stdin);
|
||||||
|
} else {
|
||||||
|
if (exec("curl -s -D " . escapeshellarg($headerfilename) . " -o " . escapeshellarg($filename) . " " . escapeshellarg($url)) === false) {
|
||||||
|
header('Status: 500');
|
||||||
|
header('Content-Length: 0');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($format === 'text') {
|
if ($format === 'text') {
|
||||||
header('Content-Type: text/plain; charset=UTF-8');
|
header('Content-Type: text/plain; charset=UTF-8');
|
||||||
|
passthru("pdftotext -raw " . escapeshellarg($filename) . " -");
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
} else if ($format === 'sig') {
|
||||||
$fd_spec = [
|
header('Content-Type: text/plain; charset=UTF-8');
|
||||||
0 => ["pipe", "r"], // stdin
|
passthru("pdfsig " . escapeshellarg($filename));
|
||||||
1 => ["pipe", "w"], // stdout
|
|
||||||
2 => ["pipe", "w"], // stderr
|
|
||||||
];
|
|
||||||
$process = proc_open(['pdftotext', '-raw', '-', '-'], $fd_spec, $pipes);
|
|
||||||
$input = fopen("php://input", "rb");
|
|
||||||
while (!feof($input)) {
|
|
||||||
if (($buffer = fread($input, 8192)) === false)
|
|
||||||
break;
|
|
||||||
fwrite($pipes[0], $buffer);
|
|
||||||
}
|
|
||||||
fclose($input);
|
|
||||||
fclose($pipes[0]);
|
|
||||||
|
|
||||||
fpassthru($pipes[1]);
|
|
||||||
fclose($pipes[1]);
|
|
||||||
$stderr = stream_get_contents($pipes[2]);
|
|
||||||
fclose($pipes[2]);
|
|
||||||
$return_value = proc_close($process);
|
|
||||||
} else {
|
|
||||||
passthru("curl -s '" . escapeshellarg($url) . "' | pdftotext -raw - -");
|
|
||||||
}
|
|
||||||
} else if ($format === 'json') {
|
} else if ($format === 'json') {
|
||||||
header('Content-Type: application/json; charset=UTF-8');
|
header('Content-Type: application/json; charset=UTF-8');
|
||||||
|
if (exec("pdftotext -raw " . escapeshellarg($filename) . " -", $text) === false) {
|
||||||
$fd_spec = [
|
|
||||||
0 => ["pipe", "r"], // stdin
|
|
||||||
1 => ["pipe", "w"], // stdout
|
|
||||||
2 => ["pipe", "w"], // stderr
|
|
||||||
];
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
||||||
$process = proc_open(['pdftotext', '-raw', '-', '-'], $fd_spec, $pipes);
|
|
||||||
$input = fopen("php://input", "rb");
|
|
||||||
while (!feof($input)) {
|
|
||||||
if (($buffer = fread($input, 8192)) === false)
|
|
||||||
break;
|
|
||||||
fwrite($pipes[0], $buffer);
|
|
||||||
}
|
|
||||||
fclose($input);
|
|
||||||
} else {
|
|
||||||
$process = proc_open(
|
|
||||||
['bash', '-c',
|
|
||||||
"curl -s " . escapeshellarg($url) . " | " .
|
|
||||||
"pdftotext -raw - -"],
|
|
||||||
$fd_spec,
|
|
||||||
$pipes
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose($pipes[0]);
|
|
||||||
$text = stream_get_contents($pipes[1]);
|
|
||||||
fclose($pipes[1]);
|
|
||||||
$stderr = stream_get_contents($pipes[2]);
|
|
||||||
fclose($pipes[2]);
|
|
||||||
$return_value = proc_close($process);
|
|
||||||
|
|
||||||
if ($stderr !== '') {
|
|
||||||
header('Status: 500');
|
header('Status: 500');
|
||||||
header('Content-Length: ' . strlen($stderr));
|
header('Content-Length: 0');
|
||||||
header('Content-Type: text/plain');
|
exit;
|
||||||
exit($stderr);
|
|
||||||
}
|
}
|
||||||
|
$text = implode("\n", $text);
|
||||||
|
exec("pdfsig " . escapeshellarg($filename), $sig);
|
||||||
|
$sig = implode("\n", $sig);
|
||||||
|
|
||||||
$r = preg_match('@([a-z]{2}) (https://webgate\.ec\.europa\.eu/tracesnt/directory/publication/organic-operator/(.*?)\.pdf) (\d+) / (\d+)@', $text, $matches);
|
$r = preg_match('@([a-z]{2}) (https://webgate\.ec\.europa\.eu/tracesnt/directory/publication/organic-operator/(.*?)\.pdf) (\d+) / (\d+)@', $text, $matches);
|
||||||
if ($r === 1) {
|
if ($r === 1) {
|
||||||
@@ -189,6 +163,31 @@ if ($format === 'text') {
|
|||||||
$valid1 = implode('-', array_reverse(explode('/', $matches[0][0])));
|
$valid1 = implode('-', array_reverse(explode('/', $matches[0][0])));
|
||||||
$valid2 = implode('-', array_reverse(explode('/', $matches[1][0])));
|
$valid2 = implode('-', array_reverse(explode('/', $matches[1][0])));
|
||||||
|
|
||||||
|
$sigs = [];
|
||||||
|
foreach (array_slice(explode("\nSignature #", $sig), 1) as $s) {
|
||||||
|
$sData = [];
|
||||||
|
$sData2 = [];
|
||||||
|
preg_match_all('/\n {2}- (([^:\n]*): )?([^\n]*)/', $s, $matches, PREG_SET_ORDER);
|
||||||
|
foreach ($matches as $m) {
|
||||||
|
if (strlen($m[2]) === 0) {
|
||||||
|
$sData2[] = $m[3];
|
||||||
|
} else {
|
||||||
|
$sData[$m[2]] = $m[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$sigs[] = [
|
||||||
|
'signerCommonName' => $sData['Signer Certificate Common Name'],
|
||||||
|
'valid' => $sData['Signature Validation'] === 'Signature is Valid.',
|
||||||
|
'trusted' => $sData['Certificate Validation'] === 'Certificate is Trusted.',
|
||||||
|
'totalDocument' => in_array('Total document signed', $sData2),
|
||||||
|
'timestamp' => gmdate('Y-m-d\TH:i:s\Z', strtotime($sData['Signing Time'])),
|
||||||
|
'type' => $sData['Signature Type'],
|
||||||
|
'hashAlgorithm' => $sData['Signing Hash Algorithm'],
|
||||||
|
'signerDistinguishedName' => $sData['Signer full Distinguished Name'],
|
||||||
|
'fieldName' => $sData['Signature Field Name'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
echo "{\"type\":\"traces\",\"lang\":\"$lang\",\"id\":\"$certId\",\"status\":\"$statusMap[$status]\"";
|
echo "{\"type\":\"traces\",\"lang\":\"$lang\",\"id\":\"$certId\",\"status\":\"$statusMap[$status]\"";
|
||||||
echo ",\n \"operator\":{\"id\":" . jenc($operatorId).
|
echo ",\n \"operator\":{\"id\":" . jenc($operatorId).
|
||||||
',"groupOfOperators":' . jenc(!str_starts_with($data['I.2'], '☑')) .
|
',"groupOfOperators":' . jenc(!str_starts_with($data['I.2'], '☑')) .
|
||||||
@@ -207,23 +206,34 @@ if ($format === 'text') {
|
|||||||
",\n \"productCategories\":" . jenc($products) .
|
",\n \"productCategories\":" . jenc($products) .
|
||||||
",\n \"validFrom\":" . jenc($valid1) .
|
",\n \"validFrom\":" . jenc($valid1) .
|
||||||
',"validTo":' . jenc($valid2) .
|
',"validTo":' . jenc($valid2) .
|
||||||
",\n \"url\":\"$certUrl\"\n}\n";
|
",\n \"url\":\"$certUrl\"" .
|
||||||
} else {
|
",\n \"digitalSignatures\":" . jenc($sigs) .
|
||||||
echo "{\"type\":\"unknown\"}\n";
|
"\n}\n";
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
$fd_spec = [
|
|
||||||
0 => ["pipe", "r"], // stdin
|
|
||||||
1 => ["pipe", "w"], // stdout
|
|
||||||
2 => ["pipe", "w"], // stderr
|
|
||||||
3 => ["pipe", "w"], // headers
|
|
||||||
];
|
|
||||||
$process = proc_open(['curl', '-s', '-D', '/dev/fd/3', $url], $fd_spec, $pipes);
|
|
||||||
fclose($pipes[0]);
|
|
||||||
|
|
||||||
|
if (preg_match('/AT-BIO-[0-9]{3}/', $text, $matches) === 1) {
|
||||||
|
$authorityId = $matches[0];
|
||||||
|
$certId = null;
|
||||||
|
$certNr = null;
|
||||||
|
if (preg_match("/$authorityId\.040-[0-9]{7}\.[0-9]{4}\.[0-9]{3}/", $text, $matches) === 1)
|
||||||
|
$certId = $matches[0];
|
||||||
|
if (preg_match_all("/\b[0-9]+([._-])[0-9]+\g{-1}[0-9]+\b/", $text, $matches, PREG_SET_ORDER) !== false) {
|
||||||
|
foreach ($matches as $m) {
|
||||||
|
if (strlen($m[0]) > 10 && !str_ends_with($certId, $m[0]))
|
||||||
|
$certNr = $m[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo "{\"type\":\"$authorityId\",\"lang\":\"de\",\"id\":" . jenc($certId) . ",\"nr\":" . jenc($certNr);
|
||||||
|
echo ",\n \"operator\":{},\n \"authority\":{\"id\":" . jenc($authorityId) . "}}\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "{\"type\":\"unknown\"}\n";
|
||||||
|
} else {
|
||||||
$headers = [];
|
$headers = [];
|
||||||
$status_code = null;
|
$status_code = null;
|
||||||
while (($line = fgets($pipes[3])) !== false) {
|
foreach (explode("\n", file_get_contents($headerfilename)) as $line) {
|
||||||
if (trim($line) === '') break;
|
if (trim($line) === '') break;
|
||||||
if ($status_code === null) {
|
if ($status_code === null) {
|
||||||
$status_code = intval(explode(' ', $line)[1]);
|
$status_code = intval(explode(' ', $line)[1]);
|
||||||
@@ -236,9 +246,8 @@ if ($format === 'text') {
|
|||||||
$v = trim($v);
|
$v = trim($v);
|
||||||
$headers[$k] = $v;
|
$headers[$k] = $v;
|
||||||
}
|
}
|
||||||
fclose($pipes[3]);
|
|
||||||
|
|
||||||
if ($status_code === 200 && str_starts_with($headers['content-type'], "application/pdf")) {
|
if (str_starts_with($headers['content-type'], "application/pdf")) {
|
||||||
header('Content-Type: application/pdf');
|
header('Content-Type: application/pdf');
|
||||||
$content_length = null;
|
$content_length = null;
|
||||||
if (isset($headers['content-length'])) {
|
if (isset($headers['content-length'])) {
|
||||||
@@ -246,20 +255,15 @@ if ($format === 'text') {
|
|||||||
header('Content-Length: ' . $headers['content-length']);
|
header('Content-Length: ' . $headers['content-length']);
|
||||||
}
|
}
|
||||||
$parts = explode('/', $url);
|
$parts = explode('/', $url);
|
||||||
$filename = $parts[sizeof($parts) - 1];
|
$realFilename = $parts[sizeof($parts) - 1];
|
||||||
if (isset($headers['content-disposition'])) {
|
if (isset($headers['content-disposition'])) {
|
||||||
preg_match('@filename="(.*?)"@', $headers['content-disposition'], $matches);
|
preg_match('@filename="(.*?)"@', $headers['content-disposition'], $matches);
|
||||||
$filename = $matches[1];
|
$realFilename = $matches[1];
|
||||||
}
|
}
|
||||||
header('Content-Disposition: inline; filename="' . $filename . '"');
|
header('Content-Disposition: inline; filename="' . $realFilename . '"');
|
||||||
fpassthru($pipes[1]);
|
fpassthru($file);
|
||||||
} else {
|
} else {
|
||||||
header('Status: 500');
|
header('Status: 500');
|
||||||
header('Content-Length: 0');
|
header('Content-Length: 0');
|
||||||
}
|
}
|
||||||
fclose($pipes[1]);
|
|
||||||
|
|
||||||
$stderr = stream_get_contents($pipes[2]);
|
|
||||||
fclose($pipes[2]);
|
|
||||||
$return_value = proc_close($process);
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user