Suite CRM 8.5.1 Cannot upload pictures or see them once uploaded

I have Suite Crm 8.5.1 running on a Vitrualmin Virtual Server php 8.1.24

I cannot seem to upload images. e.g. adding a product I select an image and all seems well. There is no upload button etc. I just select the file and then save the record.

Once I look at the record there is no image. If I edit the record then there is no image showing.

Can anyone assist with this.

Cheers
Tony

I have checked the permissions and run the command line fixes of rthe permissions. Not that I could see any issues but there are many many subdirectories so who knows.

This did not fix my issue. I can upload images into users but not products or change the site logo.

Going a little bit further there seems to be nothing in the actual database for the product record I created in respect of the product image. the field is defined as product_image varchar(255) and has a checkmark next to it in phpmyadmin when looking at the record.

If I look at a user record with a photo correctly uploaded I can see the file name in the field in the db record.

Has anyone else seen these issues on 8.5.1?

Cheers
Tony

When you upload a ‘product’ image the file is deposited into

/var/www/html/suitecrm/public/legacy/upload

The image name is not retained, it is transformed into an ID string (i.e)
86a1758b-0b7b-1605-258e-627693c029bb

I’ve just tried on my suite instance to replicate and it looks like product uploads are appending the file name after the string but thats ok.

That means my image should load from browser if i visit

https://domain.com/legacy/upload/43A61465-3011-65A5-27D3-7C0E0F26283F_Logo.png

Unfortunately that doesn’t work, i’m met with a 403 FORBIDDEN page trying it that way.
image

This then leads you to have a look at the .htaccess within /var/www/html/suitecrm/public/legacy and there’s a redirect 403 rule on the uploads directory.

Take a look in
/var/www/html/public/legacy/.htaccess and comment out the 403 redirect rule for uploads

That’ll do it :slight_smile:

See the product ‘image’ showing on page & can load the image directly from the browser url too.

This is great thank you. I will try this out. I have been looking at the whole redirection stuff as I had a suspicion it was something like this at the root of the problems but we could add pictures to users just fine.

When you are trying to deploy to a virtual server hosted on a virtualmin host. Things are not straightforward. For instance the redirect from the root of the crm (/crm) to /crm/public/ is problematic.

The only way I seemed to be able to get it to even install was to redirect all web requests to the actual directory like /home/domain/public_html/crm/public/

I am not sure why this has to be so complex.

Why not have all the redirection stuff in the root of the installation. in my case /crm

Maybe I am fundamentally misunderstanding something. But a lot of work to get a webapp working!

Cheers
Tony

Just did a fresh install. Made the changes you mentioned.

No diffference. Nothing gets uploaded to that directory.

A get a very quick error popup saying undefined and that’s it.

No image gets attached to the product.

However, I can upload a photo to a user record and a file gets put in the uploads directory with a filename of 1_photo

Any further suggestions please?

Cheers
Tony

@dhuntress which version of php and suitecrm as you using and on what kind oof hosting?

Just to rule out any permission issues I set the entire installation of suitecrm to 777 and logged in again to the same issue!

I can’t find any log information for the quick pop up [undefined] error. That is clearly something to do with the upload process.

Cheers
Tony

This is starting to look like a bug in 8.5.1!

I cannot see anything I can configure to solve this problem.

Can someone from the product team comment please.

Cheers
Spart

UPDATE*

I have installed 8.5.1 on another host and this is exactly the same. Cannot change the site logo or upload images to products. But can upload an image to users.

Answers on a postcard please.

Cheers
Tony

I’ve never had to use 777 for anything in suite.

Directories should be 2755 and files should be 0644

The user that’s running the ‘apache’ service should own said files and directories.

In config.php in the public/legacy folder there’s a default permissions section

Have you put the default user and group in there? (www-data) usually.

Are you setting these permissions before or after installing?

If you upload the file, correct permissions after is it still inaccessible?

Uploads not hitting the upload directory also suggests permission issue as it means suite can’t put it there

Undefined labelling is also an indicator that file permissions aren’t set right as suite can’t read from the files that labels them

I’ve seen all these behaviours you’re experiencing and referring here Downloading & Installing :: SuiteCRM Documentation may assist

Im on apache2/8.5.1 suite, 8.2php production

I agree is suggests that there is some kind of permissions problem but I cannot find it!

Are you talking about these parameters in the config file?

 array (
    'dir_mode' => 1528,
    'file_mode' => 493,
    'user' => '',
    'group' => '',
  ),

