/** * Make control on an uploaded file from an GUI page and move it to final destination. * If there is errors (virus found, antivir in error, bad filename), file is not moved. * Note: This function can be used only into a HTML page context. Use dol_move if you are outside. * * @param string $src_file Source full path filename ($_FILES['field']['tmp_name']) * @param string $dest_file Target full path filename ($_FILES['field']['name']) * @param int $allowoverwrite 1=Overwrite target file if it already exists * @param int $disablevirusscan 1=Disable virus scan * @param integer $uploaderrorcode Value of PHP upload error code ($_FILES['field']['error']) * @param int $nohook Disable all hooks * @param string $varfiles _FILES var name * @return int >0 if OK, <0 or string if KO * @see dol_move */ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan = 0, $uploaderrorcode = 0, $nohook = 0, $varfiles = 'addedfile') { global $conf, $db, $user, $langs; global $object, $hookmanager; $reshook = 0; $file_name = $dest_file; if (empty($nohook)) { // If an upload error has been reported if ($uploaderrorcode) { switch ($uploaderrorcode) { case UPLOAD_ERR_INI_SIZE: // 1 return 'ErrorFileSizeTooLarge'; break; case UPLOAD_ERR_FORM_SIZE: // 2 return 'ErrorFileSizeTooLarge'; break; case UPLOAD_ERR_PARTIAL: // 3 return 'ErrorPartialFile'; break; case UPLOAD_ERR_NO_TMP_DIR: // return 'ErrorNoTmpDir'; break; case UPLOAD_ERR_CANT_WRITE: return 'ErrorFailedToWriteInDir'; break; case UPLOAD_ERR_EXTENSION: return 'ErrorUploadBlockedByAddon'; break; default: break; } } // If we need to make a virus scan if (empty($disablevirusscan) && file_exists($src_file) && !empty($conf->global->MAIN_ANTIVIRUS_COMMAND)) { if (!class_exists('AntiVir')) { require DOL_DOCUMENT_ROOT . '/core/class/antivir.class.php'; } $antivir = new AntiVir($db); $result = $antivir->dol_avscan_file($src_file); if ($result < 0) { $reterrors = $antivir->errors; dol_syslog('Files.lib::dol_move_uploaded_file File "' . $src_file . '" (target name "' . $dest_file . '") KO with antivirus: result=' . $result . ' errors=' . join(',', $antivir->errors), LOG_WARNING); return 'ErrorFileIsInfectedWithAVirus: ' . join(',', $reterrors); } } // Security: // Disallow file with some extensions. We renamed them. // Car si on a mis le rep documents dans un rep de la racine web (pas bien), cela permet d'executer du code a la demande. if (preg_match('/\\.htm|\\.html|\\.php|\\.pl|\\.cgi$/i', $dest_file)) { $file_name .= '.noexe'; } // Security: // On interdit fichiers caches, remontees de repertoire ainsi que les pipes dans les noms de fichiers. if (preg_match('/^\\./', $src_file) || preg_match('/\\.\\./', $src_file) || preg_match('/[<>|]/', $src_file)) { dol_syslog("Refused to deliver file " . $src_file, LOG_WARNING); return -1; } // Security: // On interdit fichiers caches, remontees de repertoire ainsi que les pipe dans les noms de fichiers. if (preg_match('/^\\./', $dest_file) || preg_match('/\\.\\./', $dest_file) || preg_match('/[<>|]/', $dest_file)) { dol_syslog("Refused to deliver file " . $dest_file, LOG_WARNING); return -2; } $reshook = $hookmanager->initHooks(array('fileslib')); $parameters = array('dest_file' => $dest_file, 'src_file' => $src_file, 'file_name' => $file_name, 'varfiles' => $varfiles, 'allowoverwrite' => $allowoverwrite); $reshook = $hookmanager->executeHooks('moveUploadedFile', $parameters, $object); } if ($reshook < 0) { $errmsg = join(',', $hookmanager->errors); if (empty($errmsg)) { $errmsg = 'ErrorReturnedBySomeHooks'; } // Should not occurs. Added if hook is bugged and does not set ->errors when there is error. return $errmsg; } elseif (empty($reshook)) { // The file functions must be in OS filesystem encoding. $src_file_osencoded = dol_osencode($src_file); $file_name_osencoded = dol_osencode($file_name); // Check if destination dir is writable // TODO // Check if destination file already exists if (!$allowoverwrite) { if (file_exists($file_name_osencoded)) { dol_syslog("Files.lib::dol_move_uploaded_file File " . $file_name . " already exists. Return 'ErrorFileAlreadyExists'", LOG_WARNING); return 'ErrorFileAlreadyExists'; } } // Move file $return = move_uploaded_file($src_file_osencoded, $file_name_osencoded); if ($return) { if (!empty($conf->global->MAIN_UMASK)) { @chmod($file_name_osencoded, octdec($conf->global->MAIN_UMASK)); } dol_syslog("Files.lib::dol_move_uploaded_file Success to move " . $src_file . " to " . $file_name . " - Umask=" . $conf->global->MAIN_UMASK, LOG_DEBUG); return 1; // Success } else { dol_syslog("Files.lib::dol_move_uploaded_file Failed to move " . $src_file . " to " . $file_name, LOG_ERR); return -3; // Unknown error } } return 1; // Success }
/** * Move an uploaded file after some controls. * If there is errors (virus found, antivir in error, bad filename), file is not moved. * @param src_file Source full path filename ($_FILES['field']['tmp_name']) * @param dest_file Target full path filename * @param allowoverwrite 1=Overwrite target file if it already exists * @param disablevirusscan 1=Disable virus scan * @param uploaderrorcode Value of upload error code ($_FILES['field']['error']) * @param notrigger Disable all triggers * @return int >0 if OK, <0 or string if KO */ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan=0, $uploaderrorcode=0, $notrigger=0) { global $conf, $user, $langs, $db; global $object; $file_name = $dest_file; // If an upload error has been reported if ($uploaderrorcode) { switch($uploaderrorcode) { case UPLOAD_ERR_INI_SIZE: // 1 return 'ErrorFileSizeTooLarge'; break; case UPLOAD_ERR_FORM_SIZE: // 2 return 'ErrorFileSizeTooLarge'; break; case UPLOAD_ERR_PARTIAL: // 3 return 'ErrorPartialFile'; break; case UPLOAD_ERR_NO_TMP_DIR: // return 'ErrorNoTmpDir'; break; case UPLOAD_ERR_CANT_WRITE: return 'ErrorFailedToWriteInDir'; break; case UPLOAD_ERR_EXTENSION: return 'ErrorUploadBlockedByAddon'; break; default: break; } } // If we need to make a virus scan if (empty($disablevirusscan) && file_exists($src_file) && ! empty($conf->global->MAIN_ANTIVIRUS_COMMAND)) { require_once(DOL_DOCUMENT_ROOT.'/lib/security.lib.php'); require_once(DOL_DOCUMENT_ROOT.'/lib/antivir.class.php'); $antivir=new AntiVir($db); $result = $antivir->dol_avscan_file($src_file); if ($result < 0) // If virus or error, we stop here { $reterrors=$antivir->errors; dol_syslog('Functions.lib::dol_move_uploaded_file File "'.$src_file.'" (target name "'.$file_name.'") KO with antivirus: result='.$result.' errors='.join(',',$antivir->errors), LOG_WARNING); return 'ErrorFileIsInfectedWithAVirus: '.join(',',$reterrors); } } // Security: // Disallow file with some extensions. We renamed them. // Car si on a mis le rep documents dans un rep de la racine web (pas bien), cela permet d'executer du code a la demande. if (preg_match('/\.htm|\.html|\.php|\.pl|\.cgi$/i',$file_name)) { $file_name.= '.noexe'; } // Security: // On interdit fichiers caches, remontees de repertoire ainsi que les pipes dans les noms de fichiers. if (preg_match('/^\./',$src_file) || preg_match('/\.\./',$src_file) || preg_match('/[<>|]/',$src_file)) { dol_syslog("Refused to deliver file ".$src_file, LOG_WARNING); return -1; } // Security: // On interdit fichiers caches, remontees de repertoire ainsi que les pipe dans // les noms de fichiers. if (preg_match('/^\./',$dest_file) || preg_match('/\.\./',$dest_file) || preg_match('/[<>|]/',$dest_file)) { dol_syslog("Refused to deliver file ".$dest_file, LOG_WARNING); return -2; } // The file functions must be in OS filesystem encoding. $src_file_osencoded=dol_osencode($src_file); $file_name_osencoded=dol_osencode($file_name); // Check if destination dir is writable // TODO // Check if destination file already exists if (! $allowoverwrite) { if (file_exists($file_name_osencoded)) { dol_syslog("Functions.lib::dol_move_uploaded_file File ".$file_name." already exists", LOG_WARNING); return 'ErrorFileAlreadyExists'; } } // Move file $return=move_uploaded_file($src_file_osencoded, $file_name_osencoded); if ($return) { if (! empty($conf->global->MAIN_UMASK)) @chmod($file_name_osencoded, octdec($conf->global->MAIN_UMASK)); dol_syslog("Functions.lib::dol_move_uploaded_file Success to move ".$src_file." to ".$file_name." - Umask=".$conf->global->MAIN_UMASK, LOG_DEBUG); if (! $notrigger && is_object($object)) { $object->src_file=$dest_file; // Appel des triggers include_once(DOL_DOCUMENT_ROOT . "/core/class/interfaces.class.php"); $interface=new Interfaces($db); $result=$interface->run_triggers('FILE_UPLOAD',$object,$user,$langs,$conf); if ($result < 0) { $error++; $errors=$interface->errors; } // Fin appel triggers } return 1; // Success } else { dol_syslog("Functions.lib::dol_move_uploaded_file Failed to move ".$src_file." to ".$file_name, LOG_ERR); return -3; // Unknown error } return 1; }