dolibarr  20.0.0-beta
connector.lib.php
1 <?php
2 /*
3  * FCKeditor - The text editor for Internet - http://www.fckeditor.net
4  * Copyright (C) 2003-2010 Frederico Caldeira Knabben
5  * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
6  *
7  * == BEGIN LICENSE ==
8  *
9  * Licensed under the terms of any of the following licenses at your
10  * choice:
11  *
12  * - GNU General Public License Version 2 or later (the "GPL")
13  * https://www.gnu.org/licenses/gpl.html
14  *
15  * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
16  * https://www.gnu.org/licenses/lgpl.html
17  *
18  * - Mozilla Public License Version 1.1 or later (the "MPL")
19  * http://www.mozilla.org/MPL/MPL-1.1.html
20  *
21  * == END LICENSE ==
22  *
23  * These functions are used by the connector.php script.
24  */
25 
31 function SetXmlHeaders()
32 {
33  ob_end_clean();
34 
35  // Prevent the browser from caching the result.
36  // Date in the past
37  header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
38  // always modified
39  header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
40  // HTTP/1.1
41  header('Cache-Control: no-store, no-cache, must-revalidate');
42  header('Cache-Control: post-check=0, pre-check=0', false);
43  // HTTP/1.0
44  header('Pragma: no-cache');
45 
46  // Set the response format.
47  header('Content-Type: text/xml; charset=utf-8');
48 }
49 
58 function CreateXmlHeader($command, $resourceType, $currentFolder)
59 {
60  SetXmlHeaders();
61 
62  // Create the XML document header.
63  echo '<?xml version="1.0" encoding="utf-8" ?>';
64 
65  // Create the main "Connector" node.
66  echo '<Connector command="'.$command.'" resourceType="'.$resourceType.'">';
67 
68  // Add the current folder node.
69  echo '<CurrentFolder path="'.ConvertToXmlAttribute($currentFolder).'" url="'.ConvertToXmlAttribute(GetUrlFromPath($resourceType, $currentFolder, $command)).'" />';
70 
71  $GLOBALS['HeaderSent'] = true;
72 }
73 
79 function CreateXmlFooter()
80 {
81  echo '</Connector>';
82 }
83 
91 function SendError($number, $text)
92 {
93  if ($_GET['Command'] == 'FileUpload') {
94  SendUploadResults($number, "", "", $text);
95  }
96 
97  if (isset($GLOBALS['HeaderSent']) && $GLOBALS['HeaderSent']) {
98  SendErrorNode($number, $text);
99  CreateXmlFooter();
100  } else {
101  SetXmlHeaders();
102 
103  dol_syslog('Error: '.$number.' '.$text, LOG_ERR);
104 
105  // Create the XML document header
106  echo '<?xml version="1.0" encoding="utf-8" ?>';
107 
108  echo '<Connector>';
109 
110  SendErrorNode($number, $text);
111 
112  echo '</Connector>';
113  }
114  exit;
115 }
116 
124 function SendErrorNode($number, $text)
125 {
126  if ($text) {
127  echo '<Error number="'.$number.'" text="'.htmlspecialchars($text).'" />';
128  } else {
129  echo '<Error number="'.$number.'" />';
130  }
131  return '';
132 }
133 
134 
135 
143 function GetFolders($resourceType, $currentFolder)
144 {
145  // Map the virtual path to the local server path.
146  $sServerDir = ServerMapFolder($resourceType, $currentFolder, 'GetFolders');
147 
148  // Array that will hold the folders names.
149  $aFolders = array();
150 
151  $oCurrentFolder = @opendir($sServerDir);
152 
153  if ($oCurrentFolder !== false) {
154  while ($sFile = readdir($oCurrentFolder)) {
155  if ($sFile != '.' && $sFile != '..' && is_dir($sServerDir.$sFile)) {
156  $aFolders[] = '<Folder name="'.ConvertToXmlAttribute($sFile).'" />';
157  }
158  }
159  closedir($oCurrentFolder);
160  }
161 
162  // Open the "Folders" node.
163  echo "<Folders>";
164 
165  natcasesort($aFolders);
166  foreach ($aFolders as $sFolder) {
167  echo $sFolder;
168  }
169 
170  // Close the "Folders" node.
171  echo "</Folders>";
172 }
173 
181 function GetFoldersAndFiles($resourceType, $currentFolder)
182 {
183  // Map the virtual path to the local server path.
184  $sServerDir = ServerMapFolder($resourceType, $currentFolder, 'GetFoldersAndFiles');
185 
186  // Arrays that will hold the folders and files names.
187  $aFolders = array();
188  $aFiles = array();
189 
190  $oCurrentFolder = @opendir($sServerDir);
191 
192  if ($oCurrentFolder !== false) {
193  while ($sFile = readdir($oCurrentFolder)) {
194  if ($sFile != '.' && $sFile != '..') {
195  if (is_dir($sServerDir.$sFile)) {
196  $aFolders[] = '<Folder name="'.ConvertToXmlAttribute($sFile).'" />';
197  } else {
198  $iFileSize = @filesize($sServerDir.$sFile);
199  if (!$iFileSize) {
200  $iFileSize = 0;
201  }
202  if ($iFileSize > 0) {
203  $iFileSize = round($iFileSize / 1024);
204  if ($iFileSize < 1) {
205  $iFileSize = 1;
206  }
207  }
208 
209  $aFiles[] = '<File name="'.ConvertToXmlAttribute($sFile).'" size="'.$iFileSize.'" />';
210  }
211  }
212  }
213  closedir($oCurrentFolder);
214  }
215 
216  // Send the folders
217  natcasesort($aFolders);
218  echo '<Folders>';
219 
220  foreach ($aFolders as $sFolder) {
221  echo $sFolder;
222  }
223 
224  echo '</Folders>';
225 
226  // Send the files
227  natcasesort($aFiles);
228  echo '<Files>';
229 
230  foreach ($aFiles as $sFiles) {
231  echo $sFiles;
232  }
233 
234  echo '</Files>';
235 }
236 
244 function CreateFolder($resourceType, $currentFolder)
245 {
246  $sErrorNumber = '0';
247  $sErrorMsg = '';
248 
249  if (isset($_GET['NewFolderName'])) {
250  $sNewFolderName = GETPOST('NewFolderName');
251  $sNewFolderName = SanitizeFolderName($sNewFolderName);
252 
253  if (strpos($sNewFolderName, '..') !== false) {
254  $sErrorNumber = '102'; // Invalid folder name.
255  } else {
256  // Map the virtual path to the local server path of the current folder.
257  $sServerDir = ServerMapFolder($resourceType, $currentFolder, 'CreateFolder');
258 
259  if (is_writable($sServerDir)) {
260  $sServerDir .= $sNewFolderName;
261 
262  $sErrorMsg = CreateServerFolder($sServerDir);
263 
264  switch ($sErrorMsg) {
265  case '':
266  $sErrorNumber = '0';
267  break;
268  case 'Invalid argument':
269  case 'No such file or directory':
270  $sErrorNumber = '102'; // Path too long.
271  break;
272  default:
273  $sErrorNumber = '110';
274  break;
275  }
276  } else {
277  $sErrorNumber = '103';
278  }
279  }
280  } else {
281  $sErrorNumber = '102';
282  }
283 
284  // Create the "Error" node.
285  echo '<Error number="'.$sErrorNumber.'" />';
286 }
287 
297 function FileUpload($resourceType, $currentFolder, $sCommand, $CKEcallback = '')
298 {
299  global $user;
300 
301  if (!isset($_FILES)) {
302  global $_FILES;
303  }
304  $sErrorNumber = '0';
305  $sFileName = '';
306 
307  if (isset($_FILES['NewFile']) && !is_null($_FILES['NewFile']['tmp_name']) || (isset($_FILES['upload']) && !is_null($_FILES['upload']['tmp_name']))) {
308  global $Config;
309 
310  $oFile = isset($_FILES['NewFile']) ? $_FILES['NewFile'] : $_FILES['upload'];
311 
312  // $resourceType should be 'Image';
313  $detectHtml = 0;
314 
315  // Map the virtual path to the local server path.
316  $sServerDir = ServerMapFolder($resourceType, $currentFolder, $sCommand);
317 
318  // Get the uploaded file name.
319  $sFileName = $oFile['name'];
320 
321  //$sFileName = SanitizeFileName($sFileName);
322  $sFileName = dol_sanitizeFileName($sFileName);
323 
324  $sOriginalFileName = $sFileName;
325 
326  // Get the extension.
327  $sExtension = substr($sFileName, (strrpos($sFileName, '.') + 1));
328  $sExtension = strtolower($sExtension);
329 
330  // Check permission
331  $permissiontouploadmediaisok = 1;
332  if (!empty($user->socid)) {
333  $permissiontouploadmediaisok = 0;
334  }
335  /*if (!$user->hasRight('website', 'write') && !$user->hasRight('mailing', 'write')) {
336  $permissiontouploadmediaisok = 0;
337  }*/
338  if (!$permissiontouploadmediaisok) {
339  dol_syslog("connector.lib.php Try to upload a file with no permission");
340  $sErrorNumber = '202';
341  }
342 
343  include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
344  //var_dump($sFileName); var_dump(image_format_supported($sFileName));exit;
345  $imgsupported = image_format_supported($sFileName);
346  $isImageValid = ($imgsupported >= 0 ? true : false);
347  if (!$isImageValid) {
348  $sErrorNumber = '202';
349  }
350 
351 
352  // Check if it is an allowed extension.
353  if (!$sErrorNumber) {
354  if (IsAllowedExt($sExtension, $resourceType)) {
355  $iCounter = 0;
356 
357  while (true) {
358  $sFilePath = $sServerDir.$sFileName;
359 
360  if (is_file($sFilePath)) {
361  $iCounter++;
362  $sFileName = RemoveExtension($sOriginalFileName).'('.$iCounter.').'.$sExtension;
363  $sErrorNumber = '201';
364  } else {
365  include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
366  dol_move_uploaded_file($oFile['tmp_name'], $sFilePath, 0, 0);
367 
368  if (is_file($sFilePath)) {
369  if (isset($Config['ChmodOnUpload']) && !$Config['ChmodOnUpload']) {
370  break;
371  }
372 
373  $permissions = '0777';
374  if (isset($Config['ChmodOnUpload']) && $Config['ChmodOnUpload']) {
375  $permissions = (string) $Config['ChmodOnUpload'];
376  }
377  $permissionsdec = octdec($permissions);
378  dol_syslog("connector.lib.php permission = ".$permissions." ".$permissionsdec." ".decoct($permissionsdec));
379  $oldumask = umask(0);
380  chmod($sFilePath, $permissionsdec);
381  umask($oldumask);
382  }
383 
384  break;
385  }
386  }
387 
388  if (file_exists($sFilePath)) {
389  //previous checks failed, try once again
390  if (isset($isImageValid) && $imgsupported === -1 && IsImageValid($sFilePath, $sExtension) === false) {
391  dol_syslog("connector.lib.php IsImageValid is ko");
392  @unlink($sFilePath);
393  $sErrorNumber = '202';
394  } elseif (isset($detectHtml) && $detectHtml === -1 && DetectHtml($sFilePath) === true) {
395  dol_syslog("connector.lib.php DetectHtml is ko");
396  @unlink($sFilePath);
397  $sErrorNumber = '202';
398  }
399  }
400  } else {
401  $sErrorNumber = '202';
402  }
403  }
404  } else {
405  $sErrorNumber = '203';
406  }
407 
408 
409  $sFileUrl = CombinePaths(GetResourceTypePath($resourceType, $sCommand), $currentFolder);
410  $sFileUrl = CombinePaths($sFileUrl, $sFileName);
411 
412 
413  // @CHANGE
414  //SendUploadResults( $sErrorNumber, $sFileUrl, $sFileName );
415  if ($CKEcallback == '') {
416  // this line already exists so wrap the if block around it
417  SendUploadResults($sErrorNumber, $sFileUrl, $sFileName);
418  } else {
419  //issue the CKEditor Callback
420  SendCKEditorResults(
421  $CKEcallback,
422  $sFileUrl,
423  ($sErrorNumber != 0 ? 'Error '.$sErrorNumber.' upload failed.' : 'Upload Successful')
424  );
425  }
426 
427  exit;
428 }
429 
430 
431 
439 function CombinePaths($sBasePath, $sFolder)
440 {
441  return RemoveFromEnd($sBasePath, '/').'/'.RemoveFromStart($sFolder, '/');
442 }
443 
451 function GetResourceTypePath($resourceType, $sCommand)
452 {
453  global $Config;
454 
455  if ($sCommand == "QuickUpload") {
456  return $Config['QuickUploadPath'][$resourceType];
457  } else {
458  return $Config['FileTypesPath'][$resourceType];
459  }
460 }
461 
469 function GetResourceTypeDirectory($resourceType, $sCommand)
470 {
471  global $Config;
472  if ($sCommand == "QuickUpload") {
473  if (strlen($Config['QuickUploadAbsolutePath'][$resourceType]) > 0) {
474  return $Config['QuickUploadAbsolutePath'][$resourceType];
475  }
476 
477  // Map the "UserFiles" path to a local directory.
478  return Server_MapPath($Config['QuickUploadPath'][$resourceType]);
479  } else {
480  if (strlen($Config['FileTypesAbsolutePath'][$resourceType]) > 0) {
481  return $Config['FileTypesAbsolutePath'][$resourceType];
482  }
483 
484  // Map the "UserFiles" path to a local directory.
485  return Server_MapPath($Config['FileTypesPath'][$resourceType]);
486  }
487 }
488 
497 function GetUrlFromPath($resourceType, $folderPath, $sCommand)
498 {
499  return CombinePaths(GetResourceTypePath($resourceType, $sCommand), $folderPath);
500 }
501 
508 function RemoveExtension($fileName)
509 {
510  return substr($fileName, 0, strrpos($fileName, '.'));
511 }
512 
521 function ServerMapFolder($resourceType, $folderPath, $sCommand)
522 {
523  // Get the resource type directory.
524  $sResourceTypePath = GetResourceTypeDirectory($resourceType, $sCommand);
525 
526  // Ensure that the directory exists.
527  $sErrorMsg = CreateServerFolder($sResourceTypePath);
528  if ($sErrorMsg != '') {
529  SendError(1, "Error creating folder \"$sResourceTypePath\" ($sErrorMsg)");
530  }
531 
532  // Return the resource type directory combined with the required path.
533  return CombinePaths($sResourceTypePath, $folderPath);
534 }
535 
542 function GetParentFolder($folderPath)
543 {
544  $sPattern = "-[/\\\\][^/\\\\]+[/\\\\]?$-";
545  return preg_replace($sPattern, '', $folderPath);
546 }
547 
555 function CreateServerFolder($folderPath, $lastFolder = null)
556 {
557  global $user;
558  global $Config;
559 
560  $sParent = GetParentFolder($folderPath);
561 
562  // Ensure the folder path has no double-slashes, or mkdir may fail on certain platforms
563  while (strpos($folderPath, '//') !== false) {
564  $folderPath = str_replace('//', '/', $folderPath);
565  }
566 
567  $permissiontouploadmediaisok = 1;
568  if (!empty($user->socid)) {
569  $permissiontouploadmediaisok = 0;
570  }
571  /*if (!$user->hasRight('website', 'write') && !$user->hasRight('mailing', 'write')) {
572  $permissiontouploadmediaisok = 0;
573  }*/
574  if (!$permissiontouploadmediaisok) {
575  return 'Bad permissions to create a folder in media directory';
576  }
577 
578  // Check if the parent exists, or create it.
579  if (!empty($sParent) && !file_exists($sParent)) {
580  //prevents against infinite loop when we can't create root folder
581  if (!is_null($lastFolder) && $lastFolder === $sParent) {
582  return "Can't create $folderPath directory";
583  }
584 
585  // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
586  $sErrorMsg = CreateServerFolder($sParent, $folderPath);
587  if ($sErrorMsg != '') {
588  return $sErrorMsg;
589  }
590  }
591 
592  if (!file_exists($folderPath)) {
593  // Turn off all error reporting.
594  error_reporting(0);
595 
596  $php_errormsg = '';
597  // Enable error tracking to catch the error.
598  ini_set('track_errors', '1');
599 
600  if (isset($Config['ChmodOnFolderCreate']) && !$Config['ChmodOnFolderCreate']) {
601  mkdir($folderPath);
602  } else {
603  $permissions = '0777';
604  if (isset($Config['ChmodOnFolderCreate']) && $Config['ChmodOnFolderCreate']) {
605  $permissions = (string) $Config['ChmodOnFolderCreate'];
606  }
607  $permissionsdec = octdec($permissions);
608  $permissionsdec |= octdec('0111'); // Set x bit required for directories
609  dol_syslog("connector.lib.php permission = ".$permissions." ".$permissionsdec." ".decoct($permissionsdec));
610  // To create the folder with 0777 permissions, we need to set umask to zero.
611  $oldumask = umask(0);
612  mkdir($folderPath, $permissionsdec);
613  umask($oldumask);
614  }
615 
616  $sErrorMsg = $php_errormsg;
617 
618  // Restore the configurations.
619  ini_restore('track_errors');
620  ini_restore('error_reporting');
621 
622  return $sErrorMsg;
623  } else {
624  return '';
625  }
626 }
627 
633 function GetRootPath()
634 {
635  if (!isset($_SERVER)) {
636  global $_SERVER;
637  }
638  $sRealPath = realpath('./');
639  // #2124 ensure that no slash is at the end
640  $sRealPath = rtrim($sRealPath, "\\/");
641 
642  $sSelfPath = $_SERVER['PHP_SELF'];
643  $sSelfPath = substr($sSelfPath, 0, strrpos($sSelfPath, '/'));
644 
645  $sSelfPath = str_replace('/', DIRECTORY_SEPARATOR, $sSelfPath);
646 
647  $position = strpos($sRealPath, $sSelfPath);
648 
649  // This can check only that this script isn't run from a virtual dir
650  // But it avoids the problems that arise if it isn't checked
651  if ($position === false || $position != strlen($sRealPath) - strlen($sSelfPath)) {
652  SendError(1, 'Sorry, can\'t map "UserFilesPath" to a physical path. You must set the "UserFilesAbsolutePath" value in "editor/filemanager/connectors/php/config.inc.php".');
653  }
654 
655  return substr($sRealPath, 0, $position);
656 }
657 
663 function Server_MapPath($path)
664 {
665  // This function is available only for Apache
666  if (function_exists('apache_lookup_uri')) {
667  $info = apache_lookup_uri($path);
668  return $info->filename.$info->path_info;
669  }
670 
671  // This isn't correct but for the moment there's no other solution
672  // If this script is under a virtual directory or symlink it will detect the problem and stop
673  return GetRootPath().$path;
674 }
675 
683 function IsAllowedExt($sExtension, $resourceType)
684 {
685  global $Config;
686  // Get the allowed and denied extensions arrays.
687  $arAllowed = $Config['AllowedExtensions'][$resourceType];
688  $arDenied = $Config['DeniedExtensions'][$resourceType];
689 
690  if (count($arAllowed) > 0 && !in_array($sExtension, $arAllowed)) {
691  return false;
692  }
693 
694  if (count($arDenied) > 0 && in_array($sExtension, $arDenied)) {
695  return false;
696  }
697 
698  return true;
699 }
700 
707 function IsAllowedType($resourceType)
708 {
709  global $Config;
710  if (!in_array($resourceType, $Config['ConfigAllowedTypes'])) {
711  return false;
712  }
713 
714  return true;
715 }
716 
723 function IsAllowedCommand($sCommand)
724 {
725  global $Config;
726 
727  if (!in_array($sCommand, $Config['ConfigAllowedCommands'])) {
728  return false;
729  }
730 
731  return true;
732 }
733 
739 function GetCurrentFolder()
740 {
741  $sCurrentFolder = isset($_GET['CurrentFolder']) ? GETPOST('CurrentFolder', '', 1) : '/';
742 
743  // Check the current folder syntax (must begin and start with a slash).
744  if (!preg_match('|/$|', $sCurrentFolder)) {
745  $sCurrentFolder .= '/';
746  }
747  if (strpos($sCurrentFolder, '/') !== 0) {
748  $sCurrentFolder = '/'.$sCurrentFolder;
749  }
750 
751  // Ensure the folder path has no double-slashes
752  while (strpos($sCurrentFolder, '//') !== false) {
753  $sCurrentFolder = str_replace('//', '/', $sCurrentFolder);
754  }
755 
756  // Check for invalid folder paths (..)
757  if (strpos($sCurrentFolder, '..') || strpos($sCurrentFolder, "\\")) {
758  SendError(102, '');
759  }
760 
761  if (preg_match(",(/\.)|[[:cntrl:]]|(//)|(\\\\)|([\:\*\?\"<>\|]),", $sCurrentFolder)) {
762  SendError(102, '');
763  }
764 
765  return $sCurrentFolder;
766 }
767 
774 function SanitizeFolderName($sNewFolderName)
775 {
776  $sNewFolderName = stripslashes($sNewFolderName);
777 
778  // Remove . \ / | : ? * " < >
779  $sNewFolderName = preg_replace('/\\.|\\\\|\\/|\\||\\:|\\?|\\*|"|<|>|[[:cntrl:]]/', '_', $sNewFolderName);
780 
781  return $sNewFolderName;
782 }
783 
790 function SanitizeFileName($sNewFileName)
791 {
792  global $Config;
793 
794  $sNewFileName = stripslashes($sNewFileName);
795 
796  // Replace dots in the name with underscores (only one dot can be there... security issue).
797  if ($Config['ForceSingleExtension']) {
798  $sNewFileName = preg_replace('/\\.(?![^.]*$)/', '_', $sNewFileName);
799  }
800 
801  // Remove \ / | : ? * " < >
802  $sNewFileName = preg_replace('/\\\\|\\/|\\||\\:|\\?|\\*|"|<|>|[[:cntrl:]]/', '_', $sNewFileName);
803 
804  return $sNewFileName;
805 }
806 
816 function SendUploadResults($errorNumber, $fileUrl = '', $fileName = '', $customMsg = '')
817 {
818  // Minified version of the document.domain automatic fix script (#1919).
819  // The original script can be found at _dev/domain_fix_template.js
820  echo <<<EOF
821 <script type="text/javascript">
822 (function(){var d=document.domain;while (true){try{var A=window.parent.document.domain;break;}catch(e) {};d=d.replace(/.*?(?:\.|$)/,'');if (d.length==0) break;try{document.domain=d;}catch (e){break;}}})();
823 EOF;
824 
825  if ($errorNumber && $errorNumber != 201) {
826  $fileUrl = "";
827  $fileName = "";
828  }
829 
830  $rpl = array('\\' => '\\\\', '"' => '\\"');
831  echo 'console.log('.$errorNumber.');';
832  echo 'window.parent.OnUploadCompleted('.$errorNumber.', "'.strtr($fileUrl, $rpl).'", "'.strtr($fileName, $rpl).'", "'.strtr($customMsg, $rpl).'");';
833  echo '</script>';
834  exit;
835 }
836 
837 
838 // @CHANGE
839 
840 // This is the function that sends the results of the uploading process to CKE.
849 function SendCKEditorResults($callback, $sFileUrl, $customMsg = '')
850 {
851  echo '<script type="text/javascript">';
852 
853  $rpl = array('\\' => '\\\\', '"' => '\\"');
854 
855  echo 'window.parent.CKEDITOR.tools.callFunction("'.$callback.'","'.strtr($sFileUrl, $rpl).'", "'.strtr($customMsg, $rpl).'");';
856 
857  echo '</script>';
858 }
859 
860 
861 
869 function RemoveFromStart($sourceString, $charToRemove)
870 {
871  $sPattern = '|^'.$charToRemove.'+|';
872  return preg_replace($sPattern, '', $sourceString);
873 }
874 
882 function RemoveFromEnd($sourceString, $charToRemove)
883 {
884  $sPattern = '|'.$charToRemove.'+$|';
885  return preg_replace($sPattern, '', $sourceString);
886 }
887 
894 function FindBadUtf8($string)
895 {
896  $regex = '([\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]';
897  $regex .= '|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2}|(.{1}))';
898 
899  $matches = array();
900  while (preg_match('/'.$regex.'/S', $string, $matches)) {
901  if (isset($matches[2])) {
902  return true;
903  }
904  $string = substr($string, strlen($matches[0]));
905  }
906 
907  return false;
908 }
909 
916 function ConvertToXmlAttribute($value)
917 {
918  if (defined('PHP_OS')) {
919  $os = PHP_OS;
920  } else {
921  $os = php_uname();
922  }
923 
924  if (strtoupper(substr($os, 0, 3)) === 'WIN' || FindBadUtf8($value)) {
925  return (mb_convert_encoding(htmlspecialchars($value), 'UTF-8', 'ISO-8859-1'));
926  } else {
927  return (htmlspecialchars($value));
928  }
929 }
930 
938 function IsHtmlExtension($ext, $formExtensions)
939 {
940  if (!$formExtensions || !is_array($formExtensions)) {
941  return false;
942  }
943  $lcaseHtmlExtensions = array();
944  foreach ($formExtensions as $key => $val) {
945  $lcaseHtmlExtensions[$key] = strtolower($val);
946  }
947  return in_array($ext, $lcaseHtmlExtensions);
948 }
949 
957 function DetectHtml($filePath)
958 {
959  $fp = @fopen($filePath, 'rb');
960 
961  //open_basedir restriction, see #1906
962  if ($fp === false || !flock($fp, LOCK_SH)) {
963  return -1;
964  }
965 
966  $chunk = fread($fp, 1024);
967  flock($fp, LOCK_UN);
968  fclose($fp);
969 
970  $chunk = strtolower($chunk);
971 
972  if (!$chunk) {
973  return false;
974  }
975 
976  $chunk = trim($chunk);
977 
978  if (preg_match("/<!DOCTYPE\W*X?HTML/sim", $chunk)) {
979  return true;
980  }
981 
982  $tags = array('<body', '<head', '<html', '<img', '<pre', '<script', '<table', '<title');
983 
984  foreach ($tags as $tag) {
985  if (false !== strpos($chunk, $tag)) {
986  return true;
987  }
988  }
989 
990  //type = javascript
991  if (preg_match('!type\s*=\s*[\'"]?\s*(?:\w*/)?(?:ecma|java)!sim', $chunk)) {
992  return true;
993  }
994 
995  //href = javascript
996  //src = javascript
997  //data = javascript
998  if (preg_match('!(?:href|src|data)\s*=\s*[\'"]?\s*(?:ecma|java)script:!sim', $chunk)) {
999  return true;
1000  }
1001 
1002  //url(javascript
1003  if (preg_match('!url\s*\‍(\s*[\'"]?\s*(?:ecma|java)script:!sim', $chunk)) {
1004  return true;
1005  }
1006 
1007  return false;
1008 }
1009 
1018 function IsImageValid($filePath, $extension)
1019 {
1020  if (!@is_readable($filePath)) {
1021  return -1;
1022  }
1023 
1024  $imageCheckExtensions = array(
1025  'gif',
1026  'jpeg',
1027  'jpg',
1028  'png',
1029  'swf',
1030  'psd',
1031  'bmp',
1032  'iff',
1033  'tiff',
1034  'tif',
1035  'swc',
1036  'jpc',
1037  'jp2',
1038  'jpx',
1039  'jb2',
1040  'xbm',
1041  'wbmp'
1042  );
1043 
1044  if (!in_array($extension, $imageCheckExtensions)) {
1045  return true;
1046  }
1047 
1048  if (@getimagesize($filePath) === false) {
1049  return false;
1050  }
1051 
1052  return true;
1053 }
This class is used to manage file upload using ajax.
dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan=0, $uploaderrorcode=0, $nohook=0, $varfiles='addedfile', $upload_dir='')
Check validity of a file upload from an GUI page, and move it to its final destination.
Definition: files.lib.php:1320
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
image_format_supported($file, $acceptsvg=0)
Return if a filename is file name of a supported image format.
Definition: images.lib.php:84
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:123