This is what is currently in the file OOTB.

In terms of setting permissions, I ran these 2 commands following installation as per the documentation.

find . -type d -not -perm 2755 -exec chmod 2755 {} \;
find . -type f -not -perm 0644 -exec chmod 0644 {} \;

As I said I also temporarily set the entire install to 777 and that made no difference. Also the same on another OOTB install on another host.

Driving me nuts…

Cheers
Tony

Give up Tony like most of us have. The maintainers refuse to allow debug into the code that sets permissions. We could fix this quickly and stop years of frustration with more years to come obviously.

Permissions and ownership data is known by Suitecrm at install time as evidenced by the CRON ownership to apply in the crontab settings that shows in the admin page. The request for @pgr’s debug PR has been in github for years and despite repeated requests from the community to solve these simple issues, the maintainers continue to focus on adding new code. They are killing any chance of widespread adoption of SuiteCRM. I would go further and question their motivation for purposely ignoring these continued and persistent adoption-killing fixes.

It is like they are on a different journey. Changing leadership of the roadmap team is likely the only solution at this time or move to another CRM solution that cares. Can we raise enough for PGR to fork the version to add debug and move forward that way? Permissions and install would likely get cleaned up at the v8.5 stage and then continue to clean up everything that doesn’t work. Stop adding adding lipstick to this pig. Let the maintainers wander off with their strategy which just isn’t working after 10+ versions of v8 now under the belt.

This stuff above is years and years unaddressed. Maintainers let @PGR take the brunt of explaining the lack of fixes for a few years now. It seems almost intentional at this stage. Shame on them. how can we get this ship righted and restore confidence to v8? From the download and comments, it is DOA it seems. Hard to believe anyone thinks that is a successful release. Pretty soon I predict someone will write DNR on V8’s forehead.

Save your health and days of frustration. Stay away from v8 SuiteCRM until the permissions are addressed and auto-install works with proper configuration of php version, owner/group/permission properties and recognition of the variables for each underlying linux distro. That is not rocket science. Hiring a server admin won’t help a casual user. You will blow your budget as you plow through the last years of the same problems we’ve all been facing. It’s crazy these things remain unresolved. No wonder funding and support money has dried up.

@pjdm Wow!

We have dabbled with SuiteCRM for years and each time had to give up. We thought this time with the promise of V8 it looked like it really could be a winner for us to deploy. But, apparently not. I love the idea of OSS but let’s have the very basic things waorking OOTB I shouldn’t need a degree in computer science to get it installed and working.

The documentation states this and that. You do those things and of course, they don’t work. I am sure that the issues I am having are related to PHP issues or permissions. The bug I raised the other days has at least been acknowledged and seemingly prioritised. But who knows? Various people have responded saying it works OOTB for them. I have no idea how.

I have met or exceeded all compatibility matrix requirements. Installed from scratch multiple times with multiple approaches. Run endless ‘fix permissions’ scripts etc. It installs looks ok. But functionally can’t get past first base. Can’t change the site logo, can’t upload product images. I am sure there would be more if we did our head in further on testing. But without this basic functionality pointless. We have other web apps running perfectly on the same hosting platforms.

I have no idea how to make this better. Forking the product is the way of history on many of these OSS applications due to the frustrations we are discussing and many more.

I am sure there is a dedicated and passionate core somewhere that are as frustrated as we clients are. Are they motivated still? I hope so, and that it seems is all that we can be, hopeful that the kind of posts I and many others have put up are taken seriously, they represent a serious barrier to adoption and widespread usage.

We always contribute to OSS software that we use that is functional. If I had to charge a client for the amount of hours I have spent on just getting it installed they would be horrified and then to not have basic functionality well that would be a death blow to our relationship.

The roadmap is ridiculously bereft of any detail.

Also what happened to SuiteAssured. The issues we are facing are core product issues and these are still around!

After scouring the market looking for a functional and reasonably modern self hosted CRM system there really is not a lot out there in any better shape!

What kind of shape is salesagility in? I found this page which this surely cannot be right 2K in funding wouldn’t last very long! Advert running to hire a developer for ~30K PA

The company seems to be solvent but very small on a global stage showing 23 employees in April 22. Mr Soper seems to be materially the owner who is around 68 years old. Maybe I am looking at the wrong salesagility but the addresses seem to match up.

Is there a dev con for SuiteCRM?

Cheers
Tony

