dolibarr 21.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 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
7 *
8 * == BEGIN LICENSE ==
9 *
10 * Licensed under the terms of any of the following licenses at your
11 * choice:
12 *
13 * - GNU General Public License Version 2 or later (the "GPL")
14 * https://www.gnu.org/licenses/gpl.html
15 *
16 * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
17 * https://www.gnu.org/licenses/lgpl.html
18 *
19 * - Mozilla Public License Version 1.1 or later (the "MPL")
20 * http://www.mozilla.org/MPL/MPL-1.1.html
21 *
22 * == END LICENSE ==
23 *
24 * These functions are used by the connector.php script.
25 */
26
32function SetXmlHeaders()
33{
34 ob_end_clean();
35
36 // Prevent the browser from caching the result.
37 // Date in the past
38 header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
39 // always modified
40 header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
41 // HTTP/1.1
42 header('Cache-Control: no-store, no-cache, must-revalidate');
43 header('Cache-Control: post-check=0, pre-check=0', false);
44 // HTTP/1.0
45 header('Pragma: no-cache');
46
47 // Set the response format.
48 header('Content-Type: text/xml; charset=utf-8');
49}
50
59function CreateXmlHeader($command, $resourceType, $currentFolder)
60{
61 SetXmlHeaders();
62
63 // Create the XML document header.
64 echo '<?xml version="1.0" encoding="utf-8" ?>';
65
66 // Create the main "Connector" node.
67 echo '<Connector command="'.$command.'" resourceType="'.$resourceType.'">';
68
69 // Add the current folder node.
70 echo '<CurrentFolder path="'.ConvertToXmlAttribute($currentFolder).'" url="'.ConvertToXmlAttribute(GetUrlFromPath($resourceType, $currentFolder, $command)).'" />';
71
72 $GLOBALS['HeaderSent'] = true;
73}
74
80function CreateXmlFooter()
81{
82 echo '</Connector>';
83}
84
92function SendError($number, $text)
93{
94 if ($_GET['Command'] == 'FileUpload') {
95 SendUploadResults((string) $number, "", "", $text);
96 }
97
98 if (isset($GLOBALS['HeaderSent']) && $GLOBALS['HeaderSent']) {
99 SendErrorNode($number, $text);
100 CreateXmlFooter();
101 } else {
102 SetXmlHeaders();
103
104 dol_syslog('Error: '.$number.' '.$text, LOG_ERR);
105
106 // Create the XML document header
107 echo '<?xml version="1.0" encoding="utf-8" ?>';
108
109 echo '<Connector>';
110
111 SendErrorNode($number, $text);
112
113 echo '</Connector>';
114 }
115 exit;
116}
117
125function SendErrorNode($number, $text)
126{
127 if ($text) {
128 echo '<Error number="'.$number.'" text="'.htmlspecialchars($text).'" />';
129 } else {
130 echo '<Error number="'.$number.'" />';
131 }
132 return '';
133}
134
135
136
144function GetFolders($resourceType, $currentFolder)
145{
146 // Map the virtual path to the local server path.
147 $sServerDir = ServerMapFolder($resourceType, $currentFolder, 'GetFolders');
148
149 // Array that will hold the folders names.
150 $aFolders = array();
151
152 $oCurrentFolder = @opendir($sServerDir);
153
154 if ($oCurrentFolder !== false) {
155 while ($sFile = readdir($oCurrentFolder)) {
156 if ($sFile != '.' && $sFile != '..' && is_dir($sServerDir.$sFile)) {
157 $aFolders[] = '<Folder name="'.ConvertToXmlAttribute($sFile).'" />';
158 }
159 }
160 closedir($oCurrentFolder);
161 }
162
163 // Open the "Folders" node.
164 echo "<Folders>";
165
166 natcasesort($aFolders);
167 foreach ($aFolders as $sFolder) {
168 echo $sFolder;
169 }
170
171 // Close the "Folders" node.
172 echo "</Folders>";
173}
174
182function GetFoldersAndFiles($resourceType, $currentFolder)
183{
184 // Map the virtual path to the local server path.
185 $sServerDir = ServerMapFolder($resourceType, $currentFolder, 'GetFoldersAndFiles');
186
187 // Arrays that will hold the folders and files names.
188 $aFolders = array();
189 $aFiles = array();
190
191 $oCurrentFolder = @opendir($sServerDir);
192
193 if ($oCurrentFolder !== false) {
194 while ($sFile = readdir($oCurrentFolder)) {
195 if ($sFile != '.' && $sFile != '..') {
196 if (is_dir($sServerDir.$sFile)) {
197 $aFolders[] = '<Folder name="'.ConvertToXmlAttribute($sFile).'" />';
198 } else {
199 $iFileSize = @filesize($sServerDir.$sFile);
200 if (!$iFileSize) {
201 $iFileSize = 0;
202 }
203 if ($iFileSize > 0) {
204 $iFileSize = round($iFileSize / 1024);
205 if ($iFileSize < 1) {
206 $iFileSize = 1;
207 }
208 }
209
210 $aFiles[] = '<File name="'.ConvertToXmlAttribute($sFile).'" size="'.$iFileSize.'" />';
211 }
212 }
213 }
214 closedir($oCurrentFolder);
215 }
216
217 // Send the folders
218 natcasesort($aFolders);
219 echo '<Folders>';
220
221 foreach ($aFolders as $sFolder) {
222 echo $sFolder;
223 }
224
225 echo '</Folders>';
226
227 // Send the files
228 natcasesort($aFiles);
229 echo '<Files>';
230
231 foreach ($aFiles as $sFiles) {
232 echo $sFiles;
233 }
234
235 echo '</Files>';
236}
237
245function CreateFolder($resourceType, $currentFolder)
246{
247 $sErrorNumber = '0';
248 $sErrorMsg = '';
249
250 if (isset($_GET['NewFolderName'])) {
251 $sNewFolderName = GETPOST('NewFolderName');
252 $sNewFolderName = SanitizeFolderName($sNewFolderName);
253
254 if (strpos($sNewFolderName, '..') !== false) {
255 $sErrorNumber = '102'; // Invalid folder name.
256 } else {
257 // Map the virtual path to the local server path of the current folder.
258 $sServerDir = ServerMapFolder($resourceType, $currentFolder, 'CreateFolder');
259
260 if (is_writable($sServerDir)) {
261 $sServerDir .= $sNewFolderName;
262
263 $sErrorMsg = CreateServerFolder($sServerDir);
264
265 switch ($sErrorMsg) {
266 case '':
267 $sErrorNumber = '0';
268 break;
269 case 'Invalid argument':
270 case 'No such file or directory':
271 $sErrorNumber = '102'; // Path too long.
272 break;
273 default:
274 $sErrorNumber = '110';
275 break;
276 }
277 } else {
278 $sErrorNumber = '103';
279 }
280 }
281 } else {
282 $sErrorNumber = '102';
283 }
284
285 // Create the "Error" node.
286 echo '<Error number="'.$sErrorNumber.'" />';
287}
288
298function FileUpload($resourceType, $currentFolder, $sCommand, $CKEcallback = '')
299{
300 global $user;
301
302 if (!isset($_FILES)) {
303 global $_FILES; // @phan-suppress-current-line PhanPluginConstantVariableNull
304 }
305 $sErrorNumber = '0';
306 $sFileName = '';
307
308 // (_FILES indexes:) @phan-suppress-next-line PhanTypeInvalidDimOffset
309 if (isset($_FILES['NewFile']) && !is_null($_FILES['NewFile']['tmp_name']) && !is_null($_FILES['NewFile']['name']) || (isset($_FILES['upload']) && !is_null($_FILES['upload']['tmp_name']) && !is_null($_FILES['upload']['name']))) {
310 global $Config;
311
312 $oFile = isset($_FILES['NewFile']) ? $_FILES['NewFile'] : $_FILES['upload'];
313
314 // $resourceType should be 'Image';
315 $detectHtml = 0;
316
317 // Map the virtual path to the local server path.
318 $sServerDir = ServerMapFolder($resourceType, $currentFolder, $sCommand);
319
320 // Get the uploaded file name.
321 $sFileName = $oFile['name'];
322
323 //$sFileName = SanitizeFileName($sFileName);
324 $sFileName = dol_sanitizeFileName($sFileName);
325
326 $sOriginalFileName = $sFileName;
327
328 // Get the extension.
329 $sExtension = substr($sFileName, (strrpos($sFileName, '.') + 1));
330 $sExtension = strtolower($sExtension);
331
332 // Check permission
333 $permissiontouploadmediaisok = 1;
334 if (!empty($user->socid)) {
335 $permissiontouploadmediaisok = 0;
336 }
337 /*if (!$user->hasRight('website', 'write') && !$user->hasRight('mailing', 'write')) {
338 $permissiontouploadmediaisok = 0;
339 }*/
340 if (!$permissiontouploadmediaisok) {
341 dol_syslog("connector.lib.php Try to upload a file with no permission");
342 $sErrorNumber = '202';
343 }
344
345 include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
346 //var_dump($sFileName); var_dump(image_format_supported($sFileName));exit;
347 $imgsupported = image_format_supported($sFileName);
348 $isImageValid = ($imgsupported >= 0);
349 if (!$isImageValid) {
350 $sErrorNumber = '202';
351 }
352
353
354 // Check if it is an allowed extension.
355 if (!$sErrorNumber) {
356 if (IsAllowedExt($sExtension, $resourceType)) {
357 $iCounter = 0;
358
359 while (true) {
360 $sFilePath = $sServerDir.$sFileName;
361
362 if (is_file($sFilePath)) {
363 $iCounter++;
364 $sFileName = RemoveExtension($sOriginalFileName).'('.$iCounter.').'.$sExtension;
365 $sErrorNumber = '201';
366 } else {
367 include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
368 dol_move_uploaded_file($oFile['tmp_name'], $sFilePath, 0, 0);
369
370 if (is_file($sFilePath)) {
371 if (isset($Config['ChmodOnUpload']) && !$Config['ChmodOnUpload']) {
372 break;
373 }
374
375 $permissions = '0777';
376 if (isset($Config['ChmodOnUpload']) && $Config['ChmodOnUpload']) {
377 $permissions = (string) $Config['ChmodOnUpload'];
378 }
379 $permissionsdec = octdec($permissions);
380 dol_syslog("connector.lib.php permission = ".$permissions." ".$permissionsdec." ".decoct($permissionsdec));
381 $oldumask = umask(0);
382 chmod($sFilePath, $permissionsdec);
383 umask($oldumask);
384 }
385
386 break;
387 }
388 }
389
390 if (file_exists($sFilePath)) {
391 //previous checks failed, try once again
392 if (isset($isImageValid) && $imgsupported === -1 && IsImageValid($sFilePath, $sExtension) === false) {
393 dol_syslog("connector.lib.php IsImageValid is ko");
394 @unlink($sFilePath);
395 $sErrorNumber = '202';
396 } else {
397 $detectHtml = DetectHtml($sFilePath);
398 if ($detectHtml === true || $detectHtml == -1) {
399 // Note that is is a simple test and not reliable. Security does not rely on this.
400 dol_syslog("connector.lib.php DetectHtml is ko");
401 @unlink($sFilePath);
402 $sErrorNumber = '202';
403 }
404 }
405 }
406 } else {
407 $sErrorNumber = '202';
408 }
409 }
410 } else {
411 $sErrorNumber = '203';
412 }
413
414
415 $sFileUrl = CombinePaths(GetResourceTypePath($resourceType, $sCommand), $currentFolder);
416 $sFileUrl = CombinePaths($sFileUrl, $sFileName);
417
418
419 // @CHANGE
420 //SendUploadResults( $sErrorNumber, $sFileUrl, $sFileName );
421 if ($CKEcallback == '') {
422 // this line already exists so wrap the if block around it
423 SendUploadResults($sErrorNumber, $sFileUrl, $sFileName);
424 } else {
425 //issue the CKEditor Callback
426 SendCKEditorResults(
427 $CKEcallback,
428 $sFileUrl,
429 ($sErrorNumber != 0 ? 'Error '.$sErrorNumber.' upload failed.' : 'Upload Successful')
430 );
431 }
432
433 exit;
434}
435
436
437
445function CombinePaths($sBasePath, $sFolder)
446{
447 return RemoveFromEnd($sBasePath, '/').'/'.RemoveFromStart($sFolder, '/');
448}
449
457function GetResourceTypePath($resourceType, $sCommand)
458{
459 global $Config;
460
461 if ($sCommand == "QuickUpload") {
462 return $Config['QuickUploadPath'][$resourceType];
463 } else {
464 return $Config['FileTypesPath'][$resourceType];
465 }
466}
467
475function GetResourceTypeDirectory($resourceType, $sCommand)
476{
477 global $Config;
478 if ($sCommand == "QuickUpload") {
479 if (strlen($Config['QuickUploadAbsolutePath'][$resourceType]) > 0) {
480 return $Config['QuickUploadAbsolutePath'][$resourceType];
481 }
482
483 // Map the "UserFiles" path to a local directory.
484 return Server_MapPath($Config['QuickUploadPath'][$resourceType]);
485 } else {
486 if (strlen($Config['FileTypesAbsolutePath'][$resourceType]) > 0) {
487 return $Config['FileTypesAbsolutePath'][$resourceType];
488 }
489
490 // Map the "UserFiles" path to a local directory.
491 return Server_MapPath($Config['FileTypesPath'][$resourceType]);
492 }
493}
494
503function GetUrlFromPath($resourceType, $folderPath, $sCommand)
504{
505 return CombinePaths(GetResourceTypePath($resourceType, $sCommand), $folderPath);
506}
507
514function RemoveExtension($fileName)
515{
516 return substr($fileName, 0, strrpos($fileName, '.'));
517}
518
527function ServerMapFolder($resourceType, $folderPath, $sCommand)
528{
529 // Get the resource type directory.
530 $sResourceTypePath = GetResourceTypeDirectory($resourceType, $sCommand);
531
532 // Ensure that the directory exists.
533 $sErrorMsg = CreateServerFolder($sResourceTypePath);
534 if ($sErrorMsg != '') {
535 SendError(1, "Error creating folder \"$sResourceTypePath\" ($sErrorMsg)");
536 }
537
538 // Return the resource type directory combined with the required path.
539 return CombinePaths($sResourceTypePath, $folderPath);
540}
541
548function GetParentFolder($folderPath)
549{
550 $sPattern = "-[/\\\\][^/\\\\]+[/\\\\]?$-";
551 return preg_replace($sPattern, '', $folderPath);
552}
553
561function CreateServerFolder($folderPath, $lastFolder = null)
562{
563 global $user;
564 global $Config;
565
566 $sParent = GetParentFolder($folderPath);
567
568 // Ensure the folder path has no double-slashes, or mkdir may fail on certain platforms
569 while (strpos($folderPath, '//') !== false) {
570 $folderPath = str_replace('//', '/', $folderPath);
571 }
572
573 $permissiontouploadmediaisok = 1;
574 if (!empty($user->socid)) {
575 $permissiontouploadmediaisok = 0;
576 }
577 /*if (!$user->hasRight('website', 'write') && !$user->hasRight('mailing', 'write')) {
578 $permissiontouploadmediaisok = 0;
579 }*/
580 if (!$permissiontouploadmediaisok) {
581 return 'Bad permissions to create a folder in media directory';
582 }
583
584 // Check if the parent exists, or create it.
585 if (!empty($sParent) && !file_exists($sParent)) {
586 //prevents against infinite loop when we can't create root folder
587 if (!is_null($lastFolder) && $lastFolder === $sParent) {
588 return "Can't create $folderPath directory";
589 }
590
591 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
592 $sErrorMsg = CreateServerFolder($sParent, $folderPath);
593 if ($sErrorMsg != '') {
594 return $sErrorMsg;
595 }
596 }
597
598 if (!file_exists($folderPath)) {
599 // Turn off all error reporting.
600 error_reporting(0);
601
602 $php_errormsg = '';
603 // Enable error tracking to catch the error.
604 ini_set('track_errors', '1');
605
606 if (isset($Config['ChmodOnFolderCreate']) && !$Config['ChmodOnFolderCreate']) {
607 mkdir($folderPath);
608 } else {
609 $permissions = '0777';
610 if (isset($Config['ChmodOnFolderCreate']) && $Config['ChmodOnFolderCreate']) {
611 $permissions = (string) $Config['ChmodOnFolderCreate'];
612 }
613 $permissionsdec = octdec($permissions);
614 $permissionsdec |= octdec('0111'); // Set x bit required for directories
615 dol_syslog("connector.lib.php permission = ".$permissions." ".$permissionsdec." ".decoct($permissionsdec));
616 // To create the folder with 0777 permissions, we need to set umask to zero.
617 $oldumask = umask(0);
618 mkdir($folderPath, $permissionsdec);
619 umask($oldumask);
620 }
621
622 $sErrorMsg = $php_errormsg;
623
624 // Restore the configurations.
625 ini_restore('track_errors');
626 ini_restore('error_reporting');
627
628 return $sErrorMsg;
629 } else {
630 return '';
631 }
632}
633
639function GetRootPath()
640{
641 if (!isset($_SERVER)) {
642 global $_SERVER; // @phan-suppress-current-line PhanPluginConstantVariableNull
643 }
644 $sRealPath = realpath('./');
645 // #2124 ensure that no slash is at the end
646 $sRealPath = rtrim($sRealPath, "\\/");
647
648 $sSelfPath = $_SERVER['PHP_SELF'];
649 $sSelfPath = substr($sSelfPath, 0, strrpos($sSelfPath, '/'));
650
651 $sSelfPath = str_replace('/', DIRECTORY_SEPARATOR, $sSelfPath);
652
653 $position = strpos($sRealPath, $sSelfPath);
654
655 // This can check only that this script isn't run from a virtual dir
656 // But it avoids the problems that arise if it isn't checked
657 if ($position === false || $position != strlen($sRealPath) - strlen($sSelfPath)) {
658 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".');
659 }
660
661 return substr($sRealPath, 0, $position);
662}
663
669function Server_MapPath($path)
670{
671 // This function is available only for Apache
672 if (function_exists('apache_lookup_uri')) {
673 $info = apache_lookup_uri($path);
674 return $info->filename.$info->path_info;
675 }
676
677 // This isn't correct but for the moment there's no other solution
678 // If this script is under a virtual directory or symlink it will detect the problem and stop
679 return GetRootPath().$path;
680}
681
689function IsAllowedExt($sExtension, $resourceType)
690{
691 global $Config;
692 // Get the allowed and denied extensions arrays.
693 $arAllowed = $Config['AllowedExtensions'][$resourceType];
694 $arDenied = $Config['DeniedExtensions'][$resourceType];
695
696 if (count($arAllowed) > 0 && !in_array($sExtension, $arAllowed)) {
697 return false;
698 }
699
700 if (count($arDenied) > 0 && in_array($sExtension, $arDenied)) {
701 return false;
702 }
703
704 return true;
705}
706
713function IsAllowedType($resourceType)
714{
715 global $Config;
716 if (!in_array($resourceType, $Config['ConfigAllowedTypes'])) {
717 return false;
718 }
719
720 return true;
721}
722
729function IsAllowedCommand($sCommand)
730{
731 global $Config;
732
733 if (!in_array($sCommand, $Config['ConfigAllowedCommands'])) {
734 return false;
735 }
736
737 return true;
738}
739
745function GetCurrentFolder()
746{
747 $sCurrentFolder = isset($_GET['CurrentFolder']) ? GETPOST('CurrentFolder', 'alphanohtml', 1) : '/';
748
749 // Check the current folder syntax (must begin and start with a slash).
750 if (!preg_match('|/$|', $sCurrentFolder)) {
751 $sCurrentFolder .= '/';
752 }
753 if (strpos($sCurrentFolder, '/') !== 0) {
754 $sCurrentFolder = '/'.$sCurrentFolder;
755 }
756
757 // Ensure the folder path has no double-slashes
758 while (strpos($sCurrentFolder, '//') !== false) {
759 $sCurrentFolder = str_replace('//', '/', $sCurrentFolder);
760 }
761
762 // Check for invalid folder paths (..)
763 if (strpos($sCurrentFolder, '..') || strpos($sCurrentFolder, "\\")) {
764 SendError(102, '');
765 }
766
767 if (preg_match(",(/\.)|[[:cntrl:]]|(//)|(\\\\)|([\:\*\?\"<>\|]),", $sCurrentFolder)) {
768 SendError(102, '');
769 }
770
771 return $sCurrentFolder;
772}
773
780function SanitizeFolderName($sNewFolderName)
781{
782 $sNewFolderName = stripslashes($sNewFolderName);
783
784 // Remove . \ / | : ? * " < >
785 $sNewFolderName = preg_replace('/\\.|\\\\|\\/|\\||\\:|\\?|\\*|"|<|>|[[:cntrl:]]/', '_', $sNewFolderName);
786
787 return $sNewFolderName;
788}
789
796function SanitizeFileName($sNewFileName)
797{
798 global $Config;
799
800 $sNewFileName = stripslashes($sNewFileName);
801
802 // Replace dots in the name with underscores (only one dot can be there... security issue).
803 if ($Config['ForceSingleExtension']) {
804 $sNewFileName = preg_replace('/\\.(?![^.]*$)/', '_', $sNewFileName);
805 }
806
807 // Remove \ / | : ? * " < >
808 $sNewFileName = preg_replace('/\\\\|\\/|\\||\\:|\\?|\\*|"|<|>|[[:cntrl:]]/', '_', $sNewFileName);
809
810 return $sNewFileName;
811}
812
822function SendUploadResults($errorNumber, $fileUrl = '', $fileName = '', $customMsg = '')
823{
824 // Minified version of the document.domain automatic fix script (#1919).
825 // The original script can be found at _dev/domain_fix_template.js
826 echo <<<EOF
827<script type="text/javascript">
828(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;}}})();
829EOF;
830
831 if ($errorNumber && $errorNumber != '201') {
832 $fileUrl = "";
833 $fileName = "";
834 }
835
836 $rpl = array('\\' => '\\\\', '"' => '\\"');
837 echo 'console.log('.$errorNumber.');';
838 echo 'window.parent.OnUploadCompleted('.$errorNumber.', "'.strtr($fileUrl, $rpl).'", "'.strtr($fileName, $rpl).'", "'.strtr($customMsg, $rpl).'");';
839 echo '</script>';
840 exit;
841}
842
843
844// @CHANGE
845
846// This is the function that sends the results of the uploading process to CKE.
855function SendCKEditorResults($callback, $sFileUrl, $customMsg = '')
856{
857 echo '<script type="text/javascript">';
858
859 $rpl = array('\\' => '\\\\', '"' => '\\"');
860
861 echo 'window.parent.CKEDITOR.tools.callFunction("'.$callback.'","'.strtr($sFileUrl, $rpl).'", "'.strtr($customMsg, $rpl).'");';
862
863 echo '</script>';
864}
865
866
867
875function RemoveFromStart($sourceString, $charToRemove)
876{
877 $sPattern = '|^'.$charToRemove.'+|';
878 return preg_replace($sPattern, '', $sourceString);
879}
880
888function RemoveFromEnd($sourceString, $charToRemove)
889{
890 $sPattern = '|'.$charToRemove.'+$|';
891 return preg_replace($sPattern, '', $sourceString);
892}
893
900function FindBadUtf8($string)
901{
902 $regex = '([\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]';
903 $regex .= '|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2}|(.{1}))';
904
905 $matches = array();
906 while (preg_match('/'.$regex.'/S', $string, $matches)) {
907 if (isset($matches[2])) {
908 return true;
909 }
910 $string = substr($string, strlen($matches[0]));
911 }
912
913 return false;
914}
915
922function ConvertToXmlAttribute($value)
923{
924 if (defined('PHP_OS')) {
925 $os = PHP_OS;
926 } else {
927 $os = php_uname();
928 }
929
930 if (strtoupper(substr($os, 0, 3)) === 'WIN' || FindBadUtf8($value)) {
931 return (mb_convert_encoding(htmlspecialchars($value), 'UTF-8', 'ISO-8859-1'));
932 } else {
933 return (htmlspecialchars($value));
934 }
935}
936
944function IsHtmlExtension($ext, $formExtensions)
945{
946 if (!$formExtensions || !is_array($formExtensions)) {
947 return false;
948 }
949 $lcaseHtmlExtensions = array();
950 foreach ($formExtensions as $key => $val) {
951 $lcaseHtmlExtensions[$key] = strtolower($val);
952 }
953 return in_array($ext, $lcaseHtmlExtensions);
954}
955
963function DetectHtml($filePath)
964{
965 $fp = @fopen($filePath, 'rb');
966
967 //open_basedir restriction, see #1906
968 if ($fp === false || !flock($fp, LOCK_SH)) {
969 return -1;
970 }
971
972 $chunk = fread($fp, 1024);
973 flock($fp, LOCK_UN);
974 fclose($fp);
975
976 $chunk = strtolower($chunk);
977
978 if (!$chunk) {
979 return false;
980 }
981
982 $chunk = trim($chunk);
983
984 if (preg_match("/<!DOCTYPE\W*X?HTML/sim", $chunk)) {
985 return true;
986 }
987
988 $tags = array('<body', '<head', '<html', '<img', '<pre', '<script', '<table', '<title');
989
990 foreach ($tags as $tag) {
991 if (false !== strpos($chunk, $tag)) {
992 return true;
993 }
994 }
995
996 //type = javascript
997 if (preg_match('!type\s*=\s*[\'"]?\s*(?:\w*/)?(?:ecma|java)!sim', $chunk)) {
998 return true;
999 }
1000
1001 //href = javascript
1002 //src = javascript
1003 //data = javascript
1004 if (preg_match('!(?:href|src|data)\s*=\s*[\'"]?\s*(?:ecma|java)script:!sim', $chunk)) {
1005 return true;
1006 }
1007
1008 //url(javascript
1009 if (preg_match('!url\s*\‍(\s*[\'"]?\s*(?:ecma|java)script:!sim', $chunk)) {
1010 return true;
1011 }
1012
1013 return false;
1014}
1015
1024function IsImageValid($filePath, $extension)
1025{
1026 if (!@is_readable($filePath)) {
1027 return -1;
1028 }
1029
1030 $imageCheckExtensions = array(
1031 'gif',
1032 'jpeg',
1033 'jpg',
1034 'png',
1035 'swf',
1036 'psd',
1037 'bmp',
1038 'iff',
1039 'tiff',
1040 'tif',
1041 'swc',
1042 'jpc',
1043 'jp2',
1044 'jpx',
1045 'jb2',
1046 'xbm',
1047 'wbmp'
1048 );
1049
1050 if (!in_array($extension, $imageCheckExtensions)) {
1051 return true;
1052 }
1053
1054 if (@getimagesize($filePath) === false) {
1055 return false;
1056 }
1057
1058 return true;
1059}
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.
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.
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:149