From 04e7ba74f1126374718a4a2fd9579935aa15da40 Mon Sep 17 00:00:00 2001
From: appu <apparao@vtiger.com>
Date: Wed, 22 Nov 2023 11:28:34 +0530
Subject: [PATCH] 1790:Logo upload issue fixed

---
 include/utils/VtlibUtils.php                  | 26 ++++-----
 .../Vtiger/actions/CompanyDetailsSave.php     | 30 +++++-----
 vtlib/Vtiger/Functions.php                    | 55 +++++++++++--------
 3 files changed, 60 insertions(+), 51 deletions(-)

diff --git a/include/utils/VtlibUtils.php b/include/utils/VtlibUtils.php
index 9d8122d19..1215aea17 100644
--- a/include/utils/VtlibUtils.php
+++ b/include/utils/VtlibUtils.php
@@ -665,11 +665,10 @@ function vtlib_purify($input, $ignore = false) {
     static $purified_cache = array();
     $value = $input;
 
-	$encryptInput = null;
     if (!is_array($input)) {
-        $encryptInput = hash('sha256',$input);
-        if (array_key_exists($encryptInput, $purified_cache)) {
-            $value = $purified_cache[$encryptInput];
+        $md5OfInput = md5($input);
+        if (array_key_exists($md5OfInput, $purified_cache)) {
+            $value = $purified_cache[$md5OfInput];
             //to escape cleaning up again
             $ignore = true;
         }
@@ -677,7 +676,6 @@ function vtlib_purify($input, $ignore = false) {
     $use_charset = $default_charset;
     $use_root_directory = $root_directory;
 
-
     if (!$ignore) {
         // Initialize the instance if it has not yet done
         if ($__htmlpurifier_instance == false) {
@@ -702,6 +700,7 @@ function vtlib_purify($input, $ignore = false) {
             $config->set('CSS.AllowTricky', true);
             $config->set('URI.AllowedSchemes', $allowedSchemes);
             $config->set('Attr.EnableID', true);
+            $config->set('HTML.TargetBlank', true);
 
             $__htmlpurifier_instance = new HTMLPurifier($config);
         }
@@ -717,14 +716,9 @@ function vtlib_purify($input, $ignore = false) {
                 $value = purifyHtmlEventAttributes($value, true);
             }
         }
-        if ($encryptInput != null) {
-			$purified_cache[$encryptInput] = $value;
-    	}
-	}
-
-	if ($value && !is_array($value)) {
-		$value = str_replace('&amp;', '&', $value);
-	}
+        $purified_cache[$md5OfInput] = $value;
+    }
+    $value = str_replace('&amp;', '&', $value);
     return $value;
 }
 
@@ -764,7 +758,7 @@ $htmlEventAttributes = "onerror|onblur|onchange|oncontextmenu|onfocus|oninput|on
         //remove script tag with contents
         $value = purifyScript($value);
         //purify javascript alert from the tag contents
-        $value = purifyJavascriptAlert($value); 
+        $value = purifyJavascriptAlert($value);
 	
     } else {
         if (preg_match("/\s*(" . $htmlEventAttributes . ")\s*=/i", $value)) {
@@ -810,8 +804,8 @@ function purifyJavascriptAlert($value){
             $javaScriptRegex = '/(&.*?lt;|<).?'.$tag.'[^>]*(j[\s]?a[\s]?v[\s]?a[\s]?s[\s]?c[\s]?r[\s]?i[\s]?p[\s]?t[\s]*[=&%#:])[^>]*?(>|&.*?gt;)/i';
             foreach($matches[0] as $matchedValue){
                 //strict check addded - if &tab;/&newLine added in the above tags we are replacing it to spaces.
-                $purifyContent = preg_replace('/&NewLine;|&amp;NewLine;|&Tab;|&amp;Tab;|\t/i',' ',$purifyContent);
-		$purifyContent = preg_replace($javaScriptRegex,"<$tag>",decode_html($matchedValue));
+                $purifyContent = preg_replace('/&NewLine;|&amp;NewLine;|&Tab;|&amp;Tab;|\t/i',' ',decode_html($matchedValue));
+                $purifyContent = preg_replace($javaScriptRegex,"<$tag>",$purifyContent);
                 $value = str_replace($matchedValue, $purifyContent, $value);
                 
                 /*
diff --git a/modules/Settings/Vtiger/actions/CompanyDetailsSave.php b/modules/Settings/Vtiger/actions/CompanyDetailsSave.php
index f13b1fe9d..6aa4d09bc 100644
--- a/modules/Settings/Vtiger/actions/CompanyDetailsSave.php
+++ b/modules/Settings/Vtiger/actions/CompanyDetailsSave.php
@@ -32,29 +32,33 @@ class Settings_Vtiger_CompanyDetailsSave_Action extends Settings_Vtiger_Basic_Ac
 		$status = false;
 		if ($request->get('organizationname')) {
 			$saveLogo = $status = true;
-			$logoName = false;
+			$binFileName = false;
 			if(!empty($_FILES['logo']['name'])) {
-                                $logoDetails = $_FILES['logo'];
+				$logoDetails = $_FILES['logo'];
 				$saveLogo = Vtiger_Functions::validateImage($logoDetails);
-                                global $upload_badext;// from config.inc.php
-				$logoName = sanitizeUploadFileName($logoDetails['name'], $upload_badext);
-				if ($saveLogo && pathinfo($logoName, PATHINFO_EXTENSION) != 'txt') {
-					$moduleModel->saveLogo($logoName);
-                                } else {
-					$saveLogo = false;
+				if (is_string($saveLogo)) $saveLogo = ($saveLogo == 'false')? false : true;
+
+				global $upload_badext;//from config.inc.php
+				$binFileName = sanitizeUploadFileName($logoDetails['name'], $upload_badext);
+				if ($saveLogo && pathinfo($binFileName, PATHINFO_EXTENSION) != 'txt') {
+					$moduleModel->saveLogo($binFileName);
+				}else{
+					throw new Exception(vtranslate('LBL_INVALID_IMAGE'),103);
 				}
-			}else{
+			} else {
 				$saveLogo = true;
 			}
 			$fields = $moduleModel->getFields();
 			foreach ($fields as $fieldName => $fieldType) {
 				$fieldValue = $request->get($fieldName);
 				if ($fieldName === 'logoname') {
-					if (!empty($logoDetails['name']) && $logoName) {
-						$fieldValue = decode_html(ltrim(basename(" " . $logoName)));
+					if (!empty($logoDetails['name']) && $binFileName) {
+						$fieldValue = decode_html(ltrim(basename(" " . $binFileName)));
 					} else {
 						$fieldValue = decode_html($moduleModel->get($fieldName));
 					}
+				} else {
+					$fieldValue = strip_tags(decode_html($fieldValue));
 				}
 				// In OnBoard company detail page we will not be sending all the details
 				if($request->has($fieldName) || ($fieldName == "logoname")) {
@@ -74,8 +78,8 @@ class Settings_Vtiger_CompanyDetailsSave_Action extends Settings_Vtiger_Basic_Ac
 		}
 		return;
 	}
-
+	
 	public function validateRequest(Vtiger_Request $request) {
 		$request->validateWriteAccess();
 	}
-}
+}
\ No newline at end of file
diff --git a/vtlib/Vtiger/Functions.php b/vtlib/Vtiger/Functions.php
index ab4d4a328..f61b27dc3 100644
--- a/vtlib/Vtiger/Functions.php
+++ b/vtlib/Vtiger/Functions.php
@@ -647,53 +647,64 @@ class Vtiger_Functions {
             $file_details['type'] = mime_content_type($file_details['tmp_name']);
         }
 
-        $filetype = strtolower(pathinfo($file_details['name'], PATHINFO_EXTENSION));
-        $saveimage = in_array($filetype, $allowedImageFormats);
+        $mimeTypesList = array_merge($allowedImageFormats, array('x-ms-bmp')); //bmp another format
+        $file_type_details = explode("/", $file_details['type']);
+        $filetype = $file_type_details['1'];
+        if ($filetype) {
+            $filetype = strtolower($filetype);
+        }
+
+        $saveimage = 'true';
+        if (!in_array($filetype, $allowedImageFormats)) {
+            $saveimage = 'false';
+        }
 
-        if ($saveimage) {
+        //mime type check
+        if ($saveimage == 'true') {
             $mimeType = mime_content_type($file_details['tmp_name']);
-            list($mimeTypeContents, $mimeSubtype) = explode('/', $mimeType);
-            if (strtolower($mimeTypeContents) !== 'image' || !in_array($mimeSubtype, $allowedImageFormats)) {
-                $saveimage = false;
+            $mimeTypeContents = explode('/', $mimeType);
+            if (!$file_details['size'] || strtolower($mimeTypeContents[0]) !== 'image' || !in_array($mimeTypeContents[1], $mimeTypesList)) {
+                $saveimage = 'false';
             }
         }
 
+        //metadata check
         $shortTagSupported = ini_get('short_open_tag') ? true : false;
-
-        if ($saveimage) {
+        if ($saveimage == 'true') {
             $tmpFileName = $file_details['tmp_name'];
 
-            if (in_array($file_details['type'], ['image/jpeg', 'image/tiff'])) {
-                $exifdata = @exif_read_data($tmpFileName);
+            if ($file_details['type'] == 'image/jpeg' || $file_details['type'] == 'image/tiff') {
+                $exifdata = @exif_read_data($file_details['tmp_name']);
                 if ($exifdata && !self::validateImageMetadata($exifdata, $shortTagSupported)) {
-                    $saveimage = false;
+                    $saveimage = 'false';
                 }
-
-                if ($saveimage && $file_details['type'] == 'image/jpeg' && extension_loaded('gd') && function_exists('gd_info')) {
+                //131225968::remove sensitive information(like,GPS or camera information) from the image
+                if (($saveimage == 'true' ) && ($file_details['type'] == 'image/jpeg' ) && extension_loaded('gd') && function_exists('gd_info')) {
                     $img = imagecreatefromjpeg($tmpFileName);
                     imagejpeg($img, $tmpFileName);
                 }
             }
         }
 
-        if ($saveimage) {
+        if ($saveimage == 'true') {
             $imageContents = file_get_contents($tmpFileName);
-            $shortTag = $shortTagSupported ? "<?" : "<?php";
-            if (stripos($imageContents, $shortTag) !== false) {
-                $saveimage = false;
+            if (stripos($imageContents, $shortTagSupported ? "<?" : "<?php") !== false) { // suspicious dynamic content.
+                $saveimage = 'false';
             }
         }
 
-        if ($saveimage && in_array($filetype, ['svg+xml', $mimeSubtype])) {
-            // Remove malicious HTML attributes with values from the contents.
+        if (($filetype == 'svg+xml' || $mimeTypeContents[1] == 'svg+xml') && $saveimage == 'true') {
+            //remove malicious html attributes with its value from the contents.
             $imageContents = purifyHtmlEventAttributes($imageContents, true);
-            file_put_contents($tmpFileName, $imageContents);
+            $filePointer = fopen("$tmpFileName", "w");
+            fwrite($filePointer, $imageContents);
+            fclose($filePointer);
         }
 
-        if ($saveimage) {
+        if ($saveimage == 'true') {
             /*
              * File functions like  filegroup(), fileowner(), filesize(), filetype(), fileperms() and few others,caches file information, we need to clear the cache so it will not return the cache value if we perform/call same function after updating the file
-            */
+             */
             clearstatcache();
         }
 
-- 
GitLab