4 * Document Template Management Module.
7 * @link http://www.open-emr.org
8 * @author Rod Roark <rod@sunsetsystems.com>
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @author Tyler Wrenn <tyler@tylerwrenn.com>
11 * @copyright Copyright (c) 2013-2014 Rod Roark <rod@sunsetsystems.com>
12 * @copyright Copyright (c) 2018 Brady Miller <brady.g.miller@gmail.com>
13 * @copyright Copyright (c) 2020 Tyler Wrenn <tyler@tylerwrenn.com>
14 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
17 require_once('../globals.php');
19 use OpenEMR\Common\Acl\AclMain
;
20 use OpenEMR\Common\Crypto\CryptoGen
;
21 use OpenEMR\Common\Csrf\CsrfUtils
;
22 use OpenEMR\Common\Twig\TwigContainer
;
23 use OpenEMR\Core\Header
;
25 if (!AclMain
::aclCheckCore('admin', 'super')) {
26 echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Document Template Management")]);
30 // Set up crypto object
31 $cryptoGen = new CryptoGen();
33 $form_filename = convert_safe_file_dir_name($_REQUEST['form_filename'] ??
'');
35 $templatedir = "$OE_SITE_DIR/documents/doctemplates";
37 // If downloading a file, do the download and nothing else.
38 // Thus the current browser page should remain displayed.
40 if (!empty($_POST['bn_download'])) {
42 if (!CsrfUtils
::verifyCsrfToken($_POST["csrf_token_form"])) {
43 CsrfUtils
::csrfNotVerified();
46 $templatepath = "$templatedir/$form_filename";
48 // Place file in variable
49 $fileData = file_get_contents($templatepath);
51 // Decrypt file, if applicable
52 if ($cryptoGen->cryptCheckStandard($fileData)) {
53 $fileData = $cryptoGen->decryptStandard($fileData, null, 'database');
56 header('Content-Description: File Transfer');
57 header('Content-Transfer-Encoding: binary');
59 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
60 header('Pragma: public');
61 // attachment, not inline
62 header("Content-Disposition: attachment; filename=\"$form_filename\"");
63 // Note we avoid providing a mime type that suggests opening the file.
64 header("Content-Type: application/octet-stream");
65 header("Content-Length: " . strlen($fileData));
70 if (!empty($_POST['bn_delete'])) {
72 if (!CsrfUtils
::verifyCsrfToken($_POST["csrf_token_form"])) {
73 CsrfUtils
::csrfNotVerified();
76 $templatepath = "$templatedir/$form_filename";
77 if (is_file($templatepath)) {
78 unlink($templatepath);
82 if (!empty($_POST['bn_upload'])) {
84 if (!CsrfUtils
::verifyCsrfToken($_POST["csrf_token_form"])) {
85 CsrfUtils
::csrfNotVerified();
89 $tmp_name = $_FILES['form_file']['tmp_name'];
90 if (is_uploaded_file($tmp_name) && $_FILES['form_file']['size']) {
91 // Choose the destination path/filename.
92 $form_dest_filename = $_POST['form_dest_filename'];
93 if ($form_dest_filename == '') {
94 $form_dest_filename = $_FILES['form_file']['name'];
97 $form_dest_filename = convert_safe_file_dir_name(basename($form_dest_filename));
98 if ($form_dest_filename == '') {
99 die(xlt('Cannot determine a destination filename'));
101 $path_parts = pathinfo($form_dest_filename);
102 $extension = strtolower($path_parts['extension'] ??
'');
104 if (!in_array($extension, array('odt', 'txt', 'docx', 'zip'))) {
105 die(text($extension) . ' ' . xlt('filetype is not accepted'));
108 // Check if the uploaded file is a zip file
109 if ($extension === 'zip') {
110 $maxZipSize = 1048576; // 1 MB (adjust the size as needed)
111 if ($_FILES['form_file']['size'] > $maxZipSize) {
112 die(xlt('Zip file size exceeds the maximum allowed size'));
115 // Check for nested zip files
116 $zip = new ZipArchive();
117 if ($zip->open($tmp_name) === true) {
118 for ($i = 0; $i < $zip->numFiles
; $i++
) {
119 $nestedFile = $zip->getNameIndex($i);
120 if (pathinfo($nestedFile, PATHINFO_EXTENSION
) === 'zip') {
121 die(xlt('Nested zip files are not allowed'));
126 die(xlt('Failed to open the zip file'));
130 $templatepath = "$templatedir/$form_dest_filename";
131 // If the site's template directory does not yet exist, create it.
132 if (!is_dir($templatedir)) {
136 // If the target file already exists, delete it.
137 if (is_file($templatepath)) {
138 unlink($templatepath);
141 // Place uploaded file in variable.
142 $fileData = file_get_contents($tmp_name);
144 // Encrypt uploaded file, if applicable.
145 if ($GLOBALS['drive_encryption']) {
146 $storedData = $cryptoGen->encryptStandard($fileData, null, 'database');
148 $storedData = $fileData;
151 // Store the uploaded file.
152 if (file_put_contents($templatepath, $storedData) === false) {
153 die(xlt('Unable to create') . " '" . text($templatepath) . "'");
161 <title
><?php
echo xlt('Document Template Management'); ?
></title
>
162 <?php Header
::setupHeader(); ?
>
166 font
-family
: sans
-serif
;
167 font
-size
: 0.8125rem
;
172 font
-family
: sans
-serif
;
173 font
-size
: 0.8125rem
;
178 <body
class="body_top">
179 <div
class="container">
180 <form method
='post' action
='manage_document_templates.php' enctype
='multipart/form-data'
181 onsubmit
='return top.restoreSession()'>
182 <input type
="hidden" name
="csrf_token_form" value
="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
183 <h2
class="text-center"><?php
echo xlt('Document Template Management'); ?
></h2
>
186 <div
class="mx-auto mt-3">
188 <h5
class="card-header"><?php
echo xlt('Upload a Template'); ?
></h5
>
189 <div
class="card-body">
190 <div
class="custom-file">
191 <input type
="hidden" name
="MAX_FILE_SIZE" value
="250000000" />
192 <input type
="file" name
="form_file" size
="40" class="custom-file-input" id
="customFile" />
193 <label
class="custom-file-label" for="customFile"><?php
echo xlt('Choose file'); ?
></label
>
195 <div
class="input-group mt-3">
196 <label
for="form_dest_filename"><?php
echo xlt('Destination Filename'); ?
>:</label
>
197 <input type
='text' class="form-control" name
='form_dest_filename' id
='form_dest_filename' size
='30' />
198 <div
class="input-group-append">
199 <input type
='submit' class="btn btn-primary" name
='bn_upload' value
='<?php echo xla('Upload
') ?>' />
207 <div
class="mx-auto mt-3">
209 <h5
class="card-header"><?php
echo xlt('Download or Delete a Template'); ?
></h5
>
210 <div
class="card-body">
211 <select
class="form-control" name
='form_filename'>
213 // Generate an <option> for each existing file.
214 if (file_exists($templatedir)) {
215 $dh = opendir($templatedir);
220 $templateslist = array();
221 while (false !== ($sfname = readdir($dh))) {
222 if (substr($sfname, 0, 1) == '.') {
226 $templateslist[$sfname] = $sfname;
230 ksort($templateslist);
231 foreach ($templateslist as $sfname) {
232 echo " <option value='" . attr($sfname) . "'";
233 echo ">" . text($sfname) . "</option>\n";
239 <input type
='submit' class="btn btn-success" name
='bn_download' value
='<?php echo xla('Download
') ?>' />
240 <input type
='submit' class="btn btn-danger" name
='bn_delete' value
='<?php echo xla('Delete
') ?>' />
251 $
(".custom-file-input").on("change", function() {
252 var fileName
= $
(this
).val().split("\\").pop();
253 $
(this
).siblings(".custom-file-label").addClass("selected").html(jsText(fileName
));