['message' => 'ZipArchive extension not available.']]);
exit;
}
$docx = buildMinimalDocx($text);
header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
header('Content-Disposition: attachment; filename="redacted.docx"');
header('Content-Length: ' . strlen($docx));
header('Cache-Control: no-store');
echo $docx;
exit;
function buildMinimalDocx(string $text): string
{
$tmp = tempnam(sys_get_temp_dir(), 'dbn_docx_');
@unlink($tmp);
$tmp .= '.docx';
$zip = new ZipArchive();
$zip->open($tmp, ZipArchive::CREATE | ZipArchive::OVERWRITE);
$zip->addFromString('[Content_Types].xml', contentTypesXml());
$zip->addFromString('_rels/.rels', relsXml());
$zip->addFromString('word/document.xml', documentXml($text));
$zip->addFromString('word/_rels/document.xml.rels', wordRelsXml());
$zip->addFromString('docProps/app.xml', appXml());
$zip->addFromString('docProps/core.xml', coreXml());
$zip->close();
$bytes = file_get_contents($tmp);
@unlink($tmp);
return $bytes;
}
function documentXml(string $text): string
{
$lines = explode("\n", str_replace("\r\n", "\n", str_replace("\r", "\n", $text)));
$paras = [];
foreach ($lines as $line) {
$safe = htmlspecialchars($line, ENT_XML1 | ENT_COMPAT, 'UTF-8');
if ($safe === '') {
$paras[] = '';
} else {
$paras[] = ''
. '' . $safe . '';
}
}
return ''
. ''
. '' . implode('', $paras)
. ''
. ''
. '';
}
function contentTypesXml(): string
{
return ''
. ''
. ''
. ''
. ''
. ''
. ''
. '';
}
function relsXml(): string
{
return ''
. ''
. ''
. ''
. ''
. '';
}
function wordRelsXml(): string
{
return ''
. '';
}
function appXml(): string
{
return ''
. ''
. 'DoBetterNorge Redact'
. '';
}
function coreXml(): string
{
$date = date('Y-m-d\TH:i:s\Z');
return ''
. ''
. 'DoBetterNorge'
. '' . $date . ''
. '';
}