* Copyright (C) 2010-2014 Regis Houssin * Copyright (C) 2010-2016 Juanjo Menent * Copyright (C) 2013 Charles-Fr BENKE * Copyright (C) 2013 Cédric Salvador * Copyright (C) 2014 Marcos García * Copyright (C) 2015 Bahfir Abbes * Copyright (C) 2016-2017 Ferran Marcet * Copyright (C) 2019-2025 Frédéric France * Copyright (C) 2024-2025 MDW * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file htdocs/core/class/html.formfile.class.php * \ingroup core * \brief File of class to offer components to list and upload files */ /** * Class to offer components to list and upload files */ class FormFile { /** * @var DoliDB */ private $db; /** * @var string Error code (or message) */ public $error; /** * @var int */ public $numoffiles; /** * @var array{nboffiles:int,extensions:array,files:string[]} Used to return information by function getDocumentsLink */ public $infofiles; /** * Constructor * * @param DoliDB $db Database handler */ public function __construct($db) { $this->db = $db; $this->numoffiles = 0; } /** * Show an image with feature to edit it * * @param string $htmlname HTML name * @param string $modulepart Module part * @param string $dirformainimage Main directory of module * @param string $subdirformainimage Subdirectory into main directory. Often '', can be 'logos/'. * @param string $fileformainimage File name of image to show * @return string HTML code to show and edit image */ public function showImageToEdit(string $htmlname, string $modulepart, string $dirformainimage, string $subdirformainimage, string $fileformainimage) { global $langs; include_once DOL_DOCUMENT_ROOT.'/core/lib/functions.lib.php'; include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; $tmparraysize = getDefaultImageSizes(); $maxwidthsmall = $tmparraysize['maxwidthsmall']; $maxheightsmall = $tmparraysize['maxheightsmall']; $maxwidthmini = $tmparraysize['maxwidthmini']; $maxheightmini = $tmparraysize['maxheightmini']; $quality = $tmparraysize['quality']; $imgheight = 80; $imgwidth = 200; $max = 'max-'; if ($htmlname == 'logo_squarred') { $imgheight = 80; $imgwidth = 80; $max = ''; } $maxfilesizearray = getMaxFileSizeArray(); $maxmin = $maxfilesizearray['maxmin']; $fileformainimagesmall = getImageFileNameForSize($fileformainimage, '_small'); // This include the "thumbs/..." in path $fileformainimagemini = getImageFileNameForSize($fileformainimage, '_mini'); // This include the "thumbs/..." in path $out = ''; $out .= '
'; if ($maxmin > 0) { $out .= ''; // MAX_FILE_SIZE must precede the field type=file } $out .= ''; $out .= '
'; if (!empty($fileformainimagesmall)) { $out .= ''; if (file_exists($dirformainimage.'/'.$subdirformainimage.$fileformainimagesmall)) { $out .= '
'; $out .= ''; $out .= '
'; } elseif (!empty($fileformainimage)) { // Regenerate the thumbs if (!file_exists($dirformainimage.'/'.$subdirformainimage.$fileformainimagemini)) { $imgThumbMini = vignette($dirformainimage.'/'.$subdirformainimage.$fileformainimage, $maxwidthmini, $maxheightmini, '_mini', $quality); } $imgThumbSmall = vignette($dirformainimage.'/'.$subdirformainimage.$fileformainimage, $maxwidthsmall, $maxheightsmall, '_small', $quality); $out .= '
'; $out .= ''; $out .= '
'; } } elseif (!empty($fileformainimage)) { if (file_exists($dirformainimage.'/'.$subdirformainimage.$fileformainimage)) { $out .= '
'; $out .= ''; $out .= '
'; $out .= ''; } else { $out .= '
'; $out .= ''; $out .= '
'; } } $out .= '
'; return $out; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Show form to upload a new file. * * @param string $url Url * @param string $title Title zone (Title or '' or 'none') * @param int<0,1> $addcancel 1=Add 'Cancel' button * @param int $sectionid If upload must be done inside a particular ECM section (is sectionid defined, sectiondir must not be) * @param int $perm Value of permission to allow upload * @param int $size Length of input file area. Deprecated. * @param CommonObject|BlockedLog|null $object Object to use (when attachment is done on an element) * @param string $options Add an option column * @param int<0,1> $useajax Use fileupload ajax (0=never, 1=if enabled, 2=always whatever is option). * Deprecated 2 should never be used and if 1 is used, option should not be enabled. * @param string $savingdocmask Mask to use to define output filename. For example 'XXXXX-__YYYYMMDD__-__file__' * @param int<0,1> $linkfiles 1=Also add form to link files, 0=Do not show form to link files * @param string $htmlname Name and id of HTML form ('formuserfile' by default, 'formuserfileecm' when used to upload a file in ECM) * @param string $accept Specifies the types of files accepted (This is not a security check but an user interface facility. eg '.pdf,image/*' or '.png,.jpg' or 'video/*') * @param string $sectiondir If upload must be done inside a particular directory (if sectiondir defined, sectionid must not be) * @param int<0,2> $usewithoutform 0=Default, 1=Disable
and to use in existing form area, 2=Disable the tag only * @param int<0,1> $capture 1=Add tag capture="capture" to force use of micro or video recording to generate file. When setting this to 1, you must also provide a value for $accept. * @param int<0,1> $disablemulti 0=Default, 1=Disable multiple file upload * @param int<0,1> $nooutput 0=Output result with print, 1=Return result * @return int|string|array{formToUploadAFile:string,formToAddALink:string} Return integer <0 if KO, >0 if OK, or string if $nooutput=1 or array if $nooutput=2 */ public function form_attach_new_file($url, $title = '', $addcancel = 0, $sectionid = 0, $perm = 1, $size = 50, $object = null, $options = '', $useajax = 1, $savingdocmask = '', $linkfiles = 1, $htmlname = 'formuserfile', $accept = '', $sectiondir = '', $usewithoutform = 0, $capture = 0, $disablemulti = 0, $nooutput = 0) { // phpcs:enable global $conf, $langs, $hookmanager; $hookmanager->initHooks(array('formfile')); // Deprecation warning if ($useajax == 2) { dol_syslog(__METHOD__.": using 2 for useajax is deprecated and should be not used", LOG_WARNING); } if (!empty($conf->browser->layout) && $conf->browser->layout != 'classic') { $useajax = 0; } //If there is no permission and the option to hide unauthorized actions is enabled, then nothing is printed if (!$perm && getDolGlobalString('MAIN_BUTTON_HIDE_UNAUTHORIZED')) { if ($nooutput) { return ''; } else { return 1; } } // Section to generate the form to upload a new file $out = "\n".'
'."\n"; if ($nooutput != 2) { if (empty($title)) { $title = $langs->trans("AttachANewFile"); } if ($title != 'none') { $out .= load_fiche_titre($title, '', ''); } } if (empty($usewithoutform)) { // Try to avoid this and set instead the form by the caller. // Add a param as GET parameter to detect when POST were cleaned by PHP because a file larger than post_max_size $url .= (strpos($url, '?') === false ? '?' : '&').'uploadform=1'; $out .= ''."\n"; } if (empty($usewithoutform) || $usewithoutform == 2) { $out .= ''."\n"; $out .= ''."\n"; $out .= ''."\n"; $out .= ''."\n"; $out .= ''."\n"; $out .= ''."\n"; } $out .= ''; $out .= ''; if (!empty($options)) { $out .= ''; } $out .= '"; if ($savingdocmask) { //add a global variable for disable the auto renaming on upload $rename = getDolGlobalString('MAIN_DOC_UPLOAD_NOT_RENAME_BY_DEFAULT') ? '' : 'checked'; $out .= ''; if (!empty($options)) { $out .= ''; } $out .= ''; $out .= ''; } $out .= "
'.$options.''; $maxfilesizearray = getMaxFileSizeArray(); $max = $maxfilesizearray['max']; $maxmin = $maxfilesizearray['maxmin']; $maxphptoshow = $maxfilesizearray['maxphptoshow']; $maxphptoshowparam = $maxfilesizearray['maxphptoshowparam']; if ($maxmin > 0) { $out .= ''; // MAX_FILE_SIZE must precede the field type=file } $out .= 'load('link'); $out .= ''; $out .= ''; $out .= ''; } $out .= 'trans("Cancel").'">'; } if (getDolGlobalString('MAIN_UPLOAD_DOC')) { if ($perm && empty($conf->dol_optimize_smallscreen)) { $langs->load('other'); $menudolibarrsetupmax = $langs->transnoentitiesnoconv("Home").' - '.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("Security"); $tooltiptext = $langs->trans("ThisLimitIsDefinedInSetupAt", $menudolibarrsetupmax, $max, $maxphptoshowparam, $maxphptoshow); if (getDolGlobalString('MAIN_SAVE_FILE_CONTENT_AS_TEXT')) { $tooltiptext .= '

Option to extract the file content in text to save it in database is ON ('.getDolGlobalString('MAIN_SAVE_FILE_CONTENT_AS_TEXT').')'; } $out .= ' '; $out .= info_admin($tooltiptext, 1, 0, '1', 'classfortooltip'); } } else { $out .= ' ('.$langs->trans("UploadDisabled").')'; } $out .= "
'.$options.''; $out .= ' '; $out .= ''; $out .= '
"; if (empty($usewithoutform)) { $out .= ''; if (empty($sectionid)) { $out .= '
'; } } $parameters = array('socid' => (isset($GLOBALS['socid']) ? $GLOBALS['socid'] : ''), 'id' => (isset($GLOBALS['id']) ? $GLOBALS['id'] : ''), 'url' => $url, 'perm' => $perm, 'options' => $options); // @phan-suppress-next-line PhanTypeMismatchArgumentNullable $res = $hookmanager->executeHooks('formattachOptionsUpload', $parameters, $object); if (empty($res)) { $out = '
'.$out.'
'; } $out .= $hookmanager->resPrint; $out .= "\n
\n"; $out2 = ""; // Section to generate the form to upload a new file if ($linkfiles) { $out2 .= "\n".'
'."\n"; $langs->load('link'); if ($nooutput != 2) { $title = $langs->trans("LinkANewFile"); $out2 .= load_fiche_titre($title, '', ''); } if (empty($usewithoutform)) { $out2 .= '