diff --git a/include/Webservices/Utils.php b/include/Webservices/Utils.php index 89cbf49a70417b4ccc1ca90fb7bee6b5135b9488..720e2c5f5af0780ba80a87c6bc5a88299d55d543 100644 --- a/include/Webservices/Utils.php +++ b/include/Webservices/Utils.php @@ -476,29 +476,21 @@ function vtws_getModuleHandlerFromId($id,$user){ } function vtws_CreateCompanyLogoFile($fieldname) { - global $root_directory; - $uploaddir = $root_directory ."/test/logo/"; - $allowedFileTypes = array("jpeg", "png", "jpg", "pjpeg" ,"x-png"); - $binFile = $_FILES[$fieldname]['name']; - $fileType = $_FILES[$fieldname]['type']; - $fileSize = $_FILES[$fieldname]['size']; - $fileTypeArray = explode("/",$fileType); - $fileTypeValue = strtolower($fileTypeArray[1]); - if($fileTypeValue == '') { - $fileTypeValue = substr($binFile,strrpos($binFile, '.')+1); - } - if($fileSize != 0) { - if(in_array($fileTypeValue, $allowedFileTypes)) { - move_uploaded_file($_FILES[$fieldname]["tmp_name"], - $uploaddir.$_FILES[$fieldname]["name"]); - copy($uploaddir.$_FILES[$fieldname]["name"], $uploaddir.'application.ico'); - return $binFile; - } - throw new WebServiceException(WebServiceErrorCode::$INVALIDTOKEN, - "$fieldname wrong file type given for upload"); - } - throw new WebServiceException(WebServiceErrorCode::$INVALIDTOKEN, - "$fieldname file upload failed"); + $fileSize = $_FILES[$fieldname]['size']; + if($fileSize != 0) { + global $root_directory; + $uploaddir = $root_directory ."/test/logo/"; + $binFile = $_FILES[$fieldname]['name']; + $saveLogo = validateImageFile($_FILES[$fieldname]); + if($saveLogo == 'true') { + move_uploaded_file($_FILES[$fieldname]["tmp_name"], $uploaddir.$binFile); + copy($uploaddir.$binFile, $uploaddir.'application.ico'); + return $binFile; + } + throw new WebServiceException(WebServiceErrorCode::$FAILED_TO_UPDATE, + "$fieldname wrong file type given for upload"); + } + throw new WebServiceException(WebServiceErrorCode::$FAILED_TO_UPDATE, "$fieldname file upload failed"); } function vtws_getActorEntityName ($name, $idList) { diff --git a/include/Webservices/WebServiceErrorCode.php b/include/Webservices/WebServiceErrorCode.php index 7b7a06d2327c04a08465a6019360ddeb60581a56..128583de9f289ceecc95973582fe6e3760f56639 100644 --- a/include/Webservices/WebServiceErrorCode.php +++ b/include/Webservices/WebServiceErrorCode.php @@ -43,6 +43,7 @@ public static $FAILED_TO_CREATE = "FAILED_TO_CREATE"; public static $INACTIVECURRENCY = "CURRENCY_INACTIVE"; public static $PASSWORDNOTSTRONG = "PASSWORD_NOT_STRONG"; + public static $FAILED_TO_UPDATE = "FAILED_TO_UPDATE"; } ?> diff --git a/vtlib/Vtiger/Functions.php b/vtlib/Vtiger/Functions.php index c79d259b651dbb9367164b90242ee6a95883da74..ab4d4a3286370e99d13ff46dda45cfd6759de1c6 100644 --- a/vtlib/Vtiger/Functions.php +++ b/vtlib/Vtiger/Functions.php @@ -15,6 +15,7 @@ class Vtiger_Functions { const LINK_TO_ANCHOR_TEXT_SYMBOL = '#'; + static $supportedImageFormats = array('jpeg', 'png', 'jpg', 'pjpeg', 'x-png', 'gif', 'bmp', 'vnd.adobe.photoshop', 'tiff', 'svg+xml', 'x-eps', 'x-dwg', 'vnd.dwg', 'webp', 'x-ms-bmp', 'ico', 'vnd.microsoft.icon', 'x-icon'); static function userIsAdministrator($user) { return (isset($user->is_admin) && $user->is_admin == 'on'); @@ -622,76 +623,84 @@ class Vtiger_Functions { return $filepath; } - static function validateImageMetadata($data, $short=true) { - if (is_array($data)) { - foreach ($data as $key => $value) { - $ok = self::validateImageMetadata($value); - if (!$ok) return false; - } - } else { - if (stripos($data, $short ? "<?" : "<?php") !== false) { // suspicious dynamic content - return false; - } - } - return true; - } + static function validateImageMetadata($data, $short = true) { + if (is_array($data)) { + foreach ($data as $key => $value) { + $ok = self::validateImageMetadata($value, $short); + if (!$ok) + return false; + } + } else { + if (stripos($data, $short ? "<?" : "<?php") !== false) { // suspicious dynamic content + return false; + } + } + return true; + } - static function validateImage($file_details) { - global $app_strings, $log; - $allowedImageFormats = array('jpeg', 'png', 'jpg', 'pjpeg', 'x-png', 'gif', 'bmp'); - - $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)) { - $log->debug('file type not matched allowed formats'); - $saveimage = 'false'; - } - - //mime type check - $mimeType = self::mime_content_type($file_details['tmp_name']); - $mimeTypeContents = explode('/', $mimeType); - if (!$file_details['size'] || strtolower($mimeTypeContents[0]) !== 'image' || !in_array($mimeTypeContents[1], $mimeTypesList)) { - $log->debug('Failed because of size or image not supported types'); - $saveimage = 'false'; - } - - //metadata check - $shortTag = strtolower(ini_get('short_open_tag')); - $shortTagSupported = ($shortTag == '1' || $shortTag == 'on') ? TRUE : FALSE; - if ($saveimage == 'true') { - $tmpFileName = $file_details['tmp_name']; - 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)) { - $log->debug('Image metadata validation failed'); - $saveimage = 'false'; - } - //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); - } - } - } + static function validateImage($file_details) { + global $app_strings; + $allowedImageFormats = Vtiger_Functions::$supportedImageFormats; - // Check for php code injection - if ($saveimage == 'true') { - $imageContents = file_get_contents($file_details['tmp_name']); - if (stripos($imageContents, $shortTagSupported ? "<?" : "<?php") !== false) { // suspicious dynamic content. - $log->debug('Php injection suspected'); - $saveimage = 'false'; - } - } - return $saveimage; - } + // Determine mime-types based on file-content for generic type (Outlook add-on). + if ($file_details['type'] == 'application/octet-stream' && function_exists('mime_content_type')) { + $file_details['type'] = mime_content_type($file_details['tmp_name']); + } + + $filetype = strtolower(pathinfo($file_details['name'], PATHINFO_EXTENSION)); + $saveimage = in_array($filetype, $allowedImageFormats); + + if ($saveimage) { + $mimeType = mime_content_type($file_details['tmp_name']); + list($mimeTypeContents, $mimeSubtype) = explode('/', $mimeType); + if (strtolower($mimeTypeContents) !== 'image' || !in_array($mimeSubtype, $allowedImageFormats)) { + $saveimage = false; + } + } + + $shortTagSupported = ini_get('short_open_tag') ? true : false; + + if ($saveimage) { + $tmpFileName = $file_details['tmp_name']; + + if (in_array($file_details['type'], ['image/jpeg', 'image/tiff'])) { + $exifdata = @exif_read_data($tmpFileName); + if ($exifdata && !self::validateImageMetadata($exifdata, $shortTagSupported)) { + $saveimage = false; + } + + if ($saveimage && $file_details['type'] == 'image/jpeg' && extension_loaded('gd') && function_exists('gd_info')) { + $img = imagecreatefromjpeg($tmpFileName); + imagejpeg($img, $tmpFileName); + } + } + } + + if ($saveimage) { + $imageContents = file_get_contents($tmpFileName); + $shortTag = $shortTagSupported ? "<?" : "<?php"; + if (stripos($imageContents, $shortTag) !== false) { + $saveimage = false; + } + } + + if ($saveimage && in_array($filetype, ['svg+xml', $mimeSubtype])) { + // Remove malicious HTML attributes with values from the contents. + $imageContents = purifyHtmlEventAttributes($imageContents, true); + file_put_contents($tmpFileName, $imageContents); + } + + if ($saveimage) { + /* + * 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(); + } + + return $saveimage; + } - static function getMergedDescription($description, $id, $parent_type, $removeTags = false) { + static function getMergedDescription($description, $id, $parent_type, $removeTags = false) { global $current_user; $token_data_pair = explode('$', $description); $emailTemplate = new EmailTemplate($parent_type, $description, $id, $current_user);