dolibarr 21.0.3
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 dol_syslog("FileUpload sFileName=".$sFileName);
327
328 $sOriginalFileName = $sFileName;
329
330 // Get the extension.
331 $sExtension = substr($sFileName, (strrpos($sFileName, '.') + 1));
332 $sExtension = strtolower($sExtension);
333
334 // Check permission
335 $permissiontouploadmediaisok = 1;
336 if (!empty($user->socid)) {
337 $permissiontouploadmediaisok = 0;
338 }
339 /*if (!$user->hasRight('website', 'write') && !$user->hasRight('mailing', 'write')) {
340 $permissiontouploadmediaisok = 0;
341 }*/
342 if (!$permissiontouploadmediaisok) {
343 dol_syslog("connector.lib.php Try to upload a file with no permission");
344 $sErrorNumber = '204';
345 }
346
347 include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
348 //var_dump($sFileName); var_dump(image_format_supported($sFileName));exit;
349 $imgsupported = image_format_supported($sFileName);
350 $isImageValid = ($imgsupported >= 0);
351 if (!$isImageValid) {
352 $sErrorNumber = '202';
353 }
354
355
356 // Check if it is an allowed extension.
357 if (!$sErrorNumber) {
358 if (IsAllowedExt($sExtension, $resourceType)) {
359 $iCounter = 0;
360
361 while (true) {
362 $sFilePath = $sServerDir.$sFileName;
363
364 if (is_file($sFilePath)) {
365 $iCounter++;
366 $sFileName = RemoveExtension($sOriginalFileName).'('.$iCounter.').'.$sExtension;
367 $sErrorNumber = '201';
368 } else {
369 include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
370 dol_move_uploaded_file($oFile['tmp_name'], $sFilePath, 0, 0);
371
372 if (is_file($sFilePath)) {
373 if (isset($Config['ChmodOnUpload']) && !$Config['ChmodOnUpload']) {
374 break;
375 }
376
377 $permissions = '0777';
378 if (isset($Config['ChmodOnUpload']) && $Config['ChmodOnUpload']) {
379 $permissions = (string) $Config['ChmodOnUpload'];
380 }
381 $permissionsdec = octdec($permissions);
382 dol_syslog("connector.lib.php permission = ".$permissions." ".$permissionsdec." ".decoct($permissionsdec));
383 $oldumask = umask(0);
384 chmod($sFilePath, $permissionsdec);
385 umask($oldumask);
386 }
387
388 break;
389 }
390 }
391
392 if (file_exists($sFilePath)) {
393 //previous checks failed, try once again
394 if (isset($isImageValid) && $imgsupported === -1 && IsImageValid($sFilePath, $sExtension) === false) {
395 dol_syslog("connector.lib.php IsImageValid is ko");
396 @unlink($sFilePath);
397 $sErrorNumber = '202';
398 } else {
399 $detectHtml = DetectHtml($sFilePath);
400 if ($detectHtml === true || $detectHtml == -1) {
401 // Note that is is a simple test and not reliable. Security does not rely on this.
402 dol_syslog("connector.lib.php DetectHtml is ko detectHtml=".$detectHtml.", we delete the file.");
403 @unlink($sFilePath);
404 $sErrorNumber = '205';
405 }
406 }
407 }
408 } else {
409 $sErrorNumber = '202';
410 }
411 }
412 } else {
413 $sErrorNumber = '203';
414 }
415
416
417 $sFileUrl = CombinePaths(GetResourceTypePath($resourceType, $sCommand), $currentFolder);
418 $sFileUrl = CombinePaths($sFileUrl, $sFileName);
419
420
421 // @CHANGE
422 //SendUploadResults( $sErrorNumber, $sFileUrl, $sFileName );
423 if ($CKEcallback == '') {
424 // this line already exists so wrap the if block around it
425 SendUploadResults($sErrorNumber, $sFileUrl, $sFileName);
426 } else {
427 //issue the CKEditor Callback
428 SendCKEditorResults(
429 $CKEcallback,
430 $sFileUrl,
431 ($sErrorNumber != 0 ? 'Error '.$sErrorNumber.' upload failed.' : 'Upload Successful')
432 );
433 }
434
435 exit;
436}
437
438
439
447function CombinePaths($sBasePath, $sFolder)
448{
449 return RemoveFromEnd($sBasePath, '/').'/'.RemoveFromStart($sFolder, '/');
450}
451
459function GetResourceTypePath($resourceType, $sCommand)
460{
461 global $Config;
462
463 if ($sCommand == "QuickUpload") {
464 return $Config['QuickUploadPath'][$resourceType];
465 } else {
466 return $Config['FileTypesPath'][$resourceType];
467 }
468}
469
477function GetResourceTypeDirectory($resourceType, $sCommand)
478{
479 global $Config;
480 if ($sCommand == "QuickUpload") {
481 if (strlen($Config['QuickUploadAbsolutePath'][$resourceType]) > 0) {
482 return $Config['QuickUploadAbsolutePath'][$resourceType];
483 }
484
485 // Map the "UserFiles" path to a local directory.
486 return Server_MapPath($Config['QuickUploadPath'][$resourceType]);
487 } else {
488 if (strlen($Config['FileTypesAbsolutePath'][$resourceType]) > 0) {
489 return $Config['FileTypesAbsolutePath'][$resourceType];
490 }
491
492 // Map the "UserFiles" path to a local directory.
493 return Server_MapPath($Config['FileTypesPath'][$resourceType]);
494 }
495}
496
505function GetUrlFromPath($resourceType, $folderPath, $sCommand)
506{
507 return CombinePaths(GetResourceTypePath($resourceType, $sCommand), $folderPath);
508}
509
516function RemoveExtension($fileName)
517{
518 return substr($fileName, 0, strrpos($fileName, '.'));
519}
520
529function ServerMapFolder($resourceType, $folderPath, $sCommand)
530{
531 // Get the resource type directory.
532 $sResourceTypePath = GetResourceTypeDirectory($resourceType, $sCommand);
533
534 // Ensure that the directory exists.
535 $sErrorMsg = CreateServerFolder($sResourceTypePath);
536 if ($sErrorMsg != '') {
537 SendError(1, "Error creating folder \"$sResourceTypePath\" ($sErrorMsg)");
538 }
539
540 // Return the resource type directory combined with the required path.
541 return CombinePaths($sResourceTypePath, $folderPath);
542}
543
550function GetParentFolder($folderPath)
551{
552 $sPattern = "-[/\\\\][^/\\\\]+[/\\\\]?$-";
553 return preg_replace($sPattern, '', $folderPath);
554}
555
563function CreateServerFolder($folderPath, $lastFolder = null)
564{
565 global $user;
566 global $Config;
567
568 $sParent = GetParentFolder($folderPath);
569
570 // Ensure the folder path has no double-slashes, or mkdir may fail on certain platforms
571 while (strpos($folderPath, '//') !== false) {
572 $folderPath = str_replace('//', '/', $folderPath);
573 }
574
575 $permissiontouploadmediaisok = 1;
576 if (!empty($user->socid)) {
577 $permissiontouploadmediaisok = 0;
578 }
579 /*if (!$user->hasRight('website', 'write') && !$user->hasRight('mailing', 'write')) {
580 $permissiontouploadmediaisok = 0;
581 }*/
582 if (!$permissiontouploadmediaisok) {
583 return 'Bad permissions to create a folder in media directory';
584 }
585
586 // Check if the parent exists, or create it.
587 if (!empty($sParent) && !file_exists($sParent)) {
588 //prevents against infinite loop when we can't create root folder
589 if (!is_null($lastFolder) && $lastFolder === $sParent) {
590 return "Can't create $folderPath directory";
591 }
592
593 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
594 $sErrorMsg = CreateServerFolder($sParent, $folderPath);
595 if ($sErrorMsg != '') {
596 return $sErrorMsg;
597 }
598 }
599
600 if (!file_exists($folderPath)) {
601 // Turn off all error reporting.
602 error_reporting(0);
603
604 $php_errormsg = '';
605 // Enable error tracking to catch the error.
606 ini_set('track_errors', '1');
607
608 if (isset($Config['ChmodOnFolderCreate']) && !$Config['ChmodOnFolderCreate']) {
609 mkdir($folderPath);
610 } else {
611 $permissions = '0777';
612 if (isset($Config['ChmodOnFolderCreate']) && $Config['ChmodOnFolderCreate']) {
613 $permissions = (string) $Config['ChmodOnFolderCreate'];
614 }
615 $permissionsdec = octdec($permissions);
616 $permissionsdec |= octdec('0111'); // Set x bit required for directories
617 dol_syslog("connector.lib.php permission = ".$permissions." ".$permissionsdec." ".decoct($permissionsdec));
618 // To create the folder with 0777 permissions, we need to set umask to zero.
619 $oldumask = umask(0);
620 mkdir($folderPath, $permissionsdec);
621 umask($oldumask);
622 }
623
624 $sErrorMsg = $php_errormsg;
625
626 // Restore the configurations.
627 ini_restore('track_errors');
628 ini_restore('error_reporting');
629
630 return $sErrorMsg;
631 } else {
632 return '';
633 }
634}
635
641function GetRootPath()
642{
643 if (!isset($_SERVER)) {
644 global $_SERVER; // @phan-suppress-current-line PhanPluginConstantVariableNull
645 }
646 $sRealPath = realpath('./');
647 // #2124 ensure that no slash is at the end
648 $sRealPath = rtrim($sRealPath, "\\/");
649
650 $sSelfPath = $_SERVER['PHP_SELF'];
651 $sSelfPath = substr($sSelfPath, 0, strrpos($sSelfPath, '/'));
652
653 $sSelfPath = str_replace('/', DIRECTORY_SEPARATOR, $sSelfPath);
654
655 $position = strpos($sRealPath, $sSelfPath);
656
657 // This can check only that this script isn't run from a virtual dir
658 // But it avoids the problems that arise if it isn't checked
659 if ($position === false || $position != strlen($sRealPath) - strlen($sSelfPath)) {
660 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".');
661 }
662
663 return substr($sRealPath, 0, $position);
664}
665
671function Server_MapPath($path)
672{
673 // This function is available only for Apache
674 if (function_exists('apache_lookup_uri')) {
675 $info = apache_lookup_uri($path);
676 return $info->filename.$info->path_info;
677 }
678
679 // This isn't correct but for the moment there's no other solution
680 // If this script is under a virtual directory or symlink it will detect the problem and stop
681 return GetRootPath().$path;
682}
683
691function IsAllowedExt($sExtension, $resourceType)
692{
693 global $Config;
694 // Get the allowed and denied extensions arrays.
695 $arAllowed = $Config['AllowedExtensions'][$resourceType];
696 $arDenied = $Config['DeniedExtensions'][$resourceType];
697
698 if (count($arAllowed) > 0 && !in_array($sExtension, $arAllowed)) {
699 return false;
700 }
701
702 if (count($arDenied) > 0 && in_array($sExtension, $arDenied)) {
703 return false;
704 }
705
706 return true;
707}
708
715function IsAllowedType($resourceType)
716{
717 global $Config;
718 if (!in_array($resourceType, $Config['ConfigAllowedTypes'])) {
719 return false;
720 }
721
722 return true;
723}
724
731function IsAllowedCommand($sCommand)
732{
733 global $Config;
734
735 if (!in_array($sCommand, $Config['ConfigAllowedCommands'])) {
736 return false;
737 }
738
739 return true;
740}
741
747function GetCurrentFolder()
748{
749 $sCurrentFolder = isset($_GET['CurrentFolder']) ? GETPOST('CurrentFolder', 'alphanohtml', 1) : '/';
750
751 // Check the current folder syntax (must begin and start with a slash).
752 if (!preg_match('|/$|', $sCurrentFolder)) {
753 $sCurrentFolder .= '/';
754 }
755 if (strpos($sCurrentFolder, '/') !== 0) {
756 $sCurrentFolder = '/'.$sCurrentFolder;
757 }
758
759 // Ensure the folder path has no double-slashes
760 while (strpos($sCurrentFolder, '//') !== false) {
761 $sCurrentFolder = str_replace('//', '/', $sCurrentFolder);
762 }
763
764 // Check for invalid folder paths (..)
765 if (strpos($sCurrentFolder, '..') || strpos($sCurrentFolder, "\\")) {
766 SendError(102, '');
767 }
768
769 if (preg_match(",(/\.)|[[:cntrl:]]|(//)|(\\\\)|([\:\*\?\"<>\|]),", $sCurrentFolder)) {
770 SendError(102, '');
771 }
772
773 return $sCurrentFolder;
774}
775
782function SanitizeFolderName($sNewFolderName)
783{
784 $sNewFolderName = stripslashes($sNewFolderName);
785
786 // Remove . \ / | : ? * " < >
787 $sNewFolderName = preg_replace('/\\.|\\\\|\\/|\\||\\:|\\?|\\*|"|<|>|[[:cntrl:]]/', '_', $sNewFolderName);
788
789 return $sNewFolderName;
790}
791
798function SanitizeFileName($sNewFileName)
799{
800 global $Config;
801
802 $sNewFileName = stripslashes($sNewFileName);
803
804 // Replace dots in the name with underscores (only one dot can be there... security issue).
805 if ($Config['ForceSingleExtension']) {
806 $sNewFileName = preg_replace('/\\.(?![^.]*$)/', '_', $sNewFileName);
807 }
808
809 // Remove \ / | : ? * " < >
810 $sNewFileName = preg_replace('/\\\\|\\/|\\||\\:|\\?|\\*|"|<|>|[[:cntrl:]]/', '_', $sNewFileName);
811
812 return $sNewFileName;
813}
814
824function SendUploadResults($errorNumber, $fileUrl = '', $fileName = '', $customMsg = '')
825{
826 // Minified version of the document.domain automatic fix script (#1919).
827 // The original script can be found at _dev/domain_fix_template.js
828 echo <<<EOF
829<script type="text/javascript">
830(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;}}})();
831EOF;
832
833 if ($errorNumber && $errorNumber != '201') {
834 $fileUrl = "";
835 $fileName = "";
836 }
837
838 $rpl = array('\\' => '\\\\', '"' => '\\"');
839 echo 'console.log('.$errorNumber.');';
840 echo 'window.parent.OnUploadCompleted('.$errorNumber.', "'.strtr($fileUrl, $rpl).'", "'.strtr($fileName, $rpl).'", "'.strtr($customMsg, $rpl).'");';
841 echo '</script>';
842 exit;
843}
844
845
846// @CHANGE
847
848// This is the function that sends the results of the uploading process to CKE.
857function SendCKEditorResults($callback, $sFileUrl, $customMsg = '')
858{
859 echo '<script type="text/javascript">';
860
861 $rpl = array('\\' => '\\\\', '"' => '\\"');
862
863 echo 'window.parent.CKEDITOR.tools.callFunction("'.$callback.'","'.strtr($sFileUrl, $rpl).'", "'.strtr($customMsg, $rpl).'");';
864
865 echo '</script>';
866}
867
868
869
877function RemoveFromStart($sourceString, $charToRemove)
878{
879 $sPattern = '|^'.$charToRemove.'+|';
880 return preg_replace($sPattern, '', $sourceString);
881}
882
890function RemoveFromEnd($sourceString, $charToRemove)
891{
892 $sPattern = '|'.$charToRemove.'+$|';
893 return preg_replace($sPattern, '', $sourceString);
894}
895
902function FindBadUtf8($string)
903{
904 $regex = '([\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]';
905 $regex .= '|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2}|(.{1}))';
906
907 $matches = array();
908 while (preg_match('/'.$regex.'/S', $string, $matches)) {
909 if (isset($matches[2])) {
910 return true;
911 }
912 $string = substr($string, strlen($matches[0]));
913 }
914
915 return false;
916}
917
924function ConvertToXmlAttribute($value)
925{
926 if (defined('PHP_OS')) {
927 $os = PHP_OS;
928 } else {
929 $os = php_uname();
930 }
931
932 if (strtoupper(substr($os, 0, 3)) === 'WIN' || FindBadUtf8($value)) {
933 return (mb_convert_encoding(htmlspecialchars($value), 'UTF-8', 'ISO-8859-1'));
934 } else {
935 return (htmlspecialchars($value));
936 }
937}
938
946function IsHtmlExtension($ext, $formExtensions)
947{
948 if (!$formExtensions || !is_array($formExtensions)) {
949 return false;
950 }
951 $lcaseHtmlExtensions = array();
952 foreach ($formExtensions as $key => $val) {
953 $lcaseHtmlExtensions[$key] = strtolower($val);
954 }
955 return in_array($ext, $lcaseHtmlExtensions);
956}
957
965function DetectHtml($filePath)
966{
967 $fp = @fopen($filePath, 'rb');
968
969 if ($fp === false) {
970 return -1;
971 }
972
973 $chunk = fread($fp, 1024);
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, $includequotes=0)
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:150