maybe there is a glimmer of hope, but I have no idea how to fix it.

In the studio if I examine the data types associated with the product image field it is defined as a text field.

In users where I can upload a photo of a user the data type is defined as image.

So maybe it is a datatype field definition bug. Changing the vardef for the LBL_PRODUCT_IMAGE to image and adding the same properties as the user image field made no difference though.

Damn, I really thought I was onto something there for a minute!

When searching the entire installation for occurances of both LBL_PRODUCCT_IMAGE and product_image this is what I find.

# find . -type f -exec grep -l "LBL_PRODUCT_IMAGE" {} \;
./cache/prod/pools/OmsCTTxpXV/9/S/mU5fLf8dl6J5gAPo5ynA
./cache/prod/pools/OmsCTTxpXV/S/J/cxjyLThttm0qH2gD6nBA
./public/legacy/cache/themes/suite8/modules/AOS_Products/EditView.tpl
./public/legacy/cache/themes/suite8/modules/AOS_Products/DetailView.tpl
./public/legacy/cache/jsLanguage/AOS_Products/en_us.js
./public/legacy/cache/modules/AOS_Products/language/en_us.lang.php
./public/legacy/cache/modules/AOS_Products/AOS_Productsvardefs.php
./public/legacy/cache/smarty/templates_c/a141623ca6b6ce702279074f1b607e7a6c681cd4_0.file.DetailView.tpl.php
./public/legacy/cache/smarty/templates_c/281e0649af9e4d432e317a4af6be8054b77312ab_0.file.EditView.tpl.php
./public/legacy/modules/AOS_Products/language/en_us.lang.php
./public/legacy/modules/AOS_Products/vardefs.php
./public/legacy/modules/AOS_Products/metadata/detailviewdefs.php
./public/legacy/custom/modules/AOS_Products/Ext/Language/en_us.lang.ext.php
./public/legacy/custom/Extension/modules/AOS_Products/Ext/Language/_override_en_us.lang.php

# find . -type f -exec grep -l "product_image" {} \;
./cache/prod/pools/OmsCTTxpXV/9/S/mU5fLf8dl6J5gAPo5ynA
./public/legacy/cache/themes/suite8/modules/AOS_Products/EditView.tpl
./public/legacy/cache/themes/suite8/modules/AOS_Products/DetailView.tpl
./public/legacy/cache/modules/AOS_Products/AOS_Productsvardefs.php
./public/legacy/cache/smarty/templates_c/a141623ca6b6ce702279074f1b607e7a6c681cd4_0.file.DetailView.tpl.php
./public/legacy/cache/smarty/templates_c/281e0649af9e4d432e317a4af6be8054b77312ab_0.file.EditView.tpl.php
./public/legacy/modules/AOS_Products/vardefs.php
./public/legacy/modules/AOS_Products/metadata/editviewdefs.php
./public/legacy/modules/AOS_Products/metadata/quickcreatedefs.php
./public/legacy/modules/AOS_Products/metadata/detailviewdefs.php
./public/legacy/modules/AOS_Products/AOS_Products.php
./public/legacy/modules/AOS_Products/views/view.edit.php
./public/legacy/modules/AOS_PDF_Templates/templateParser.php
./public/legacy/custom/modules/AOS_Products/Ext/Vardefs/vardefs.ext.php
./public/legacy/custom/Extension/modules/AOS_Products/Ext/Vardefs/_override_sugarfield_product_image.php

Multiple vardef files does not fill me with confidence!

My instincts tell me the issue is in here somewhere. This seems to be the code responsible for uploading the product image in public/legacy/modules/AOS_Products/AOS_Products.php.

    public function save($check_notify = false)
    {
        global $sugar_config, $mod_strings;

        if (isset($_POST['deleteAttachment']) && $_POST['deleteAttachment'] == '1') {
            $this->product_image = '';
        }

        require_once('include/upload_file.php');
        $GLOBALS['log']->debug('UPLOADING PRODUCT IMAGE');

        if(!empty($_FILES['uploadimage']['name'])){
            $imageFileName = $_FILES['uploadimage']['name'] ?? '';
            if (!has_valid_image_extension('AOS_Products Uploaded image file: ' . $imageFileName , $imageFileName)) {
                LoggerManager::getLogger()->fatal("AOS_Products save - Invalid image file ext : '$imageFileName'.");
                throw new RuntimeException('Invalid request');
            }
        }

        if (!empty($_FILES['uploadimage']['tmp_name']) && verify_uploaded_image($_FILES['uploadimage']['tmp_name'])) {
            if ($_FILES['uploadimage']['size'] > $sugar_config['upload_maxsize']) {
                die($mod_strings['LBL_IMAGE_UPLOAD_FAIL'] . $sugar_config['upload_maxsize']);
            }
            $prefix_image = $this->getGUID() . '_';
            $this->product_image = $sugar_config['site_url'] . '/' . $sugar_config['upload_dir'] . $prefix_image . $_FILES['uploadimage']['name'];
            move_uploaded_file($_FILES['uploadimage']['tmp_name'], $sugar_config['upload_dir'] . $prefix_image . $_FILES['uploadimage']['name']);
        }

        require_once('modules/AOS_Products_Quotes/AOS_Utils.php');

        perform_aos_save($this);

        return parent::save($check_notify);
    }

