347 lines
13 KiB
PHP
347 lines
13 KiB
PHP
<?php
|
|
|
|
require "../.php/pdf.php";
|
|
|
|
header('Access-Control-Allow-Origin: *');
|
|
header('Content-Type: application/json; charset=UTF-8');
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'GET' && $_SERVER['REQUEST_METHOD'] !== 'HEAD') {
|
|
header('Status: 405');
|
|
header('Content-Length: 56');
|
|
header('Allow: GET, HEAD');
|
|
echo "{\"error\":\"method not allowed\",\"allow\":[\"GET\",\"HEAD\"]}\n";
|
|
exit;
|
|
}
|
|
|
|
function jenc($data): string {
|
|
return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
|
}
|
|
|
|
function jget($url): array | null {
|
|
$s = curl_init($url);
|
|
curl_setopt($s, CURLOPT_RETURNTRANSFER, true);
|
|
if (($json = curl_exec($s)) === false) {
|
|
return null;
|
|
}
|
|
return json_decode($json, true);
|
|
}
|
|
|
|
function pdf_fetch($url): array | null {
|
|
$s = curl_init("https://elwig.at/organic/pdf?format=json&url=" . urlencode($url));
|
|
curl_setopt($s, CURLOPT_RETURNTRANSFER, true);
|
|
if (($json = curl_exec($s)) === false) {
|
|
return null;
|
|
}
|
|
return json_decode($json, true);
|
|
}
|
|
|
|
function update_local(string $ooId, array $new): bool {
|
|
$existed = file_exists(".ids/$ooId.txt");
|
|
if (!($file = fopen(".ids/$ooId.txt", 'c+')))
|
|
return !$existed;
|
|
$data = [];
|
|
while (($line = fgets($file)) !== false) {
|
|
[$k,$v] = explode(':', trim($line), 2);
|
|
$data[$k] = $v;
|
|
}
|
|
foreach ($new as $k => $v) {
|
|
if ($v !== null)
|
|
$data[$k] = $v;
|
|
}
|
|
fseek($file, 0);
|
|
ftruncate($file, 0);
|
|
foreach ($data as $k => $v) {
|
|
fwrite($file, "$k:$v\n");
|
|
}
|
|
fclose($file);
|
|
return !$existed;
|
|
}
|
|
|
|
function find_local(string $anyId): string | null {
|
|
$found = [];
|
|
foreach (scandir('.ids/') as $file) {
|
|
if (!str_ends_with($file, '.txt')) continue;
|
|
$data = file_get_contents(".ids/$file");
|
|
if (str_contains($data, "\n$anyId\n"))
|
|
$found[] = substr($file, 0, strlen($file) - 4);
|
|
}
|
|
return sizeof($found) === 1 ? $found[0] : null;
|
|
}
|
|
|
|
function update_cache(string $country, string $postalCode): void {
|
|
$anyNew = false;
|
|
$traces = jget("https://webgate.ec.europa.eu/tracesnt/directory/publication/organic-operator/for/query?countryCode=$country&operatorPostalCode=$postalCode&sort=issuedOn");
|
|
foreach ($traces as $op) {
|
|
// traces
|
|
$ooId = $op['operatorIdentifier'];
|
|
$name = $op['operator']['name'];
|
|
$address = $op['operator']['address']['street']['value'];
|
|
$cityPostalCode = $op['operator']['address']['cityReference']['postalCode'];
|
|
$cityName = $op['operator']['address']['cityReference']['name'];
|
|
$new = update_local($ooId, ['plz' => $postalCode, 'name' => "$name|$address|$cityPostalCode $cityName"]);
|
|
$anyNew = $anyNew || $new;
|
|
}
|
|
if (!$anyNew) return;
|
|
|
|
$m = curl_multi_init();
|
|
$requests = [];
|
|
foreach (['easy-cert', 'bioc', 'bioqs', 'lkv'] as $api) {
|
|
$s = curl_init("https://elwig.at/organic/external/$api/operators?country=$country&postalCode=$postalCode");
|
|
$requests[] = $s;
|
|
curl_setopt($s, CURLOPT_RETURNTRANSFER, true);
|
|
curl_multi_add_handle($m, $s);
|
|
}
|
|
|
|
$running = 1;
|
|
do {
|
|
curl_multi_exec($m, $running);
|
|
if ($running) usleep(250_000);
|
|
} while ($running);
|
|
foreach ($requests as $r) {
|
|
curl_multi_remove_handle($m, $r);
|
|
}
|
|
curl_multi_close($m);
|
|
$data = [];
|
|
foreach ($requests as $s) {
|
|
if (($json = curl_multi_getcontent($s)) === null) {
|
|
header('Status: 500');
|
|
header('Content-Length: 34');
|
|
echo "{\"error\":\"internal server error\"}\n";
|
|
exit;
|
|
}
|
|
$data[] = json_decode($json, true)['data'];
|
|
}
|
|
|
|
foreach ($data[0] as $op) {
|
|
// easy-cert
|
|
$ooId = find_local("easy-cert:$op[db]:$op[id]");
|
|
$lfbisNr = null;
|
|
if ($ooId === null && ($opDetails = jget($op['url'])) !== null) {
|
|
foreach ($opDetails['certificates'] as $cert) {
|
|
if (preg_match("/\.([0-9]{3}-[0-9]{7})\./", $cert['nr'], $matches) === 1) {
|
|
$ooId = $matches[1];
|
|
}
|
|
}
|
|
if ($ooId === null || $lfbisNr === null) {
|
|
foreach ($opDetails['certificates'] as $cert) {
|
|
if ($cert['pdfUrl'] === null) continue;
|
|
$pdfDetails = pdf_fetch($cert['pdfUrl']);
|
|
if (isset($pdfDetails['operator']['lfbisNr'])) $lfbisNr = $pdfDetails['operator']['lfbisNr'];
|
|
if (!isset($pdfDetails['id'])) continue;
|
|
if (preg_match("/\.([0-9]{3}-[0-9]{7})\./", $pdfDetails['id'], $matches) === 1) {
|
|
$ooId = $matches[1];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ($ooId === null)
|
|
continue;
|
|
update_local($ooId, ['plz' => $postalCode, 'lfbis' => $lfbisNr, 'easy-cert' => "$op[db]:$op[id]"]);
|
|
}
|
|
foreach ($data[1] as $op) {
|
|
// bioc
|
|
$ooId = find_local("bioc:$op[id]");
|
|
if ($ooId === null && ($opDetails = jget($op['url'])) !== null) {
|
|
foreach ($opDetails['certificates'] as $cert) {
|
|
if (preg_match("/\.([0-9]{3}-[0-9]{7})\./", $cert['nr'], $matches) === 1) {
|
|
$ooId = $matches[1];
|
|
}
|
|
}
|
|
if ($ooId === null) {
|
|
foreach ($opDetails['certificates'] as $cert) {
|
|
if ($cert['pdfUrl'] === null) continue;
|
|
$pdfDetails = pdf_fetch($cert['pdfUrl']);
|
|
if (isset($pdfDetails['operator']['lfbisNr'])) $op['lfbisNr'] = $pdfDetails['operator']['lfbisNr'];
|
|
if (!isset($pdfDetails['id'])) continue;
|
|
if (preg_match("/\.([0-9]{3}-[0-9]{7})\./", $pdfDetails['id'], $matches) === 1) {
|
|
$ooId = $matches[1];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ($ooId === null)
|
|
continue;
|
|
update_local($ooId, ['plz' => $postalCode, 'bioc' => "$op[id]"]);
|
|
}
|
|
foreach ($data[2] as $op) {
|
|
// bioqs
|
|
$ooId = find_local("bioqs:$op[id]");
|
|
$lfbisNr = null;
|
|
if ($ooId === null || $lfbisNr === null) {
|
|
foreach ($op['certificates'] as $cert) {
|
|
if (preg_match("/\.([0-9]{3}-[0-9]{7})\./", $cert['nr'], $matches) === 1) {
|
|
$ooId = $matches[1];
|
|
}
|
|
}
|
|
if ($ooId === null || $lfbisNr === null) {
|
|
foreach ($op['certificates'] as $cert) {
|
|
if ($cert['pdfUrl'] === null) continue;
|
|
$pdfDetails = pdf_fetch($cert['pdfUrl']);
|
|
if (isset($pdfDetails['operator']['lfbisNr'])) $lfbisNr = $pdfDetails['operator']['lfbisNr'];
|
|
if (!isset($pdfDetails['id'])) continue;
|
|
if (preg_match("/\.([0-9]{3}-[0-9]{7})\./", $pdfDetails['id'], $matches) === 1) {
|
|
$ooId = $matches[1];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ($ooId === null)
|
|
continue;
|
|
update_local($ooId, ['plz' => $postalCode, 'lfbis' => $lfbisNr, 'bioqs' => "$op[id]"]);
|
|
}
|
|
foreach ($data[3] as $op) {
|
|
// lkv
|
|
$ooId = find_local("lkv:$op[id]");
|
|
if ($ooId === null)
|
|
continue;
|
|
update_local($ooId, ['plz' => $postalCode, 'lfbis' => $op['lfbisNr'], 'lkv' => "$op[id]"]);
|
|
update_local($ooId, ['plz' => $postalCode, 'lfbis' => $op['lfbisNr'], 'lkv' => "$op[id]"]);
|
|
}
|
|
}
|
|
|
|
$info = substr($_SERVER['PATH_INFO'], 1);
|
|
if ($info === '') {
|
|
// search
|
|
$limit = $_GET['limit'] ?? null;
|
|
$offset = intval($_GET['offset'] ?? "0");
|
|
if ($limit === '') $limit = null;
|
|
if ($limit !== null) $limit = intval($limit);
|
|
|
|
$country = $_GET['country'] ?? null;
|
|
$postalCode = $_GET['postalCode'] ?? null;
|
|
if ($country === null || $postalCode === null) {
|
|
header('Status: 400');
|
|
header('Content-Length: 109');
|
|
echo "{\"error\":\"bad request\",\"message\":\"The 'country' and 'postalCode' request URL query parameters are required\"}\n";
|
|
exit;
|
|
}
|
|
|
|
update_cache($country, $postalCode);
|
|
|
|
echo "{\"data\":[";
|
|
if ($country === 'AT') {
|
|
$first = true;
|
|
foreach (scandir('.ids/') as $file) {
|
|
if (!str_ends_with($file, '.txt') || !str_starts_with($file, '040-')) continue;
|
|
$id = substr($file, 0, strlen($file) - 4);
|
|
$data = file_get_contents(".ids/$file");
|
|
if (str_starts_with($data, "plz:$postalCode\n")) {
|
|
preg_match("/^name:(.*?)\|(.*?)\|([0-9]{4}) (.*?)$/m", $data, $name);
|
|
preg_match("/^lfbis:(.*?)$/m", $data, $lfbis);
|
|
if (!$first) echo ",";
|
|
echo "\n ";
|
|
echo jenc([
|
|
'id' => $id,
|
|
'lfbisNr' => $lfbis[1],
|
|
'name' => $name[1],
|
|
'address' => $name[2],
|
|
'postalCode' => $name[3],
|
|
'city' => $name[4],
|
|
'country' => $country,
|
|
'url' => "https://elwig.at/organic/operators/$id",
|
|
]);
|
|
$first = false;
|
|
}
|
|
}
|
|
}
|
|
echo "\n]}\n";
|
|
|
|
exit;
|
|
}
|
|
|
|
if (preg_match("/^((easy-cert:[a-z]+|bioqs|bioc|lkv):[0-9a-zA-Z-_]+|lfbis:[0-9]+)$/", $info) === 1) {
|
|
$found = find_local($info);
|
|
if ($found !== null) {
|
|
header('Status: 303');
|
|
header('Location: /organic/operators/' . $found);
|
|
header('Content-Length: 0');
|
|
exit;
|
|
}
|
|
header('Status: 404');
|
|
header('Content-Length: 22');
|
|
echo "{\"error\":\"not found\"}\n";
|
|
exit;
|
|
} else if (!file_exists(".ids/$info.txt")) {
|
|
header('Status: 404');
|
|
header('Content-Length: 22');
|
|
echo "{\"error\":\"not found\"}\n";
|
|
exit;
|
|
}
|
|
|
|
$data = file_get_contents(".ids/$info.txt");
|
|
preg_match("/^name:(.*?)\|(.*?)\|([0-9]{4}) (.*?)$/m", $data, $name);
|
|
preg_match("/^lfbis:(.*?)$/m", $data, $lfbis);
|
|
preg_match("/^easy-cert:(.*?)$/m", $data, $easyCert);
|
|
preg_match("/^bioqs:(.*?)$/m", $data, $bioQs);
|
|
preg_match("/^bioc:(.*?)$/m", $data, $bioC);
|
|
|
|
if (sizeof($easyCert) > 1 && ($opDetails = jget("https://elwig.at/organic/external/easy-cert/operators/$easyCert[1]")) !== null) {
|
|
foreach ($opDetails['certificates'] as $cert) {
|
|
if ($cert['pdfUrl'] === null) continue;
|
|
pdf_fetch($cert['pdfUrl']);
|
|
}
|
|
}
|
|
if (sizeof($bioQs) > 1 && ($opDetails = jget("https://elwig.at/organic/external/bioqs/operators/$bioQs[1]")) !== null) {
|
|
foreach ($opDetails['certificates'] as $cert) {
|
|
if ($cert['pdfUrl'] === null) continue;
|
|
pdf_fetch($cert['pdfUrl']);
|
|
}
|
|
}
|
|
if (sizeof($bioC) > 1 && ($opDetails = jget("https://elwig.at/organic/external/bioc/operators/$bioC[1]")) !== null) {
|
|
foreach ($opDetails['certificates'] as $cert) {
|
|
if ($cert['pdfUrl'] === null) continue;
|
|
pdf_fetch($cert['pdfUrl']);
|
|
}
|
|
}
|
|
|
|
$certs = [];
|
|
$certIds = [];
|
|
foreach (scandir('../certificates/') as $file) {
|
|
if (!str_contains($file, ".$info."))
|
|
continue;
|
|
$certId = substr($file, 0, 31);
|
|
if (in_array($certId, $certIds))
|
|
continue;
|
|
$certIds[] = $certId;
|
|
$cert = parse_pdf("../certificates/$certId.pdf");
|
|
$appendix = parse_pdf("../certificates/$certId.appendix.pdf");
|
|
if ($cert === null && $appendix === null)
|
|
continue;
|
|
|
|
$parts = explode('.', $file);
|
|
$certs[] = [
|
|
'id' => $certId,
|
|
'nr' => $appendix['nr'] ?? null,
|
|
'validFrom' => $cert['validFrom'] ?? null,
|
|
'validTo' => $cert['validTo'] ?? null,
|
|
'authority' => ['code' => $parts[0]],
|
|
'operator' => ['id' => $parts[1]],
|
|
'url' => "https://elwig.at/organic/certificates/$certId",
|
|
'tracesPdfUrl' => $cert !== null ? "https://elwig.at/organic/certificates/$certId.pdf" : null,
|
|
'appendixPdfUrl' => $appendix !== null ? "https://elwig.at/organic/certificates/$certId.appendix.pdf" : null,
|
|
];
|
|
}
|
|
|
|
$details = [];
|
|
if (preg_match("/^easy-cert:(.*?)$/m", $data, $easyCert) === 1)
|
|
$details[] = "https://elwig.at/organic/external/easy-cert/operators/$easyCert[1]";
|
|
if (preg_match("/^bioc:(.*?)$/m", $data, $bioc) === 1)
|
|
$details[] = "https://elwig.at/organic/external/bioc/operators/$bioc[1]";
|
|
if (preg_match("/^bioqs:(.*?)$/m", $data, $bioqs) === 1)
|
|
$details[] = "https://elwig.at/organic/external/bioqs/operators/$bioqs[1]";
|
|
if (preg_match("/^lkv:(.*?)$/m", $data, $lkv) === 1)
|
|
$details[] = "https://elwig.at/organic/external/lkv/operators/$lkv[1]";
|
|
echo jenc([
|
|
'id' => $info,
|
|
'lfbisNr' => $lfbis[1],
|
|
'name' => $name[1],
|
|
'address' => $name[2],
|
|
'postalCode' => $name[3],
|
|
'city' => $name[4],
|
|
'country' => 'AT',
|
|
'url' => "https://elwig.at/organic/operators/$info",
|
|
'tracesUrl' => "https://webgate.ec.europa.eu/tracesnt/directory/publication/organic-operator/index#!?query=$info",
|
|
'originUrls' => $details,
|
|
'certificates' => $certs,
|
|
]);
|