3 * This module provides for editing site-specific text files and
4 * for uploading site-specific image files.
7 * @link http://www.open-emr.org
8 * @author Rod Roark <rod@sunsetsystems.com>
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @copyright Copyright (c) 2010-2016 Rod Roark <rod@sunsetsystems.com>
11 * @copyright Copyright (c) 2018 Brady Miller <brady.g.miller@gmail.com>
12 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
16 require_once('../globals.php');
17 require_once($GLOBALS['srcdir'].'/acl.inc');
20 if (!acl_check('admin', 'super')) {
21 die(xlt('Not authorized'));
24 // Prepare array of names of editable files, relative to the site directory.
29 'referral_template.html',
31 'letter_templates/custom_pdf.php',
33 // Append LBF plugin filenames to the array.
34 $lres = sqlStatement('SELECT grp_form_id FROM layout_group_properties ' .
35 "WHERE grp_form_id LIKE 'LBF%' AND grp_group_id = '' AND grp_activity = 1 ORDER BY grp_seq, grp_title");
36 while ($lrow = sqlFetchArray($lres)) {
37 $option_id = $lrow['grp_form_id']; // should start with LBF
38 $my_files[] = "LBF/$option_id.plugin.php";
41 $form_filename = $_REQUEST['form_filename'];
42 // Sanity check to prevent evildoing.
43 if (!in_array($form_filename, $my_files)) {
47 $filepath = "$OE_SITE_DIR/$form_filename";
49 $imagedir = "$OE_SITE_DIR/images";
50 $educationdir = "$OE_SITE_DIR/documents/education";
52 if (!empty($_POST['bn_save'])) {
54 if (!verifyCsrfToken($_POST["csrf_token_form"])) {
59 // Textareas, at least in Firefox, return a \r\n at the end of each line
60 // even though only \n was originally there. For consistency with
61 // normal OpenEMR usage we translate those back.
62 file_put_contents($filepath, str_replace(
65 $_POST['form_filedata']
70 // Handle image uploads.
71 if (is_uploaded_file($_FILES['form_image']['tmp_name']) && $_FILES['form_image']['size']) {
72 $form_dest_filename = $_POST['form_dest_filename'];
73 if ($form_dest_filename == '') {
74 $form_dest_filename = $_FILES['form_image']['name'];
77 $form_dest_filename = basename($form_dest_filename);
78 if ($form_dest_filename == '') {
79 die(xlt('Cannot find a destination filename'));
82 $path_parts = pathinfo($form_dest_filename);
83 if (!in_array(strtolower($path_parts['extension']), array('gif','jpg','jpe','jpeg','png','svg'))) {
84 die(xlt('Only images files are accepted'));
87 $imagepath = "$imagedir/$form_dest_filename";
88 // If the site's image directory does not yet exist, create it.
89 if (!is_dir($imagedir)) {
93 if (is_file($imagepath)) {
97 $tmp_name = $_FILES['form_image']['tmp_name'];
98 if (!move_uploaded_file($_FILES['form_image']['tmp_name'], $imagepath)) {
99 die(xlt('Unable to create') . " '" . text($imagepath) . "'");
103 // Handle PDF uploads for patient education.
104 if (is_uploaded_file($_FILES['form_education']['tmp_name']) && $_FILES['form_education']['size']) {
105 $form_dest_filename = $_FILES['form_education']['name'];
106 $form_dest_filename = strtolower(basename($form_dest_filename));
107 if (substr($form_dest_filename, -4) != '.pdf') {
108 die(xlt('Filename must end with ".pdf"'));
111 $educationpath = "$educationdir/$form_dest_filename";
112 // If the site's education directory does not yet exist, create it.
113 if (!is_dir($educationdir)) {
114 mkdir($educationdir);
117 if (is_file($educationpath)) {
118 unlink($educationpath);
121 $tmp_name = $_FILES['form_education']['tmp_name'];
122 if (!move_uploaded_file($tmp_name, $educationpath)) {
123 die(text(xl('Unable to create') . " '$educationpath'"));
129 * Thumbnails generator
130 * generating thumbnail image to all images files from documents table
133 if (isset($_POST['generate_thumbnails'])) {
135 if (!verifyCsrfToken($_POST["csrf_token_form"])) {
139 $thumb_generator = new ThumbnailGenerator();
140 $results = $thumb_generator->generate_all();
142 $thumbnail_msg = "<p style='color: green'>" . xlt('Generated thumbnail(s)') . " : " . text($results['sum_success']) . "</p>";
143 $thumbnail_msg .= "<p style='color: red'>" . xlt('Failed to generate') . " : " . text($results['sum_failed']) . "</p>";
144 foreach ($results['failed'] as $key => $file) {
146 $thumbnail_msg .= "<p style='color: red; font-size: 11px'> " .text($num) . ". " . text($file) . "</p>";
149 $count_not_generated = ThumbnailGenerator
::count_not_generated();
151 $thumbnail_msg = "<p>" . xlt('Files with empty thumbnail') . ": " . text($count_not_generated) . " </p>";
157 * Security feature that enable to upload only file with mime-type from white list.
158 * Important to prevention upload of virus script.
159 * Dependence - turn on global setting 'secure_upload'
162 if ($GLOBALS['secure_upload']) {
163 $mime_types = array('image/*', 'text/*', 'audio/*', 'video/*');
168 curl_setopt_array($curl, array(
169 CURLOPT_RETURNTRANSFER
=> 1,
170 CURLOPT_URL
=> 'https://cdn.rawgit.com/jshttp/mime-db/master/db.json',
171 CURLOPT_CONNECTTIMEOUT
=> 5,
174 // Send the request & save response to $resp
175 $resp = curl_exec($curl);
176 $httpinfo = curl_getinfo($curl);
177 if ($resp && $httpinfo['http_code'] == 200 && $httpinfo['content_type'] == 'application/json;charset=utf-8') {
178 $all_mime_types = json_decode($resp, true);
179 foreach ($all_mime_types as $name => $value) {
180 $mime_types[] = $name;
183 error_log('Get list of mime-type error: "' . curl_error($curl) . '" - Code: ' . curl_errno($curl));
184 $mime_types_list = array(
189 'application/msword',
190 'application/vnd.oasis.opendocument.spreadsheet',
193 $mime_types = array_merge($mime_types, $mime_types_list);
198 if (isset($_POST['submit_form'])) {
200 if (!verifyCsrfToken($_POST["csrf_token_form"])) {
204 $new_white_list = empty($_POST['white_list']) ?
array() : $_POST['white_list'];
206 // truncate white list from list_options table
207 sqlStatement("DELETE FROM `list_options` WHERE `list_id` = 'files_white_list'");
208 foreach ($new_white_list as $mimetype) {
209 sqlStatement("INSERT INTO `list_options` (`list_id`, `option_id`, `title`, `activity`) VALUES ('files_white_list', ?, ?, 1)", array($mimetype, $mimetype));
212 $white_list = $new_white_list;
214 $white_list = array();
215 $lres = sqlStatement("SELECT option_id FROM list_options WHERE list_id = 'files_white_list' AND activity = 1");
216 while ($lrow = sqlFetchArray($lres)) {
217 $white_list[] = $lrow['option_id'];
227 <title
><?php
echo xlt('File management'); ?
></title
>
228 <link rel
="stylesheet" href
='<?php echo $css_header ?>' type
='text/css'>
230 <style type
="text/css">
231 .dehead
{ color
:#000000; font-family:sans-serif; font-size:10pt; font-weight:bold }
232 .detail
{ color
:#000000; font-family:sans-serif; font-size:10pt; font-weight:normal }
233 #generate_thumb, #file_type_whitelist{
236 border
: 2px solid dimgrey
;
238 #generate_thumb table{
242 #generate_thumb table td{
243 border
-right
: 1px solid dimgrey
;
248 <script type
="text/javascript" src
="<?php echo $GLOBALS['assets_static_relative'] ?>/jquery/dist/jquery.min.js"></script
>
250 <script language
="JavaScript">
251 // This is invoked when a filename selection changes in the drop-list.
252 // In this case anything else entered into the form is discarded.
253 function msfFileChanged() {
254 top
.restoreSession();
255 document
.forms
[0].submit();
261 <body
class="body_top">
262 <form method
='post' action
='manage_site_files.php' enctype
='multipart/form-data'
263 onsubmit
='return top.restoreSession()'>
264 <input type
="hidden" name
="csrf_token_form" value
="<?php echo attr(collectCsrfToken()); ?>" />
269 <table border
='1' width
='95%'>
271 <tr bgcolor
='#dddddd' class='dehead'>
272 <td colspan
='2' align
='center'><?php
echo xlt('Edit File in') . " " . text($OE_SITE_DIR); ?
></td
>
276 <td valign
='top' class='detail' nowrap
>
277 <select name
='form_filename' onchange
='msfFileChanged()'>
278 <option value
=''></option
>
280 foreach ($my_files as $filename) {
281 echo " <option value='" . attr($filename) . "'";
282 if ($filename == $form_filename) {
286 echo ">" . text($filename) . "</option>\n";
291 <textarea name
='form_filedata' rows
='25' style
='width:100%'><?php
292 if ($form_filename) {
293 echo text(@file_get_contents
($filepath));
299 <tr bgcolor
='#dddddd' class='dehead'>
300 <td colspan
='2' align
='center'><?php
echo text(xl('Upload Image to') . " $imagedir"); ?
></td
>
304 <td valign
='top' class='detail' nowrap
>
305 <?php
echo xlt('Source File'); ?
>:
306 <input type
="hidden" name
="MAX_FILE_SIZE" value
="12000000" />
307 <input type
="file" name
="form_image" size
="40" /> 
;
308 <?php
echo xlt('Destination Filename'); ?
>:
309 <select name
='form_dest_filename'>
310 <option value
=''>(<?php
echo xlt('Use source filename'); ?
>)</option
>
312 // Generate an <option> for each file already in the images directory.
313 $dh = opendir($imagedir);
315 die(text(xl('Cannot read directory') . " '$imagedir'"));
318 $imagesslist = array();
319 while (false !== ($sfname = readdir($dh))) {
320 if (substr($sfname, 0, 1) == '.') {
324 if ($sfname == 'CVS') {
328 $imageslist[$sfname] = $sfname;
333 foreach ($imageslist as $sfname) {
334 echo " <option value='" . attr($sfname) . "'";
335 echo ">" . text($sfname) . "</option>\n";
342 <tr bgcolor
='#dddddd' class='dehead'>
343 <td colspan
='2' align
='center'><?php
echo text(xl('Upload Patient Education PDF to') . " $educationdir"); ?
></td
>
346 <td valign
='top' class='detail' nowrap
>
347 <?php
echo xlt('Source File'); ?
>:
348 <input type
="file" name
="form_education" size
="40" /> 
;
349 <?php
echo xlt('Name must be like codetype_code_language.pdf, for example icd9_274.11_en.pdf'); ?
>
356 <input type
='submit' name
='bn_save' value
='<?php echo xla('Save
'); ?>' />
363 <div id
="generate_thumb">
364 <table style
="width: 100%">
366 <td
class="thumb_title" style
="width: 33%">
367 <b
><?php
echo xlt('Generate Thumbnails')?
></b
>
369 <td
class="thumb_msg" style
="width: 50%">
370 <span
><?php
echo $thumbnail_msg ?
></span
>
372 <td
class="thumb_form" style
="width:17%;border-right:none">
373 <form method
='post' action
='manage_site_files.php#generate_thumb'>
374 <input type
="hidden" name
="csrf_token_form" value
="<?php echo attr(collectCsrfToken()); ?>" />
375 <input style
="margin-top: 10px" type
="submit" name
="generate_thumbnails" value
="<?php echo xla('Generate') ?>">
382 <?php
if ($GLOBALS['secure_upload']) { ?
>
384 <div id
="file_type_whitelist">
385 <h2
><?php
echo xlt('Create custom white list of MIME content type of a files to secure your documents system');?
></h2
>
386 <form id
="whitelist_form" method
="post">
387 <div
class="subject-black-list">
388 <div
class="top-list">
389 <h2
><?php
echo xlt('Black list'); ?
></h2
>
390 <b
><?php
echo xlt('Filter');?
>:</b
> <input type
="text" id
="filter-black-list" >
392 <select multiple
="multiple" id
='black-list' class="form-control">
394 foreach ($mime_types as $type) {
395 if (!in_array($type, $white_list)) {
396 echo "<option value='" . attr($type) . "'> " . text($type) . "</option>";
403 <div
class="subject-info-arrows">
404 <input type
="button" id
="btnAllRight" value
=">>" /><br
/>
405 <input type
="button" id
="btnRight" value
=">" /><br
/>
406 <input type
="button" id
="btnLeft" value
="<" /><br
/>
407 <input type
="button" id
="btnAllLeft" value
="<<" />
410 <div
class="subject-white-list">
411 <div
class="top-list">
412 <h2
><?php
echo xlt('White list'); ?
></h2
>
413 <b
><?php
echo xlt('Add manually');?
>:</b
> <input type
="text" id
="add-manually-input"> <input type
="button" id
="add-manually" value
="+">
415 <select name
="white_list[]" multiple
="multiple" id
='white-list' class="form-control">
417 foreach ($white_list as $type) {
418 echo "<option value='" . attr($type) . "'> " . text($type) . "</option>";
423 <div
class="subject-info-save">
424 <input type
="button" id
="submit-whitelist" value
="<?php echo xla('Save'); ?>" />
425 <input type
="hidden" name
="submit_form" value
="1" />
426 <input type
="hidden" name
="csrf_token_form" value
="<?php echo attr(collectCsrfToken()); ?>" />
435 $
('#btnRight').click(function (e
) {
436 var selectedOpts
= $
('#black-list option:selected');
437 if (selectedOpts
.length
== 0) {
441 $
('#white-list').append($
(selectedOpts
).clone());
442 $
(selectedOpts
).remove();
446 $
('#btnAllRight').click(function (e
) {
447 var selectedOpts
= $
('#black-list option');
448 if (selectedOpts
.length
== 0) {
452 $
('#white-list').append($
(selectedOpts
).clone());
453 $
(selectedOpts
).remove();
457 $
('#btnLeft').click(function (e
) {
458 var selectedOpts
= $
('#white-list option:selected');
459 if (selectedOpts
.length
== 0) {
463 $
('#black-list').append($
(selectedOpts
).clone());
464 $
(selectedOpts
).remove();
468 $
('#btnAllLeft').click(function (e
) {
469 var selectedOpts
= $
('#white-list option');
470 if (selectedOpts
.length
== 0) {
474 $
('#black-list').append($
(selectedOpts
).clone());
475 $
(selectedOpts
).remove();
479 var storeElements
= [];
481 $
('#filter-black-list').on('keyup', function() {
482 var val
= this
.value
.toLowerCase();
484 $
('#black-list option').each(function(){
486 if(this
.value
.toLowerCase().indexOf( val
) == -1){
487 if(storeElements
.indexOf(this
) == -1){
488 storeElements
.unshift(this
)
494 $
(storeElements
).each(function(key
, element
){
496 if(element
.value
.toLowerCase().indexOf( val
) > -1){
498 $
('#black-list').prepend(element
);
499 storeElements
.splice(key
, 1)
506 $
('#add-manually').on('click', function () {
507 var new_type
= $
("#add-manually-input").val();
508 if(new_type
.length
< 1)return;
509 $
('#white-list').prepend("<option value="+new_type+
">"+new_type+
"</option>")
512 $
('#submit-whitelist').on('click', function () {
513 $
('#white-list option').prop('selected', true);
514 $
('#whitelist_form').submit();