Anyone?

Cheers
Tony


Working through this and adding some error handling seems to have resolved the issue. With the code below in public/legacy/modules/AOS_Products/AOS_Products.php and the vardef changed to image with the same properties as the user image. width, height etc. Ran a repair and rebuild from the admin section.

I can now add images to products! Eureka. Obviously this is a cludge and maybe I have got lucky. I cannot replace the site image though so maybe more of the same in that code. One step at a time.

No additional php errors show up in my Apache or php logs.

Here is my replacement code. I provide no guarantees or warranties and these changes will no doubt be overwritten in any upgrade!

public function save($check_notify = false)
{
    global $sugar_config, $mod_strings;

    if (isset($_POST['deleteAttachment']) && $_POST['deleteAttachment'] == '1') {
        $this->product_image = '';
    }

    require_once('include/upload_file.php');
    $GLOBALS['log']->debug('UPLOADING PRODUCT IMAGE');

    if (!empty($_FILES['uploadimage']['name'])) {
        $imageFileName = $_FILES['uploadimage']['name'] ?? '';
        if (!has_valid_image_extension('AOS_Products Uploaded image file: ' . $imageFileName, $imageFileName)) {
            LoggerManager::getLogger()->fatal("AOS_Products save - Invalid image file ext : '$imageFileName'.");
            throw new RuntimeException('Invalid request');
        }
    }

    if (!empty($_FILES['uploadimage']['tmp_name'])) {
        $uploadErrors = [
            UPLOAD_ERR_OK => 'There is no error, the file uploaded with success.',
            UPLOAD_ERR_INI_SIZE => 'The uploaded file exceeds the upload_max_filesize directive in php.ini.',
            UPLOAD_ERR_FORM_SIZE => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.',
            UPLOAD_ERR_PARTIAL => 'The uploaded file was only partially uploaded.',
            UPLOAD_ERR_NO_FILE => 'No file was uploaded.',
            UPLOAD_ERR_NO_TMP_DIR => 'Missing a temporary folder. Introduced in PHP 5.0.3.',
            UPLOAD_ERR_CANT_WRITE => 'Failed to write file to disk. Introduced in PHP 5.1.0.',
            UPLOAD_ERR_EXTENSION => 'A PHP extension stopped the file upload.',
        ];

        $errorCode = $_FILES['uploadimage']['error'];

        if ($errorCode !== UPLOAD_ERR_OK) {
            die("Upload failed with error: $uploadErrors[$errorCode]");
        }

        if ($_FILES['uploadimage']['size'] > $sugar_config['upload_maxsize']) {
            die($mod_strings['LBL_IMAGE_UPLOAD_FAIL'] . $sugar_config['upload_maxsize']);
        }

        $prefix_image = $this->getGUID() . '_';
        $uploadDir = rtrim($sugar_config['upload_dir'], '/') . '/';
        $uploadedFilePath = $uploadDir . $prefix_image . $_FILES['uploadimage']['name'];
        
        if (move_uploaded_file($_FILES['uploadimage']['tmp_name'], $uploadedFilePath)) {
            $this->product_image = $sugar_config['site_url'] . '/' . $uploadDir . $prefix_image . $_FILES['uploadimage']['name'];
        } else {
            die("Failed to move uploaded file to destination.");
        }
    }

    require_once('modules/AOS_Products_Quotes/AOS_Utils.php');

    perform_aos_save($this);

    return parent::save($check_notify);
}

Tested with mulitple user accounts and works every time to both initially upload an image and also change it.

Over to the people that really understand this.

Cheers
Tony

2 Likes