/** * Verify uploaded image * Verifies that image has proper extension, MIME type and doesn't contain hostile contant * @param string $path Image path * @param bool $jpeg_only Accept only JPEGs? */ function verify_uploaded_image($path, $jpeg_only = false) { $supportedExtensions = array('jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg'); if (!$jpeg_only) { $supportedExtensions['png'] = 'image/png'; } if (!file_exists($path) || !is_file($path)) { return false; } $img_size = getimagesize($path); $filetype = $img_size['mime']; $ext = end(explode(".", $path)); if (substr_count('..', $path) > 0 || $ext === $path || !in_array(strtolower($ext), array_keys($supportedExtensions)) || !in_array($filetype, array_values($supportedExtensions))) { return false; } return verify_image_file($path, $jpeg_only); }
public function save(&$bean, $params, $field, $properties, $prefix = '') { require_once 'include/upload_file.php'; $upload_file = new UploadFile($field); //remove file if (isset($_REQUEST['remove_imagefile_' . $field]) && $_REQUEST['remove_imagefile_' . $field] == 1) { $upload_file->unlink_file($bean->{$field}); $bean->{$field} = ""; } //uploadfile if (isset($_FILES[$field])) { //confirm only image file type can be uploaded if (verify_image_file($_FILES[$field]['tmp_name'])) { if ($upload_file->confirm_upload()) { // for saveTempImage API if (isset($params['temp']) && $params['temp'] === true) { // Create the new field value $bean->{$field} = create_guid(); // Move to temporary folder if (!$upload_file->final_move($bean->{$field}, true)) { // If this was a fail, reset the bean field to original $this->error = $upload_file->getErrorMessage(); } } else { // Capture the old value in case of error $oldvalue = $bean->{$field}; // Create the new field value $bean->{$field} = create_guid(); // Add checking for actual file move for reporting to consumers if (!$upload_file->final_move($bean->{$field})) { // If this was a fail, reset the bean field to original $bean->{$field} = $oldvalue; $this->error = $upload_file->getErrorMessage(); } } } else { // Added error reporting $this->error = $upload_file->getErrorMessage(); } } else { $imgInfo = getimagesize($_FILES[$field]['tmp_name']); // if file is image then this image is no longer supported. if (false !== $imgInfo) { $ext = end(explode('.', $_FILES[$field]['name'])); $this->error = string_format($GLOBALS['app_strings']['LBL_UPLOAD_IMAGE_FILE_NOT_SUPPORTED'], array($ext)); } else { $this->error = $GLOBALS['app_strings']["LBL_UPLOAD_IMAGE_FILE_INVALID"]; } } } //Check if we have the duplicate value set and use it if $bean->$field is empty if (empty($bean->{$field}) && !empty($_REQUEST[$field . '_duplicate'])) { $bean->{$field} = $_REQUEST[$field . '_duplicate']; } // case when we should copy one file to another using merge-duplicate view // $params[$field . '_duplicateBeanId'] contains id of bean from // which we should copy file. if (!empty($params[$field]) && !empty($params[$field . '_duplicateBeanId'])) { $bean->{$field} = create_guid(); $upload_file->duplicate_file($params[$field], $bean->{$field}); } }
/** * Moves temporary files associated with the bean from the temporary folder * to the upload folder. * * @param array $args The request arguments. * @param SugarBean $bean The bean associated with the file. * @throws SugarApiExceptionInvalidParameter If the file mime types differ * from $imageFileMimeTypes. */ protected function moveTemporaryFiles($args, SugarBean $bean) { require_once 'include/upload_file.php'; require_once 'include/SugarFields/SugarFieldHandler.php'; $fileFields = $bean->getFieldDefinitions('type', array('file', 'image')); $sfh = new SugarFieldHandler(); // FIXME This path should be changed with BR-1955. $basepath = UploadStream::path('upload://tmp/'); $configDir = SugarConfig::getInstance()->get('upload_dir', 'upload'); foreach ($fileFields as $fieldName => $def) { if (empty($args[$fieldName . '_guid'])) { continue; } $this->verifyFieldAccess($bean, $fieldName); $filepath = $basepath . $args[$fieldName . '_guid']; if (!is_file($filepath)) { continue; } if ($def['type'] === 'image') { $filename = $args[$fieldName . '_guid']; $bean->{$fieldName} = $filename; } else { // FIXME Image verification and mime type updating // should not be duplicated from SugarFieldFile. // SC-3338 is tracking this. require_once 'include/utils/file_utils.php'; $filename = $bean->id; $mimeType = get_file_mime_type($filepath, 'application/octet-stream'); $sf = $sfh->getSugarField($def['type']); $extension = pathinfo($fieldName, PATHINFO_EXTENSION); if (in_array($mimeType, $sf::$imageFileMimeTypes) && !verify_image_file($filepath)) { throw new SugarApiExceptionInvalidParameter(string_format($GLOBALS['app_strings']['LBL_UPLOAD_IMAGE_FILE_NOT_SUPPORTED'], array($extension))); } $bean->file_mime_type = $mimeType; $bean->file_ext = $extension; } $destination = rtrim($configDir, '/\\') . '/' . $filename; // FIXME BR-1956 will address having multiple files // associated with a record. rename($filepath, $destination); } }
public function save($bean, $params, $field, $vardef, $prefix = '') { $fakeDisplayParams = array(); $this->fillInOptions($vardef, $fakeDisplayParams); require_once 'include/upload_file.php'; $upload_file = new UploadFile($prefix . $field . '_file'); //remove file if (isset($_REQUEST['remove_file_' . $field]) && $params['remove_file_' . $field] == 1) { $upload_file->unlink_file($bean->{$field}); $bean->{$field} = ""; } $move = false; // In case of failure midway, we need to reset the values of the bean $originalvals = array('value' => $bean->{$field}); // Bug 57400 - Some beans with a filename field type do NOT have file_mime_type // or file_ext. In the case of Documents, for example, this happens to be // the case, since the DocumentRevisions bean is where these fields are found. if (isset($bean->file_mime_type)) { $originalvals['mime'] = $bean->file_mime_type; } if (isset($bean->file_ext)) { $originalvals['ext'] = $bean->file_ext; } if (isset($_FILES[$prefix . $field . '_file']) && $upload_file->confirm_upload()) { // in order to avoid any discrepancies of MIME type with the download code, // call the same MIME function instead of using the uploaded file's mime type property. $mimeType = get_file_mime_type($upload_file->get_temp_file_location(), 'application/octet-stream'); //verify the image if (in_array($mimeType, self::$imageFileMimeTypes) && !verify_image_file($upload_file->get_temp_file_location())) { $this->error = string_format($GLOBALS['app_strings']['LBL_UPLOAD_IMAGE_FILE_NOT_SUPPORTED'], array($upload_file->file_ext)); return; } $bean->{$field} = $upload_file->get_stored_file_name(); $bean->file_mime_type = $upload_file->mime_type; $bean->file_ext = $upload_file->file_ext; $move = true; } else { $this->error = $upload_file->getErrorMessage(); } if (!empty($params['isDuplicate']) && $params['isDuplicate'] == 'true') { // This way of detecting duplicates is used in Notes $old_id = $params['relate_id']; } if (!empty($params['duplicateSave']) && !empty($params['duplicateId'])) { // It's a duplicate $old_id = $params['duplicateId']; } // case when we should copy one file to another using merge-duplicate view // $params[$field . '_duplicateBeanId'] contains id of bean from // which we should copy file. if (!empty($params[$field . '_duplicateBeanId'])) { $duplicateModuleId = $params[$field . '_duplicateBeanId']; } // Backwards compatibility for fields that still use customCode to handle the file uploads if (!$move && empty($old_id) && isset($_FILES['uploadfile'])) { $upload_file = new UploadFile('uploadfile'); if ($upload_file->confirm_upload()) { $bean->{$field} = $upload_file->get_stored_file_name(); $bean->file_mime_type = $upload_file->mime_type; $bean->file_ext = $upload_file->file_ext; $move = true; } else { $this->error = $upload_file->getErrorMessage(); } } elseif (!$move && !empty($old_id) && isset($_REQUEST['uploadfile']) && !isset($_REQUEST[$prefix . $field . '_file'])) { // I think we are duplicating a backwards compatibility module. $upload_file = new UploadFile('uploadfile'); } if (empty($bean->id)) { $bean->id = create_guid(); $bean->new_with_id = true; } if ($move) { $temp = !empty($params['temp']); // Added checking of final move to capture errors that might occur if ($upload_file->final_move($bean->id, $temp)) { if (!$temp) { // This fixes an undefined index warning being thrown $docType = isset($vardef['docType']) && isset($params[$prefix . $vardef['docType']]) ? $params[$prefix . $vardef['docType']] : null; $upload_file->upload_doc($bean, $bean->id, $docType, $bean->{$field}, $upload_file->mime_type); } } else { // Reset the bean back to original, but only if we had set them. $bean->{$field} = $originalvals['value']; // See comments for these properties above in regards to Bug 57400 if (isset($originalvals['mime'])) { $bean->file_mime_type = $originalvals['mime']; } if (isset($originalvals['ext'])) { $bean->file_ext = $originalvals['ext']; } // Report the error $this->error = $upload_file->getErrorMessage(); } } elseif (!empty($old_id)) { // It's a duplicate, I think if (empty($vardef['docUrl']) || empty($params[$prefix . $vardef['docUrl']])) { $upload_file->duplicate_file($old_id, $bean->id, $bean->{$field}); } else { $docType = $vardef['docType']; $bean->{$docType} = $params[$prefix . $field . '_old_doctype']; } } elseif (!empty($params[$prefix . $field . '_remoteName'])) { // We aren't moving, we might need to do some remote linking $displayParams = array(); $this->fillInOptions($vardef, $displayParams); if (isset($params[$prefix . $vardef['docId']]) && !empty($params[$prefix . $vardef['docId']]) && isset($params[$prefix . $vardef['docType']]) && !empty($params[$prefix . $vardef['docType']])) { $bean->{$field} = $params[$prefix . $field . '_remoteName']; require_once 'include/utils/file_utils.php'; $extension = get_file_extension($bean->{$field}); if (!empty($extension)) { $bean->file_ext = $extension; $bean->file_mime_type = get_mime_content_type_from_filename($bean->{$field}); } } } elseif (!empty($duplicateModuleId)) { $upload_file->duplicate_file($duplicateModuleId, $bean->id, $bean->{$field}); $bean->{$field} = $params[$field]; require_once 'include/utils/file_utils.php'; $extension = get_file_extension($bean->{$field}); if (!empty($extension)) { $bean->file_ext = $extension; $bean->file_mime_type = get_mime_content_type_from_filename($bean->{$field}); } } if ($vardef['allowEapm'] == true && empty($bean->{$field})) { $GLOBALS['log']->info("The {$field} is empty, clearing out the lot"); // Looks like we are emptying this out $clearFields = array('docId', 'docType', 'docUrl', 'docDirectUrl'); foreach ($clearFields as $clearMe) { if (!isset($vardef[$clearMe])) { continue; } $clearField = $vardef[$clearMe]; $bean->{$clearField} = ''; } } }