Compare commits
2
Commits
028c16be3d
...
1b413cf301
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b413cf301 | ||
|
|
4572323a14 |
+12
-1
@@ -35,7 +35,7 @@
|
||||
<li><a href="#about">Über</a></li>
|
||||
<li><a href="#clients">Genossenschaften</a></li>
|
||||
<li><a href="/de/vorschau">Vorschau</a></li>
|
||||
<li><a href="/files/">Downloads</a></li>
|
||||
<li><a href="/files/elwig/">Downloads</a></li>
|
||||
<li><a href="https://git.necronda.net/winzer/">Quellcode</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
@@ -152,6 +152,17 @@
|
||||
</p>
|
||||
<div class="edge"></div><div class="edge"></div><div class="edge"></div><div class="edge"></div>
|
||||
</div>
|
||||
<div class="filling"></div>
|
||||
<div>
|
||||
<h4>Winzerkeller Seewinkel</h4>
|
||||
<h5><span>Winzerkeller Seewinkel</span><br/><span>reg. Gen.m.b.H.</span></h5>
|
||||
<h6>Zweigstellen:</h6>
|
||||
<div class="branches">Pamhagen</div>
|
||||
<p class="link">
|
||||
<a href="https://www.winzerkeller-seewinkel.at/">winzerkeller-seewinkel.at</a>
|
||||
</p>
|
||||
<div class="edge"></div><div class="edge"></div><div class="edge"></div><div class="edge"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
+12
-1
@@ -35,7 +35,7 @@
|
||||
<li><a href="#about">About</a></li>
|
||||
<li><a href="#clients">Cooperatives</a></li>
|
||||
<li><a href="/en/preview">Preview</a></li>
|
||||
<li><a href="/files/">Downloads</a></li>
|
||||
<li><a href="/files/elwig/">Downloads</a></li>
|
||||
<li><a href="https://git.necronda.net/winzer/">Source Code</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
@@ -152,6 +152,17 @@
|
||||
</p>
|
||||
<div class="edge"></div><div class="edge"></div><div class="edge"></div><div class="edge"></div>
|
||||
</div>
|
||||
<div class="filling"></div>
|
||||
<div>
|
||||
<h4>Winzerkeller Seewinkel</h4>
|
||||
<h5><span>Winzerkeller Seewinkel</span><br/><span>reg. Gen.m.b.H.</span></h5>
|
||||
<h6>Zweigstellen:</h6>
|
||||
<div class="branches">Pamhagen</div>
|
||||
<p class="link">
|
||||
<a href="https://www.winzerkeller-seewinkel.at/">winzerkeller-seewinkel.at</a>
|
||||
</p>
|
||||
<div class="edge"></div><div class="edge"></div><div class="edge"></div><div class="edge"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
+7
-2
@@ -61,9 +61,11 @@ if (sizeof($info) > 0 && $info[1] === 'stat') {
|
||||
header('Content-Length: 0');
|
||||
header('Location: /stat');
|
||||
exit();
|
||||
} else if (sizeof($info) > 1 && ($info[1] === 'elwig' || $info[1] === 'winziprint')) {
|
||||
} else if (sizeof($info) > 1 && ($info[1] === 'elwig' || $info[1] === 'winziprint' || $info[1] === 'pamhagen-sysctrl')) {
|
||||
$getProd = $info[1];
|
||||
if (sizeof($info) > 2) $getVers = $info[2];
|
||||
if (sizeof($info) > 2 && !empty($info[2])) {
|
||||
$getVers = $info[2];
|
||||
}
|
||||
if (sizeof($info) > 3) {
|
||||
header('Status: 404');
|
||||
header('Content-Length: 0');
|
||||
@@ -94,6 +96,9 @@ foreach ($files as $name => [$size, $mtime, $ctime]) {
|
||||
} else {
|
||||
$vers = substr($name, $p1 + 1, $p2 - $p1 - 1);
|
||||
$prod = strtolower(substr($name, 0, $p1));
|
||||
if ($prod === 'pamhagensysctrl') {
|
||||
$prod = 'pamhagen-sysctrl';
|
||||
}
|
||||
}
|
||||
$mod = date(DATE_ATOM, $mtime);
|
||||
$cre = date(DATE_ATOM, $ctime);
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
function get_address($array, $from, $to): array {
|
||||
$address = [];
|
||||
$postalCode = [];
|
||||
$city = [];
|
||||
for ($i = $to; $i >= $from; $i--) {
|
||||
$el = $array[$i];
|
||||
if (sizeof($postalCode) > 0) {
|
||||
if (sizeof($address) === 0) $el = rtrim($el, ", \n\r\t\v\0");
|
||||
if (strlen($el) === 0) continue;
|
||||
array_unshift($address, $el);
|
||||
} else if (preg_match("/^[A-Z0-9.\-]{3,},?$/", $el)) {
|
||||
array_unshift($postalCode, trim($el, ", \n\r\t\v\0"));
|
||||
} else {
|
||||
array_unshift($city, $el);
|
||||
}
|
||||
}
|
||||
return [implode(' ', $address), implode(' ', $postalCode), implode(' ', $city)];
|
||||
}
|
||||
|
||||
function parse_pdf(string $filename, bool $loadUrl = false): array | null {
|
||||
if (!file_exists($filename))
|
||||
return null;
|
||||
if (exec("pdftotext -raw " . escapeshellarg($filename) . " -", $text) === false)
|
||||
return null;
|
||||
|
||||
$text = implode("\n", $text);
|
||||
exec("pdfsig " . escapeshellarg($filename), $sig);
|
||||
$sig = implode("\n", $sig);
|
||||
|
||||
if ($loadUrl) {
|
||||
$prefix = "/tmp/pdfimages-" . uniqid();
|
||||
exec("zbarimg -q --raw $(pdfimages -print-filenames " . escapeshellarg($filename) . " $prefix) | uniq; rm -rf $prefix-*.*", $qrCodes);
|
||||
} else {
|
||||
$qrCodes = null;
|
||||
}
|
||||
|
||||
$r = preg_match('@([a-z]{2}) (https://webgate\.ec\.europa\.eu/tracesnt/directory/publication/organic-operator/(.*?)\.pdf) (\d+) / (\d+)@', $text, $matches);
|
||||
if ($r === 1) {
|
||||
// TRACES certificate
|
||||
|
||||
$data = [];
|
||||
$parts = preg_split('@\n(I+\.\d+) ([^\n]*)@', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$status = str_replace("\n", '', $parts[0]);
|
||||
for ($i = 3; $i < sizeof($parts); $i += 3) {
|
||||
$data[$parts[$i - 2]] = trim($parts[$i]);
|
||||
}
|
||||
|
||||
$lang = $matches[1];
|
||||
$splitAddr = [
|
||||
'de' => 'Adresse',
|
||||
'en' => 'Address',
|
||||
][$lang];
|
||||
$splitCountry = [
|
||||
'de' => 'Land',
|
||||
'en' => 'Country',
|
||||
][$lang];
|
||||
$statusMap = [
|
||||
'de' => [
|
||||
'AUSGESTELLT' => 'issued',
|
||||
],
|
||||
'en' => [
|
||||
'ISSUED' => 'issued',
|
||||
]
|
||||
][$lang];
|
||||
$activityMap = [
|
||||
'de' => [
|
||||
'Aufbereitung' => 'preparation',
|
||||
'Ausfuhr' => 'export',
|
||||
'Einfuhr' => 'import',
|
||||
'Lagerung' => 'storing',
|
||||
'Produktion' => 'production',
|
||||
'Vertrieb' => 'distribution',
|
||||
'Vertrieb/Inverkehrbringen' => 'distribution_placing_on_the_market',
|
||||
],
|
||||
'en' => [
|
||||
'Distribution' => 'distribution',
|
||||
'Distribution/Placing on the market' => 'distribution_placing_on_the_market',
|
||||
'Export' => 'export',
|
||||
'Import' => 'import',
|
||||
'Preparation' => 'preparation',
|
||||
'Production' => 'production',
|
||||
'Storing' => 'storing',
|
||||
],
|
||||
][$lang];
|
||||
|
||||
$certUrl = $matches[2];
|
||||
$certId = $matches[3];
|
||||
$authorityId = explode('.', $certId)[0];
|
||||
$operatorId = explode('.', $certId)[1];
|
||||
$operator = preg_split('@\s+@', trim($data['I.3']));
|
||||
$p1 = array_search($splitAddr, $operator);
|
||||
$p2 = array_search($splitCountry, $operator);
|
||||
$operatorName = trim(implode(' ', array_filter($operator, fn($k,$i) => $i > 0 && $i < $p1, ARRAY_FILTER_USE_BOTH)), ', ');
|
||||
[$opAddr, $opPostal, $opCity] = get_address($operator, $p1 + 1, $p2 - 1);
|
||||
|
||||
$authority = preg_split('@\s+@', trim($data['I.4']));
|
||||
$until = array_search("($authorityId)", $authority);
|
||||
$p1 = array_search($splitAddr, $authority);
|
||||
$p2 = array_search($splitCountry, $authority);
|
||||
$authorityName = implode(' ', array_filter($authority, fn($k,$i) => $i > 0 && $i < $p1 - 1 && ($i !== $p1 - 2 || !str_starts_with($k, '(')), ARRAY_FILTER_USE_BOTH));
|
||||
[$aAddr, $aPostal, $aCity] = get_address($authority, $p1 + 1, $p2 - 1);
|
||||
|
||||
$activities = [];
|
||||
foreach (explode("\n", $data['I.5']) as $a) {
|
||||
$activities[] = $activityMap[trim($a, '• ')];
|
||||
}
|
||||
|
||||
preg_match_all('/\([a-g]\)/', $data['I.6'], $matches, PREG_SET_ORDER);
|
||||
$products = [];
|
||||
foreach ($matches as $m) {
|
||||
$products[] = $m[0];
|
||||
}
|
||||
|
||||
preg_match_all('@\d+/\d+/\d+@', $data['I.8'], $matches, PREG_SET_ORDER);
|
||||
$valid1 = implode('-', array_reverse(explode('/', $matches[0][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'],
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'type' => 'traces',
|
||||
'lang' => $lang,
|
||||
'id' => $certId,
|
||||
'status' => $statusMap[$status],
|
||||
'operator' => [
|
||||
'id' => $operatorId,
|
||||
'groupOfOperators' => !str_starts_with($data['I.2'], '☑'),
|
||||
'name' => $operatorName,
|
||||
'address' => $opAddr,
|
||||
'postalCode' => $opPostal,
|
||||
'city' => $opCity,
|
||||
'countryCode' => $operator[sizeof($operator) - 1],
|
||||
],
|
||||
'authority' => [
|
||||
'id' => $authorityId,
|
||||
'name' => $authorityName,
|
||||
'address' => $aAddr,
|
||||
'postalCode' => $aPostal,
|
||||
'city' => $aCity,
|
||||
'countryCode' => $authority[sizeof($authority) - 1],
|
||||
],
|
||||
'activities' => $activities,
|
||||
'productCategories' => $products,
|
||||
'validFrom' => $valid1,
|
||||
'validTo' => $valid2,
|
||||
'url' => $certUrl,
|
||||
'digitalSignatures' => $sigs,
|
||||
'qrCodes' => $qrCodes,
|
||||
];
|
||||
}
|
||||
|
||||
$isLacon = str_contains($text, "\nLACON GmbH\n") && (str_contains($text, "\nAnlage zum Zertifikat\n"));
|
||||
if (preg_match('/AT-BIO-[0-9]{3}/', $text, $matches) === 1 || $isLacon) {
|
||||
$authorityId = $matches[0] ?? ($isLacon ? 'AT-BIO-402' : null);
|
||||
$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];
|
||||
}
|
||||
}
|
||||
|
||||
if ($certId === null && $qrCodes !== null && sizeof($qrCodes) > 0 && str_starts_with($qrCodes[0], 'www.easy-cert.com/')) {
|
||||
$res = exec("curl -L " . escapeshellarg($qrCodes[0]) . " | grep -A 100 '<table' | grep -B 100 '</table>' | sed 's/<[^>]*>//g;s/\\s\\+/ /g;s/^ //g;s/ $//g;s/\\n//m' | grep 'Certificate number' -A 1");
|
||||
if ($res !== false && preg_match("/$authorityId\.040-[0-9]{7}\.[0-9]{4}\.[0-9]{3}/", $res, $matches) === 1) {
|
||||
$certId = $matches[0];
|
||||
}
|
||||
}
|
||||
|
||||
$operator = ['lfbisNr' => null];
|
||||
if ($authorityId === 'AT-BIO-301') {
|
||||
// TODO
|
||||
} else if ($authorityId === 'AT-BIO-302') {
|
||||
if (preg_match("/^lfbis[^0-9]*([0-9]{6,7})$/im", $text, $matches) === 1)
|
||||
$operator['lfbisNr'] = str_pad($matches[1], 7, '0', STR_PAD_LEFT);
|
||||
} else if ($authorityId === 'AT-BIO-401') {
|
||||
// TODO
|
||||
} else if ($authorityId === 'AT-BIO-402') {
|
||||
if (preg_match("/^Betriebsnummer ([0-9]{6,7})$/im", $text, $matches) === 1)
|
||||
$operator['lfbisNr'] = str_pad($matches[1], 7, '0', STR_PAD_LEFT);
|
||||
} else if ($authorityId === 'AT-BIO-902') {
|
||||
if (preg_match("/ lfbis:([0-9]{6,7})$/im", $text, $matches) === 1)
|
||||
$operator['lfbisNr'] = str_pad($matches[1], 7, '0', STR_PAD_LEFT);
|
||||
} else if ($authorityId === 'AT-BIO-903') {
|
||||
// TODO
|
||||
}
|
||||
|
||||
return [
|
||||
'type' => $authorityId,
|
||||
'lang' => 'de',
|
||||
'id' => $certId,
|
||||
'nr' => $certNr,
|
||||
'operator' => $operator,
|
||||
'authority' => ['id' => $authorityId],
|
||||
'qrCodes' => $qrCodes,
|
||||
];
|
||||
}
|
||||
|
||||
return ['type' => 'unknown'];
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?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);
|
||||
}
|
||||
|
||||
$info = substr($_SERVER['PATH_INFO'], 1);
|
||||
if (strlen($info) !== 31) {
|
||||
header('Status: 404');
|
||||
header('Content-Length: 22');
|
||||
echo "{\"error\":\"not found\"}\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
$cert = parse_pdf("$info.pdf");
|
||||
$appendix = parse_pdf("$info.appendix.pdf");
|
||||
|
||||
if ($cert === null && $appendix === null) {
|
||||
header('Status: 404');
|
||||
header('Content-Length: 22');
|
||||
echo "{\"error\":\"not found\"}\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($cert !== null) $cert['pdfUrl'] = "https://elwig.at/organic/certificates/$info.pdf";
|
||||
if ($appendix !== null) $appendix['pdfUrl'] = "https://elwig.at/organic/certificates/$info.appendix.pdf";
|
||||
|
||||
echo jenc([
|
||||
'traces' => $cert,
|
||||
'appendix' => $appendix,
|
||||
]);
|
||||
+5
-5
@@ -121,7 +121,8 @@ if ($country === null) {
|
||||
|
||||
$data = [];
|
||||
|
||||
$url = "https://www.bioc.info/search/producerSearchQuery?search[name]=" . urlencode($name) . "&search[citycode]=" . urlencode($postalCode) . "&search[operatorId]=" . urlencode($idNr) . "&search[country]=$country";
|
||||
$origin = "https://www.bioc.info/search/producersearchresult?producerSearch%5Bcountry%5D={$country}&producerSearch%5Bcitycode%5D=" . urlencode($postalCode) . "&producerSearch%5Bname%5D=" . urlencode($name) . "&producerSearch%5BoperatorId%5D=" . urlencode($idNr);
|
||||
$url = "https://www.bioc.info/search/producerSearchQuery?search[country]={$country}&search[citycode]=" . urlencode($postalCode) . "&search[name]=" . urlencode($name) . "&search[operatorId]=" . urlencode($idNr);
|
||||
$m = curl_multi_init();
|
||||
$requests = [];
|
||||
foreach ($source_groups as $group) {
|
||||
@@ -134,6 +135,7 @@ foreach ($source_groups as $group) {
|
||||
$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);
|
||||
@@ -141,7 +143,7 @@ foreach ($requests as $r) {
|
||||
curl_multi_close($m);
|
||||
|
||||
foreach ($requests as $s) {
|
||||
if (($json = curl_multi_getcontent($s)) === false) {
|
||||
if (($json = curl_multi_getcontent($s)) === null) {
|
||||
header('Status: 500');
|
||||
header('Content-Length: 34');
|
||||
echo "{\"error\":\"internal server error\"}\n";
|
||||
@@ -153,10 +155,8 @@ foreach ($requests as $s) {
|
||||
}
|
||||
}
|
||||
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
|
||||
$first = true;
|
||||
echo "{\"data\":[\n";
|
||||
echo "{\"originUrl\":\"$origin\",\"data\":[\n";
|
||||
foreach ($data as $id => $row) {
|
||||
if (!$first) echo ",\n";
|
||||
$row = explode("</", $row);
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ def main() -> None:
|
||||
args = parser.parse_args()
|
||||
|
||||
s = requests.Session()
|
||||
s.verify = False
|
||||
while True:
|
||||
try:
|
||||
r = s.get(f'{URL}?menu_sid=5002')
|
||||
|
||||
+6
@@ -33,6 +33,8 @@ def main() -> None:
|
||||
query = {'PartnerCertSearchForm:pcs_' + q.split('=', 1)[0]: urllib.parse.unquote(q.split('=', 1)[-1]) for q in args.query.split('&')}
|
||||
|
||||
s = requests.Session()
|
||||
s.verify = False
|
||||
try:
|
||||
while True:
|
||||
try:
|
||||
r = s.get(f'{URL}?menu_sid=5002')
|
||||
@@ -56,6 +58,10 @@ def main() -> None:
|
||||
collapsed_rows = [[tuple(remove_tags((ATTACHMENT_RE.search(m[1]) or m)[1]) for m in TD_RE.finditer(row[1]))
|
||||
for row in ROW_RE.finditer(tbl[0])]
|
||||
for tbl in COLLAPSED_ROW_RE.finditer(result_table)]
|
||||
except:
|
||||
print('[]')
|
||||
return
|
||||
|
||||
print('[')
|
||||
first = True
|
||||
for row, tbl in zip(uncollapsed_rows, collapsed_rows):
|
||||
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
|
||||
$base = 'https://' . $_SERVER['SERVER_NAME'] . explode('?', $_SERVER['REQUEST_URI'])[0];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
$info = $_SERVER['PATH_INFO'];
|
||||
if ($info !== '') {
|
||||
header('Status: 404');
|
||||
header('Content-Length: 22');
|
||||
echo "{\"error\":\"not found\"}\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
$country = $_GET['country'] ?? null;
|
||||
$postalCode = $_GET['postalCode'] ?? null;
|
||||
|
||||
$m = curl_multi_init();
|
||||
$requests = [];
|
||||
foreach (['bioc', 'bioqs', 'easy-cert', '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'];
|
||||
}
|
||||
|
||||
$operators = [];
|
||||
|
||||
foreach ($data[2] as $op) $operators[] = ['easyCert' => $op];
|
||||
foreach ($data[0] as $op) {
|
||||
if (($m = array_find($operators, fn($o) => isset($o['easyCert']) && $o['easyCert']['id'] === $op['id'])) !== null) {
|
||||
$m['bioc'] = $op;
|
||||
} else if (isset($op['details']) && ($m = array_find($operators, fn($o) => isset($o['easyCert']) && $o['easyCert']['idNr'] === $op['details']['idNr'])) !== null) {
|
||||
$m['bioc'] = $op;
|
||||
} else if (isset($op['details']) && ($m = array_find($operators, fn($o) => isset($o['bioc']['details']) && isset($op['details']) && $o['bioc']['name'] === $op['name'] && $o['bioc']['details']['address'] === $op['details']['address'])) !== null) {
|
||||
$m['bioc'] = $op;
|
||||
} else {
|
||||
$operators[] = ['bioc' => $op];
|
||||
}
|
||||
}
|
||||
foreach ($data[1] as $op) {
|
||||
if (false) {
|
||||
|
||||
} else {
|
||||
$operators[] = ['bioqs' => $op];
|
||||
}
|
||||
}
|
||||
foreach ($data[3] as $op) $operators[] = ['lkv' => $op];
|
||||
|
||||
// for (const op of easyCert.data) operators.push({easyCert: op});
|
||||
// for (const op of bioc.data) {
|
||||
// let m;
|
||||
// if ((m = operators.find(o => o.easyCert?.id === op.id))) {
|
||||
// m.bioc = op;
|
||||
// } else if ((m = operators.find(o => o.easyCert?.idNr === op.details.idNr))) {
|
||||
// m.bioc = op;
|
||||
// } else if ((m = operators.find(o => o.bioc?.name === op.name && o.bioc?.details.address === op.details.address))) {
|
||||
// m.bioc2 = op;
|
||||
// } else {
|
||||
// operators.push({bioc: op});
|
||||
// }
|
||||
// }
|
||||
// for (const op of bioqs.data) {
|
||||
// let m;
|
||||
// if (op.lfbisNr && (m = operators.find(o => o.easyCert?.idNr === op.lfbisNr))) {
|
||||
// m.bioqs = op;
|
||||
// } else if (op.lfbisNr && (m = operators.find(o => o.bioc?.details.idNr === op.lfbisNr))) {
|
||||
// m.bioqs = op;
|
||||
// } else if (op.idNr && (m = operators.find(o => o.bioc?.details.idNr === op.idNr))) {
|
||||
// m.bioqs = op;
|
||||
// } else if ((m = operators.find(o => (o.easyCert?.name ?? o.bioc?.name) === op.name && (o.easyCert?.details.address ?? o.bioc?.details.address) === op.address))) {
|
||||
// m.bioqs = op;
|
||||
// } else {
|
||||
// operators.push({bioqs: op});
|
||||
// }
|
||||
// }
|
||||
// for (const op of lkv.data) operators.push({lkv: op});
|
||||
//
|
||||
// for (const op of operators) {
|
||||
// op.name = op.easyCert?.name ?? op.bioc?.name ?? op.bioqs?.name ?? op.lkv?.name ?? null;
|
||||
// op.address = op.easyCert?.details.address ?? op.bioc?.details.address ?? op.bioqs?.address ?? op.lkv?.address ?? null;
|
||||
// op.postalCode = op.easyCert?.postalCode ?? op.bioc?.postalCode ?? op.bioqs?.postalCode ?? op.lkv?.postalCode ?? null;
|
||||
// op.city = op.easyCert?.city ?? op.bioc?.city ?? op.bioqs?.city ?? op.lkv?.city ?? null;
|
||||
// op.countryCode = op.easyCert?.countryCode ?? op.bioc?.details.countryCode ?? 'AT';
|
||||
// op.lfbisNr = op.bioqs?.lfbisNr ?? null;
|
||||
// const certNrs = [...new Set([].concat(
|
||||
// op.easyCert?.details.certificates.map(c => c.nr) ?? [],
|
||||
// op.bioc?.details.certificates.map(c => c.nr) ?? [],
|
||||
// op.bioqs?.certificates.map(c => c.nr) ?? [],
|
||||
// op.lkv?.certificates.map(c => c.nr) ?? []
|
||||
// ))];
|
||||
// op.ooId = certNrs
|
||||
// .map(nr => nr.match(/[A-Z]{2}-.{3}-[0-9]{3}\.[0-9]{3}-[0-9]{7}\.[0-9]{4}\.[0-9]{3}/))
|
||||
// .filter(nr => nr !== null)
|
||||
// .map(nr => nr[0].split('.')[1])[0] ?? null;
|
||||
// }
|
||||
//
|
||||
// operators.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
$first = true;
|
||||
echo "{\"data\":[\n";
|
||||
foreach ($operators as $op) {
|
||||
if (!$first) echo ",\n";
|
||||
echo " ";
|
||||
echo jenc($op);
|
||||
$first = false;
|
||||
}
|
||||
echo "\n]}\n";
|
||||
+2
-4
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
$url = 'https://lkv.at/at/zertifizierung/themen/BIO/zertifizierte-BIO-Betriebe.php';
|
||||
$url = 'https://lkv.at/at/zertifizierung/themen/bio/zertifizierte-BIO-Betriebe.php';
|
||||
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
@@ -25,8 +25,6 @@ if ($info !== '') {
|
||||
exit;
|
||||
}
|
||||
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
|
||||
$postalCode = '';
|
||||
if (isset($_GET['postalCode']) && ctype_digit($_GET['postalCode'])) {
|
||||
$postalCode = $_GET['postalCode'];
|
||||
@@ -52,7 +50,7 @@ curl -s '$url' | grep -A3 '<tr' \
|
||||
@buf = map { "\$_\n" } split /\n/, \$chunk;
|
||||
} END { print for @buf; }' \
|
||||
| grep -B3 -A1 --no-group-separator '"postalCode":"$postalCode' | grep -B2 -A2 --no-group-separator '"lfbisNr":$lfbisNr' \
|
||||
| sed '\$s/.$//'
|
||||
| sed '\$s/.$//' \
|
||||
| sed 's@\s*",@",@g;s@:"\s*@:"@g'
|
||||
EOF);
|
||||
echo "]}\n";
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<title>Bio Zertifikate</title>
|
||||
<script>
|
||||
async function operatorDetailsEasyCert(db, id) {
|
||||
const res = await fetch(`/organic/external/easy-cert/operators/${db}:${id}`);
|
||||
if (!res.ok) throw new Error(res.statusText);
|
||||
return await res.json();
|
||||
}
|
||||
|
||||
async function listOperatorsEasyCert(country, postalCode) {
|
||||
const res = await fetch(`/organic/external/easy-cert/operators?country=${country}&postalCode=${postalCode}`);
|
||||
if (!res.ok) throw new Error(res.statusText);
|
||||
const data = await res.json();
|
||||
const details = await Promise.all(data.data.map(op => operatorDetailsEasyCert(op.db, op.id)));
|
||||
for (let i = 0; i < details.length; i++) {
|
||||
data.data[i].details = details[i];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
async function operatorDetailsBioc(id) {
|
||||
const res = await fetch(`/organic/external/bioc/operators/${id}`);
|
||||
if (!res.ok) throw new Error(res.statusText);
|
||||
return await res.json();
|
||||
}
|
||||
|
||||
async function listOperatorsBioc(country, postalCode) {
|
||||
const res = await fetch(`/organic/external/bioc/operators?country=${country}&postalCode=${postalCode}`);
|
||||
if (!res.ok) throw new Error(res.statusText);
|
||||
const data = await res.json();
|
||||
const details = await Promise.all(data.data.map(op => operatorDetailsBioc(op.id)));
|
||||
for (let i = 0; i < details.length; i++) {
|
||||
data.data[i].details = details[i];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
async function listOperatorsBioQs(country, postalCode) {
|
||||
const res = await fetch(`/organic/external/bioqs/operators?country=${country}&postalCode=${postalCode}`);
|
||||
if (!res.ok) throw new Error(res.statusText);
|
||||
return await res.json();
|
||||
}
|
||||
|
||||
async function listOperatorsLkv(postalCode) {
|
||||
const res = await fetch(`/organic/external/lkv/operators?postalCode=${postalCode}`);
|
||||
if (!res.ok) throw new Error(res.statusText);
|
||||
return await res.json();
|
||||
}
|
||||
|
||||
async function listOperators(country, postalCode) {
|
||||
const res = await fetch(`/organic/operators?country=${country}&postalCode=${postalCode}`);
|
||||
if (!res.ok) throw new Error(res.statusText);
|
||||
const operators = (await res.json()).data;
|
||||
operators.sort((a, b) => (a.name ?? "").localeCompare(b.name));
|
||||
console.log(...operators);
|
||||
return operators;
|
||||
}
|
||||
|
||||
async function operatorDetails(ooId) {
|
||||
const res = await fetch(`/organic/operators/${ooId}`);
|
||||
if (!res.ok) throw new Error(res.statusText);
|
||||
return await res.json();
|
||||
}
|
||||
|
||||
async function search(country, postalCode) {
|
||||
for (const t of document.getElementsByClassName("operators")) document.body.removeChild(t);
|
||||
for (const t of document.getElementsByClassName("certificates")) document.body.removeChild(t);
|
||||
for (const t of document.getElementsByTagName("p")) document.body.removeChild(t);
|
||||
const operators = await listOperators(country, postalCode);
|
||||
const tbl = document.createElement("table");
|
||||
tbl.className = "operators";
|
||||
for (const op of operators) {
|
||||
const tr = document.createElement("tr");
|
||||
tr.innerHTML = `
|
||||
<td>${op.name ?? '-'}</td>
|
||||
<td>${op.lfbisNr ?? '-'}</td>
|
||||
<td>${op.id ?? '-'}</td>
|
||||
<td>${op.address ?? '-'}</td>
|
||||
<td>${op.postalCode ?? '-'}</td>
|
||||
<td>${op.city ?? '-'}</td>
|
||||
<td>${op.countryCode ?? '-'}</td>
|
||||
<td><button onclick="details('${op.id}')">Details</button></td>`;
|
||||
tbl.appendChild(tr);
|
||||
}
|
||||
document.body.appendChild(tbl);
|
||||
}
|
||||
|
||||
async function details(ooId) {
|
||||
for (const t of document.getElementsByTagName("p")) document.body.removeChild(t);
|
||||
for (const t of document.getElementsByClassName("certificates")) document.body.removeChild(t);
|
||||
const data = await operatorDetails(ooId)
|
||||
console.log(data);
|
||||
const p = document.createElement("p");
|
||||
p.innerHTML = '';
|
||||
document.body.appendChild(p);
|
||||
|
||||
for (const cert of data.certificates) {
|
||||
p.innerHTML += `Zertifikat: ${cert.nr} ${cert.id} <a href="${cert.tracesPdfUrl}" target="_blank">Traces</a> / <a href="${cert.appendixPdfUrl}" target="_blank">Anhang</a> (${cert.validFrom}-${cert.validTo})<br/>`;
|
||||
}
|
||||
|
||||
const certs = await Promise.all(data.certificates.map(async c => {
|
||||
const res = await fetch(`/organic/pdf?format=json&url=${encodeURIComponent(c.pdfUrl)}`);
|
||||
return await res.json();
|
||||
}));
|
||||
|
||||
const tbl = document.createElement("table");
|
||||
tbl.className = "certificates";
|
||||
for (const cert of certs) {
|
||||
if (cert.type === "unknown") continue;
|
||||
console.log(cert);
|
||||
const op = cert.operator;
|
||||
const auth = cert.authority;
|
||||
const tr = document.createElement("tr");
|
||||
tr.innerHTML = `
|
||||
<td>${cert.id ?? '-'}</td>
|
||||
<td>${cert.nr ?? '-'}</td>
|
||||
<td>${cert.validFrom}<br/>${cert.validTo}</td>
|
||||
<td>${op.name}<br/>${op.address}<br/>${op.postalCode} ${op.city} (${op.countryCode})</td>
|
||||
<td>${op.id ?? '-'}</td>`;
|
||||
tbl.appendChild(tr);
|
||||
}
|
||||
|
||||
document.body.appendChild(tbl);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Bio Zertifikate</h1>
|
||||
<form onsubmit="search('AT', this.postalCode.value).then(); return false;">
|
||||
<input type="text" name="postalCode" placeholder="PLZ"/>
|
||||
<button type="submit">Suchen</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
+2
-51
@@ -36,13 +36,13 @@ $AUTHORITIES = [
|
||||
];
|
||||
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
|
||||
function jenc($data): string {
|
||||
return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'GET' && $_SERVER['REQUEST_METHOD'] !== 'HEAD') {
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
header('Status: 405');
|
||||
header('Content-Length: 56');
|
||||
header('Allow: GET, HEAD');
|
||||
@@ -58,44 +58,7 @@ if ($info !== '/' && str_ends_with($info, '/')) {
|
||||
}
|
||||
|
||||
$parts = explode('/', $info);
|
||||
if (str_starts_with($info, '/certificates/')) {
|
||||
$id = $parts[2];
|
||||
if (str_ends_with($id, '.txt')) {
|
||||
$id = substr($id, 0, -4);
|
||||
}
|
||||
if (str_contains($id, '/') || !file_exists("certificates/$id.pdf")) {
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
header('Status: 404');
|
||||
header('Content-Length: 22');
|
||||
echo "{\"error\":\"not found\"}\n";
|
||||
exit;
|
||||
}
|
||||
if (str_ends_with($parts[2], '.txt')) {
|
||||
$mode = '-layout';
|
||||
if (isset($_GET['raw']) && strtolower($_GET['raw']) === 'true') {
|
||||
$mode = '-raw';
|
||||
}
|
||||
header('Content-Type: text/plain; charset=UTF-8');
|
||||
system("pdftotext $mode 'certificates/$id.pdf' -");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (str_ends_with($id, '.appendix')) {
|
||||
header('Status: 303');
|
||||
header('Location: ' . substr($id, 0, -9));;
|
||||
exit;
|
||||
}
|
||||
|
||||
$cert = shell_exec("pdftotext -raw 'certificates/$id.pdf' -");
|
||||
$appendix = shell_exec("pdftotext -raw 'certificates/$id.appendix.pdf' -");
|
||||
|
||||
$p1 = strpos($cert, "\nI.3 ");
|
||||
$p2 = strpos($cert, "\nI.4 ");
|
||||
echo substr($cert, $p1 + 5, $p2 - $p1 - 5);
|
||||
|
||||
exit;
|
||||
} else if ($info === '/authorities') {
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
if ($info === '/authorities') {
|
||||
echo "{\"data\":[\n";
|
||||
$first = true;
|
||||
foreach ($AUTHORITIES as $auth) {
|
||||
@@ -107,7 +70,6 @@ if (str_starts_with($info, '/certificates/')) {
|
||||
exit;
|
||||
} else if (str_starts_with($info, '/authorities/')) {
|
||||
$code = $parts[2];
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
if (array_key_exists($code, $AUTHORITIES)) {
|
||||
echo jenc($AUTHORITIES[$code]);
|
||||
echo "\n";
|
||||
@@ -117,17 +79,6 @@ if (str_starts_with($info, '/certificates/')) {
|
||||
echo "{\"error\":\"not found\"}\n";
|
||||
}
|
||||
exit;
|
||||
} else if ($info === '/operators') {
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
header('Status: 501');
|
||||
header('Content-Length: 27');
|
||||
echo "{\"error\":\"not implemented\"}\n";
|
||||
exit;
|
||||
} else if (str_starts_with($info, '/operators/')) {
|
||||
$ooid = $parts[2];
|
||||
header('Content-Type: text/plain; charset=UTF-8');
|
||||
echo "Organic Operator Id: $ooid\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
header('Status: 404');
|
||||
|
||||
@@ -0,0 +1,346 @@
|
||||
<?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,
|
||||
]);
|
||||
+41
-181
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
require '.php/pdf.php';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'GET' && $_SERVER['REQUEST_METHOD'] !== 'POST' && $_SERVER['REQUEST_METHOD'] !== 'HEAD') {
|
||||
header('Status: 405');
|
||||
header('Content-Length: 0');
|
||||
@@ -17,25 +19,6 @@ if ($info !== '') {
|
||||
$url = isset($_GET['url']) ? str_replace(' ', '+', $_GET['url']) : null;
|
||||
$format = $_GET['format'] ?? 'json';
|
||||
|
||||
function get_address($array, $from, $to): array {
|
||||
$address = [];
|
||||
$postalCode = [];
|
||||
$city = [];
|
||||
for ($i = $to; $i >= $from; $i--) {
|
||||
$el = $array[$i];
|
||||
if (sizeof($postalCode) > 0) {
|
||||
if (sizeof($address) === 0) $el = rtrim($el, ", \n\r\t\v\0");
|
||||
if (strlen($el) === 0) continue;
|
||||
array_unshift($address, $el);
|
||||
} else if (preg_match("/^[A-Z0-9.\-]{3,},?$/", $el)) {
|
||||
array_unshift($postalCode, trim($el, ", \n\r\t\v\0"));
|
||||
} else {
|
||||
array_unshift($city, $el);
|
||||
}
|
||||
}
|
||||
return [implode(' ', $address), implode(' ', $postalCode), implode(' ', $city)];
|
||||
}
|
||||
|
||||
function jenc($data): string {
|
||||
return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
@@ -47,7 +30,9 @@ if (!$file || !$headerfile) {
|
||||
header('Content-Length: 0');
|
||||
exit;
|
||||
}
|
||||
$filename = stream_get_meta_data($file)['uri'];
|
||||
$cacheFile = null;
|
||||
$tmpfilename = stream_get_meta_data($file)['uri'];
|
||||
$filename = $tmpfilename;
|
||||
$headerfilename = stream_get_meta_data($headerfile)['uri'];
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$stdin = fopen("php://input", "rb");
|
||||
@@ -58,13 +43,30 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
}
|
||||
fclose($stdin);
|
||||
} else {
|
||||
if (exec("curl -s -D " . escapeshellarg($headerfilename) . " -o " . escapeshellarg($filename) . " " . escapeshellarg($url)) === false) {
|
||||
if ($cache = fopen('certificates/.cache.csv', 'r')) {
|
||||
while (($line = fgets($cache)) !== false) {
|
||||
$parts = explode(';', trim($line), 3);
|
||||
$timestamp = intval($parts[0]);
|
||||
if ($parts[2] !== $url) continue;
|
||||
$cacheFile = 'certificates/' . $parts[1] . '.pdf';
|
||||
break;
|
||||
}
|
||||
fclose($cache);
|
||||
}
|
||||
|
||||
if ($cacheFile !== null) {
|
||||
$filename = $cacheFile;
|
||||
} else {
|
||||
if (exec("curl -sk -D " . escapeshellarg($headerfilename) . " -o " . escapeshellarg($filename) . " " . escapeshellarg($url)) === false) {
|
||||
header('Status: 500');
|
||||
header('Content-Length: 0');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$timestamp = time();
|
||||
|
||||
if ($format === 'text') {
|
||||
header('Content-Type: text/plain; charset=UTF-8');
|
||||
passthru("pdftotext -raw " . escapeshellarg($filename) . " -");
|
||||
@@ -73,176 +75,34 @@ if ($format === 'text') {
|
||||
passthru("pdfsig " . escapeshellarg($filename));
|
||||
} else if ($format === 'json') {
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
if (exec("pdftotext -raw " . escapeshellarg($filename) . " -", $text) === false) {
|
||||
|
||||
if (($cert = parse_pdf($filename, true)) === null) {
|
||||
header('Status: 500');
|
||||
header('Content-Length: 0');
|
||||
exit;
|
||||
}
|
||||
$text = implode("\n", $text);
|
||||
exec("pdfsig " . escapeshellarg($filename), $sig);
|
||||
$sig = implode("\n", $sig);
|
||||
$certType = $cert['type'];
|
||||
$certId = $cert['id'];
|
||||
|
||||
$r = preg_match('@([a-z]{2}) (https://webgate\.ec\.europa\.eu/tracesnt/directory/publication/organic-operator/(.*?)\.pdf) (\d+) / (\d+)@', $text, $matches);
|
||||
if ($r === 1) {
|
||||
// TRACES certificate
|
||||
|
||||
$data = [];
|
||||
$parts = preg_split('@\n(I+\.\d+) ([^\n]*)@', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$status = str_replace("\n", '', $parts[0]);
|
||||
for ($i = 3; $i < sizeof($parts); $i += 3) {
|
||||
$data[$parts[$i - 2]] = trim($parts[$i]);
|
||||
if ($certType === 'traces') {
|
||||
if ($certId !== null && $url !== null && $cacheFile === null) {
|
||||
copy($filename, "certificates/$certId.pdf");
|
||||
file_put_contents('certificates/.cache.csv', "$timestamp;$certId;$url\n", FILE_APPEND);
|
||||
}
|
||||
|
||||
$lang = $matches[1];
|
||||
$splitAddr = [
|
||||
'de' => 'Adresse',
|
||||
'en' => 'Address',
|
||||
][$lang];
|
||||
$splitCountry = [
|
||||
'de' => 'Land',
|
||||
'en' => 'Country',
|
||||
][$lang];
|
||||
$statusMap = [
|
||||
'de' => [
|
||||
'AUSGESTELLT' => 'issued',
|
||||
],
|
||||
'en' => [
|
||||
'ISSUED' => 'issued',
|
||||
]
|
||||
][$lang];
|
||||
$activityMap = [
|
||||
'de' => [
|
||||
'Aufbereitung' => 'preparation',
|
||||
'Ausfuhr' => 'export',
|
||||
'Einfuhr' => 'import',
|
||||
'Lagerung' => 'storing',
|
||||
'Produktion' => 'production',
|
||||
'Vertrieb' => 'distribution',
|
||||
'Vertrieb/Inverkehrbringen' => 'distribution_placing_on_the_market',
|
||||
],
|
||||
'en' => [
|
||||
'Distribution' => 'distribution',
|
||||
'Distribution/Placing on the market' => 'distribution_placing_on_the_market',
|
||||
'Export' => 'export',
|
||||
'Import' => 'import',
|
||||
'Preparation' => 'preparation',
|
||||
'Production' => 'production',
|
||||
'Storing' => 'storing',
|
||||
],
|
||||
][$lang];
|
||||
|
||||
$certUrl = $matches[2];
|
||||
$certId = $matches[3];
|
||||
$authorityId = explode('.', $certId)[0];
|
||||
$operatorId = explode('.', $certId)[1];
|
||||
$operator = preg_split('@\s+@', trim($data['I.3']));
|
||||
$p1 = array_search($splitAddr, $operator);
|
||||
$p2 = array_search($splitCountry, $operator);
|
||||
$operatorName = trim(implode(' ', array_filter($operator, fn($k,$i) => $i > 0 && $i < $p1, ARRAY_FILTER_USE_BOTH)), ', ');
|
||||
[$opAddr, $opPostal, $opCity] = get_address($operator, $p1 + 1, $p2 - 1);
|
||||
|
||||
$authority = preg_split('@\s+@', trim($data['I.4']));
|
||||
$until = array_search("($authorityId)", $authority);
|
||||
$p1 = array_search($splitAddr, $authority);
|
||||
$p2 = array_search($splitCountry, $authority);
|
||||
$authorityName = implode(' ', array_filter($authority, fn($k,$i) => $i > 0 && $i < $p1 - 1 && ($i !== $p1 - 2 || !str_starts_with($k, '(')), ARRAY_FILTER_USE_BOTH));
|
||||
[$aAddr, $aPostal, $aCity] = get_address($authority, $p1 + 1, $p2 - 1);
|
||||
|
||||
$activities = [];
|
||||
foreach (explode("\n", $data['I.5']) as $a) {
|
||||
$activities[] = $activityMap[trim($a, '• ')];
|
||||
}
|
||||
|
||||
preg_match_all('/\([a-g]\)/', $data['I.6'], $matches, PREG_SET_ORDER);
|
||||
$products = [];
|
||||
foreach ($matches as $m) {
|
||||
$products[] = $m[0];
|
||||
}
|
||||
|
||||
preg_match_all('@\d+/\d+/\d+@', $data['I.8'], $matches, PREG_SET_ORDER);
|
||||
$valid1 = implode('-', array_reverse(explode('/', $matches[0][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];
|
||||
} else if ($certType !== 'unknown') {
|
||||
if ($certId !== null && $url !== null && $cacheFile === null) {
|
||||
copy($filename, "certificates/$certId.appendix.pdf");
|
||||
file_put_contents('certificates/.cache.csv', "$timestamp;$certId.appendix;$url\n", FILE_APPEND);
|
||||
}
|
||||
}
|
||||
$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 ",\n \"operator\":{\"id\":" . jenc($operatorId).
|
||||
',"groupOfOperators":' . jenc(!str_starts_with($data['I.2'], '☑')) .
|
||||
',"name":' . jenc($operatorName) .
|
||||
',"address":' . jenc($opAddr) .
|
||||
',"postalCode":' . jenc($opPostal) .
|
||||
',"city":' . jenc($opCity) .
|
||||
',"countryCode":' . jenc($operator[sizeof($operator) - 1]) .
|
||||
"},\n \"authority\":{\"id\":" . jenc($authorityId) .
|
||||
',"name":' . jenc($authorityName) .
|
||||
',"address":' . jenc($aAddr) .
|
||||
',"postalCode":' . jenc($aPostal) .
|
||||
',"city":' . jenc($aCity) .
|
||||
',"countryCode":' . jenc($authority[sizeof($authority) - 1]) .
|
||||
"},\n \"activities\":" . jenc($activities) .
|
||||
",\n \"productCategories\":" . jenc($products) .
|
||||
",\n \"validFrom\":" . jenc($valid1) .
|
||||
',"validTo":' . jenc($valid2) .
|
||||
",\n \"url\":\"$certUrl\"" .
|
||||
",\n \"digitalSignatures\":" . jenc($sigs) .
|
||||
"\n}\n";
|
||||
echo jenc($cert);
|
||||
exit;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
$operator = ['lfbisNr' => null];
|
||||
if ($authorityId === 'AT-BIO-301') {
|
||||
// TODO
|
||||
} else if ($authorityId === 'AT-BIO-302') {
|
||||
if (preg_match("/^lfbis[^0-9]*([0-9]{7})$/im", $text, $matches) === 1)
|
||||
$operator['lfbisNr'] = $matches[1];
|
||||
} else if ($authorityId === 'AT-BIO-401') {
|
||||
// TODO
|
||||
} else if ($authorityId === 'AT-BIO-402') {
|
||||
// TODO
|
||||
} else if ($authorityId === 'AT-BIO-903') {
|
||||
// TODO
|
||||
}
|
||||
echo "{\"type\":\"$authorityId\",\"lang\":\"de\",\"id\":" . jenc($certId) . ",\"nr\":" . jenc($certNr);
|
||||
echo ",\n \"operator\":" . jenc($operator) . ",\n \"authority\":{\"id\":" . jenc($authorityId) . "}}\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
echo "{\"type\":\"unknown\"}\n";
|
||||
} else if ($cacheFile === $filename) {
|
||||
header('Content-Type: application/pdf');
|
||||
header('Content-Length: ' . filesize($filename));
|
||||
header('Content-Disposition: inline; filename="' . basename($filename) . '"');
|
||||
readfile($filename);
|
||||
} else {
|
||||
$headers = [];
|
||||
$status_code = null;
|
||||
|
||||
+3
-3
@@ -320,7 +320,7 @@ main .clients .container .edge:nth-last-child(2) {top: 0; right: 0; transform: r
|
||||
main .clients .container .edge:nth-last-child(3) {bottom: 0; right: 0; transform: rotate(180deg);}
|
||||
main .clients .container .edge:nth-last-child(4) {bottom: 0; left: 0; transform: rotate(270deg);}
|
||||
|
||||
@media screen and (max-width: 1000px) {
|
||||
@media screen and (max-width: 1200px) {
|
||||
main .clients .container {
|
||||
flex-direction: column;
|
||||
}
|
||||
@@ -500,7 +500,7 @@ main.preview a:focus {
|
||||
border-radius: 0.5em;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 2480px) {
|
||||
@media screen and (min-width: 3000px) {
|
||||
.window:nth-of-type(1) {
|
||||
font-size: 2rem;
|
||||
}
|
||||
@@ -528,7 +528,7 @@ main.preview a:focus {
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 2280px) {
|
||||
@media screen and (min-width: 2800px) {
|
||||
.window:nth-of-type(2), .window:nth-of-type(3) {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user