dolibarr 25.0.0-alpha
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-2026 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 $sErrorNumber = '0';
303 $sFileName = '';
304
305 // (_FILES indexes:) @phan-suppress-next-line PhanTypeInvalidDimOffset
306 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']))) {
307 global $Config;
308
309 $oFile = isset($_FILES['NewFile']) ? $_FILES['NewFile'] : $_FILES['upload'];
310
311 // $resourceType should be 'Image';
312 $detectHtml = 0;
313
314 // Map the virtual path to the local server path.
315 $sServerDir = ServerMapFolder($resourceType, $currentFolder, $sCommand);
316
317 // Get the uploaded file name.
318 $sFileName = $oFile['name'];
319
320 //$sFileName = SanitizeFileName($sFileName);
321 $sFileName = dol_sanitizeFileName($sFileName);
322
323 dol_syslog("FileUpload sFileName=".$sFileName);
324
325 $sOriginalFileName = $sFileName;
326
327 // Get the extension.
328 $sExtension = substr($sFileName, (strrpos($sFileName, '.') + 1));
329 $sExtension = strtolower($sExtension);
330
331 // Check permission
332 $permissiontouploadmediaisok = 1;
333 if (!empty($user->socid)) {
334 $permissiontouploadmediaisok = 0;
335 }
336 /*if (!$user->hasRight('website', 'write') && !$user->hasRight('mailing', 'write')) {
337 $permissiontouploadmediaisok = 0;
338 }*/
339 if (!$permissiontouploadmediaisok) {
340 dol_syslog("connector.lib.php Try to upload a file with no permission");
341 $sErrorNumber = '204';
342 }
343
344 include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
345 //var_dump($sFileName); var_dump(image_format_supported($sFileName));exit;
346 $imgsupported = image_format_supported($sFileName);
347 $isImageValid = ($imgsupported >= 0);
348 if (!$isImageValid) {
349 $sErrorNumber = '202';
350 }
351
352
353 // Check if it is an allowed extension.
354 if (!$sErrorNumber) {
355 if (IsAllowedExt($sExtension, $resourceType)) {
356 $iCounter = 0;
357
358 while (true) {
359 $sFilePath = $sServerDir.$sFileName;
360
361 if (is_file($sFilePath)) {
362 $iCounter++;
363 $sFileName = RemoveExtension($sOriginalFileName).'('.$iCounter.').'.$sExtension;
364 $sErrorNumber = '201';
365 } else {
366 include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
367 dol_move_uploaded_file($oFile['tmp_name'], $sFilePath, 0, 0);
368
369 if (is_file($sFilePath)) {
370 if (isset($Config['ChmodOnUpload']) && !$Config['ChmodOnUpload']) {
371 break;
372 }
373
374 $permissions = '0777';
375 if (isset($Config['ChmodOnUpload']) && $Config['ChmodOnUpload']) {
376 $permissions = (string) $Config['ChmodOnUpload'];
377 }
378 $permissionsdec = octdec($permissions);
379 dol_syslog("connector.lib.php permission = ".$permissions." ".$permissionsdec." ".decoct($permissionsdec));
380 $oldumask = umask(0);
381 chmod($sFilePath, $permissionsdec);
382 umask($oldumask);
383 }
384
385 break;
386 }
387 }
388
389 if (file_exists($sFilePath)) {
390 //previous checks failed, try once again
391 if ($imgsupported === -1 && IsImageValid($sFilePath, $sExtension) === false) {
392 dol_syslog("connector.lib.php IsImageValid is ko");
393 @unlink($sFilePath);
394 $sErrorNumber = '202';
395 } else {
396 $detectHtml = DetectHtml($sFilePath);
397 if ($detectHtml === true || $detectHtml == -1) {
398 // Note that is is a simple test and not reliable. Security does not rely on this.
399 dol_syslog("connector.lib.php DetectHtml is ko detectHtml=".$detectHtml.", we delete the file.");
400 @unlink($sFilePath);
401 $sErrorNumber = '205';
402 }
403 }
404 }
405 } else {
406 $sErrorNumber = '202';
407 }
408 }
409 } else {
410 $sErrorNumber = '203';
411 }
412
413
414 $sFileUrl = CombinePaths(GetResourceTypePath($resourceType, $sCommand), $currentFolder);
415 $sFileUrl = CombinePaths($sFileUrl, $sFileName);
416
417
418 // @CHANGE
419 //SendUploadResults( $sErrorNumber, $sFileUrl, $sFileName );
420 if ($CKEcallback == '') {
421 // this line already exists so wrap the if block around it
422 SendUploadResults($sErrorNumber, $sFileUrl, $sFileName);
423 } else {
424 //issue the CKEditor Callback
425 SendCKEditorResults(
426 $CKEcallback,
427 $sFileUrl,
428 ($sErrorNumber != 0 ? 'Error '.$sErrorNumber.' upload failed.' : 'Upload Successful')
429 );
430 }
431
432 exit;
433}
434
435
436
444function CombinePaths($sBasePath, $sFolder)
445{
446 return RemoveFromEnd($sBasePath, '/').'/'.RemoveFromStart($sFolder, '/');
447}
448
456function GetResourceTypePath($resourceType, $sCommand)
457{
458 global $Config;
459
460 if ($sCommand == "QuickUpload") {
461 return $Config['QuickUploadPath'][$resourceType];
462 } else {
463 return $Config['FileTypesPath'][$resourceType];
464 }
465}
466
474function GetResourceTypeDirectory($resourceType, $sCommand)
475{
476 global $Config;
477 if ($sCommand == "QuickUpload") {
478 if (strlen($Config['QuickUploadAbsolutePath'][$resourceType]) > 0) {
479 return $Config['QuickUploadAbsolutePath'][$resourceType];
480 }
481
482 // Map the "UserFiles" path to a local directory.
483 return Server_MapPath($Config['QuickUploadPath'][$resourceType]);
484 } else {
485 if (strlen($Config['FileTypesAbsolutePath'][$resourceType]) > 0) {
486 return $Config['FileTypesAbsolutePath'][$resourceType];
487 }
488
489 // Map the "UserFiles" path to a local directory.
490 return Server_MapPath($Config['FileTypesPath'][$resourceType]);
491 }
492}
493
502function GetUrlFromPath($resourceType, $folderPath, $sCommand)
503{
504 return CombinePaths(GetResourceTypePath($resourceType, $sCommand), $folderPath);
505}
506
513function RemoveExtension($fileName)
514{
515 return dol_substr($fileName, 0, strrpos($fileName, '.'));
516}
517
526function ServerMapFolder($resourceType, $folderPath, $sCommand)
527{
528 // Get the resource type directory.
529 $sResourceTypePath = GetResourceTypeDirectory($resourceType, $sCommand);
530
531 // Ensure that the directory exists.
532 $sErrorMsg = CreateServerFolder($sResourceTypePath);
533 if ($sErrorMsg != '') {
534 SendError(1, "Error creating folder \"$sResourceTypePath\" ($sErrorMsg)");
535 }
536
537 // Return the resource type directory combined with the required path.
538 return CombinePaths($sResourceTypePath, $folderPath);
539}
540
547function GetParentFolder($folderPath)
548{
549 $sPattern = "-[/\\\\][^/\\\\]+[/\\\\]?$-";
550 return preg_replace($sPattern, '', $folderPath);
551}
552
560function CreateServerFolder($folderPath, $lastFolder = null)
561{
562 global $user;
563 global $Config;
564
565 $sParent = GetParentFolder($folderPath);
566
567 // Ensure the folder path has no double-slashes, or mkdir may fail on certain platforms
568 while (strpos($folderPath, '//') !== false) {
569 $folderPath = str_replace('//', '/', $folderPath);
570 }
571
572 $permissiontouploadmediaisok = 1;
573 if (!empty($user->socid)) {
574 $permissiontouploadmediaisok = 0;
575 }
576 /*if (!$user->hasRight('website', 'write') && !$user->hasRight('mailing', 'write')) {
577 $permissiontouploadmediaisok = 0;
578 }*/
579 if (!$permissiontouploadmediaisok) {
580 return 'Bad permissions to create a folder in media directory';
581 }
582
583 // Check if the parent exists, or create it.
584 if (!empty($sParent) && !file_exists($sParent)) {
585 //prevents against infinite loop when we can't create root folder
586 if (!is_null($lastFolder) && $lastFolder === $sParent) {
587 return "Can't create $folderPath directory";
588 }
589
590 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
591 $sErrorMsg = CreateServerFolder($sParent, $folderPath);
592 if ($sErrorMsg != '') {
593 return $sErrorMsg;
594 }
595 }
596
597 if (!file_exists($folderPath)) {
598 // Turn off all error reporting.
599 error_reporting(0);
600
601 $php_errormsg = '';
602 // Enable error tracking to catch the error.
603 ini_set('track_errors', '1');
604
605 if (isset($Config['ChmodOnFolderCreate']) && !$Config['ChmodOnFolderCreate']) {
606 mkdir($folderPath);
607 } else {
608 $permissions = '0777';
609 if (isset($Config['ChmodOnFolderCreate']) && $Config['ChmodOnFolderCreate']) {
610 $permissions = (string) $Config['ChmodOnFolderCreate'];
611 }
612 $permissionsdec = octdec($permissions);
613 $permissionsdec |= octdec('0111'); // Set x bit required for directories
614 dol_syslog("connector.lib.php permission = ".$permissions." ".$permissionsdec." ".decoct($permissionsdec));
615 // To create the folder with 0777 permissions, we need to set umask to zero.
616 $oldumask = umask(0);
617 mkdir($folderPath, $permissionsdec);
618 umask($oldumask);
619 }
620
621 $sErrorMsg = $php_errormsg;
622
623 // Restore the configurations.
624 ini_restore('track_errors');
625 ini_restore('error_reporting');
626
627 return $sErrorMsg;
628 } else {
629 return '';
630 }
631}
632
638function GetRootPath()
639{
640 $sRealPath = realpath('./');
641 // #2124 ensure that no slash is at the end
642 $sRealPath = rtrim($sRealPath, "\\/");
643
644 $sSelfPath = $_SERVER['PHP_SELF'];
645 $sSelfPath = substr($sSelfPath, 0, strrpos($sSelfPath, '/'));
646
647 $sSelfPath = str_replace('/', DIRECTORY_SEPARATOR, $sSelfPath);
648
649 $position = strpos($sRealPath, $sSelfPath);
650
651 // This can check only that this script isn't run from a virtual dir
652 // But it avoids the problems that arise if it isn't checked
653 if ($position === false || $position != strlen($sRealPath) - strlen($sSelfPath)) {
654 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".');
655 }
656
657 return substr($sRealPath, 0, $position);
658}
659
665function Server_MapPath($path)
666{
667 // This function is available only for Apache
668 if (function_exists('apache_lookup_uri')) {
669 $info = apache_lookup_uri($path);
670 return $info->filename.$info->path_info;
671 }
672
673 // This isn't correct but for the moment there's no other solution
674 // If this script is under a virtual directory or symlink it will detect the problem and stop
675 return GetRootPath().$path;
676}
677
685function IsAllowedExt($sExtension, $resourceType)
686{
687 global $Config;
688 // Get the allowed and denied extensions arrays.
689 $arAllowed = $Config['AllowedExtensions'][$resourceType];
690 $arDenied = $Config['DeniedExtensions'][$resourceType];
691
692 if (count($arAllowed) > 0 && !in_array($sExtension, $arAllowed)) {
693 return false;
694 }
695
696 if (count($arDenied) > 0 && in_array($sExtension, $arDenied)) {
697 return false;
698 }
699
700 return true;
701}
702
709function IsAllowedType($resourceType)
710{
711 global $Config;
712 if (!in_array($resourceType, $Config['ConfigAllowedTypes'])) {
713 return false;
714 }
715
716 return true;
717}
718
725function IsAllowedCommand($sCommand)
726{
727 global $Config;
728
729 if (!in_array($sCommand, $Config['ConfigAllowedCommands'])) {
730 return false;
731 }
732
733 return true;
734}
735
741function GetCurrentFolder()
742{
743 $sCurrentFolder = isset($_GET['CurrentFolder']) ? GETPOST('CurrentFolder', 'alphanohtml', 1) : '/';
744
745 // Check the current folder syntax (must begin and start with a slash).
746 if (!preg_match('|/$|', $sCurrentFolder)) {
747 $sCurrentFolder .= '/';
748 }
749 if (strpos($sCurrentFolder, '/') !== 0) {
750 $sCurrentFolder = '/'.$sCurrentFolder;
751 }
752
753 // Ensure the folder path has no double-slashes
754 while (strpos($sCurrentFolder, '//') !== false) {
755 $sCurrentFolder = str_replace('//', '/', $sCurrentFolder);
756 }
757
758 // Check for invalid folder paths (..)
759 if (strpos($sCurrentFolder, '..') || strpos($sCurrentFolder, "\\")) {
760 SendError(102, '');
761 }
762
763 if (preg_match(",(/\.)|[[:cntrl:]]|(//)|(\\\\)|([\:\*\?\"<>\|]),", $sCurrentFolder)) {
764 SendError(102, '');
765 }
766
767 return $sCurrentFolder;
768}
769
776function SanitizeFolderName($sNewFolderName)
777{
778 $sNewFolderName = stripslashes($sNewFolderName);
779
780 // Remove . \ / | : ? * " < >
781 $sNewFolderName = preg_replace('/\\.|\\\\|\\/|\\||\\:|\\?|\\*|"|<|>|[[:cntrl:]]/', '_', $sNewFolderName);
782
783 return $sNewFolderName;
784}
785
792function SanitizeFileName($sNewFileName)
793{
794 global $Config;
795
796 $sNewFileName = stripslashes($sNewFileName);
797
798 // Replace dots in the name with underscores (only one dot can be there... security issue).
799 if ($Config['ForceSingleExtension']) {
800 $sNewFileName = preg_replace('/\\.(?![^.]*$)/', '_', $sNewFileName);
801 }
802
803 // Remove \ / | : ? * " < >
804 $sNewFileName = preg_replace('/\\\\|\\/|\\||\\:|\\?|\\*|"|<|>|[[:cntrl:]]/', '_', $sNewFileName);
805
806 return $sNewFileName;
807}
808
818function SendUploadResults($errorNumber, $fileUrl = '', $fileName = '', $customMsg = '')
819{
820 // Minified version of the document.domain automatic fix script (#1919).
821 // The original script can be found at _dev/domain_fix_template.js
822 echo <<<EOF
823<script type="text/javascript">
824(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;}}})();
825EOF;
826
827 if ($errorNumber && $errorNumber != '201') {
828 $fileUrl = "";
829 $fileName = "";
830 }
831
832 $rpl = array('\\' => '\\\\', '"' => '\\"');
833 echo 'console.log('.$errorNumber.');';
834 echo 'window.parent.OnUploadCompleted('.$errorNumber.', "'.strtr($fileUrl, $rpl).'", "'.strtr($fileName, $rpl).'", "'.strtr($customMsg, $rpl).'");';
835 echo '</script>';
836 exit;
837}
838
839
840// @CHANGE
841
842// This is the function that sends the results of the uploading process to CKE.
851function SendCKEditorResults($callback, $sFileUrl, $customMsg = '')
852{
853 echo '<script type="text/javascript">';
854
855 $rpl = array('\\' => '\\\\', '"' => '\\"');
856
857 echo 'window.parent.CKEDITOR.tools.callFunction("'.$callback.'","'.strtr($sFileUrl, $rpl).'", "'.strtr($customMsg, $rpl).'");';
858
859 echo '</script>';
860}
861
862
863
871function RemoveFromStart($sourceString, $charToRemove)
872{
873 $sPattern = '|^'.$charToRemove.'+|';
874 return preg_replace($sPattern, '', $sourceString);
875}
876
884function RemoveFromEnd($sourceString, $charToRemove)
885{
886 $sPattern = '|'.$charToRemove.'+$|';
887 return preg_replace($sPattern, '', $sourceString);
888}
889
896function FindBadUtf8($string)
897{
898 $regex = '([\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]';
899 $regex .= '|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2}|(.{1}))';
900
901 $matches = array();
902 while (preg_match('/'.$regex.'/S', $string, $matches)) {
903 if (isset($matches[2])) {
904 return true;
905 }
906 $string = substr($string, strlen($matches[0]));
907 }
908
909 return false;
910}
911
918function ConvertToXmlAttribute($value)
919{
920 if (defined('PHP_OS')) {
921 $os = PHP_OS;
922 } else {
923 $os = php_uname();
924 }
925
926 if (strtoupper(substr($os, 0, 3)) === 'WIN' || FindBadUtf8($value)) {
927 return (mb_convert_encoding(htmlspecialchars($value), 'UTF-8', 'ISO-8859-1'));
928 } else {
929 return (htmlspecialchars($value));
930 }
931}
932
940function IsHtmlExtension($ext, $formExtensions)
941{
942 if (!$formExtensions || !is_array($formExtensions)) {
943 return false;
944 }
945 $lcaseHtmlExtensions = array();
946 foreach ($formExtensions as $key => $val) {
947 $lcaseHtmlExtensions[$key] = strtolower($val);
948 }
949 return in_array($ext, $lcaseHtmlExtensions);
950}
951
959function DetectHtml($filePath)
960{
961 $fp = @fopen($filePath, 'rb');
962
963 if ($fp === false) {
964 return -1;
965 }
966
967 $chunk = fread($fp, 1024);
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
1018function 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}
$propal type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition propal.php:280
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, $keyforsourcefile='addedfile', $upload_dir='', $mode=0)
Check validity of a file upload from an GUI page, and move it to its final destination.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
dol_substr($string, $start, $length=null, $stringencoding='', $trunconbytes=0)
Make a substring.
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.