0

I want to store images using PHP, so I am using the following code:

$encodedCard = isset($_POST["card"])? $_POST["card"] : null;
        $name = isset($_POST["fn"]) ? $_POST["fn"] : null;
        $card = base64_decode($encodedCard,true);
        $completePath = '/home/user/cards/' . $name . '.png';
        if (file_put_contents($completePath, $card)!== false) {
            echo "success";
        } else {
            $lastError = error_get_last();
            echo "Error writing to file: " . $lastError['message'];
        }

I have checked that the code is working properly until the if statement.

I am getting the following error:

Error writing to file: file_put_contents(/home/user/cards/image_name.png): Failed to open stream: Permission denied

Upon opening my Aapche2 error.log, I have the following:

PHP Warning: file_put_contents(/home/user/cards/image_name.png): Failed to open stream: Permission denied in /path/to/the/php/file.php on line 5

I tried changing the permissions for the directory, but nothing worked. The changes I tried are:

## did not work
chmod -R 755 /home/user/cards/
## did not work
chown -R www-data:www-data /home/user/cards/
## did not work
chmod -R 777 /home/user/cards/

If it helps, I am using Apache2 on an Ubuntu 22.04.03 LTS machine for the server.

Any help is appreciated; thanks in advance.

Edit: After Dorg's answer, I am adding some information related to my Apache 2 configuration files.

I have my PHP files saved as /var/www/domain_name/api/add/image.php.

My virtual host is as follows:

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName domain_name
    ServerAlias domain_name
    DocumentRoot /var/www/domain_name
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Although I don't have <Directory> in my virtual host, I have it in my apache.conf file as:

<Directory />
    Options FollowSymLinks
    AllowOverride None
    Require all denied
</Directory>

<Directory /usr/share>
    AllowOverride None
    Require all granted
</Directory>

<Directory /var/www/>
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

<Directory /home/user/cards/>
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

2 Answers 2

1

No need that the permission problem is based on the filesystem permissions (but its possible).

Apache has an internal permission system that you have to configure either in the Apache's (virtual-)host configuration or in an .htaccess file in the file structure.

Preferably in the Apache configuration of the (virtual-)host you state something like this:

<Directory /home/user/cards/>
    Require all granted
</Directory>

Or if such files are allowed, you can place the setting in the .htaccess file:

File: /home/user/cards/.htaccess

Require all granted

Perhaps you want to read more about .htaccess, i.e. at the Apache documentation for a better fine tuning of the rights at your site.


Update 1

Thank you for your update.

  1. .htaccess is not allowed by your configuration.
  2. The configuration should be OK to allow access to the files.
  3. If you change anything in your Apache configuration please remember you have to restart the Apache service to take them active:
    apachectl restart
    

I see your VirtualHost configuration

DocumentRoot /var/www/domain_name

and compare the assembled path:

$completePath = '/home/user/cards/' . $name . '.png';

The difference reveals the problem: The final destination is not within the DocuemntRoot.


You should create a symlink in /var/www/domain_name to /home/user/cards/

ln -s /home/user/cards  /var/www/domain_name/cards

and change the $completePath to use this symlink:

$completePath = '/var/www/domain_name/cards/' . $name . '.png'

The final URL for the web-client is within DocumentRoot /var/www/domain_name now:

http://domain_name/cards/image_name.png

Please note that the permissions set within the <Directory /home/user/cards/> will not be active for the path /var/www/domain_name/cards/.
But Apache will grant access because of the parent definition:

<Directory /var/www/>
    [...]
    Require all granted
</Directory>
2
  • I have added more information now can you tell me if I have to make any changes? Aug 30 at 18:24
  • I did as you said and what @GeneMoody-Action1 instructed, and now it is working fine. Thanks a lot to both of you. Aug 31 at 9:07
-1

See what user apache is runnign as

ps aux | grep httpd

I believe by default this will be "nobody" (But use what you find)

sudo chown nobody /path...

5
  • I am getting user 49898 0.0 0.0 17732 2432 pts/0 S+ 19:05 0:00 grep --color=auto httpd, What to do next? Aug 30 at 13:37
  • do you actually have a user named "user" the first column to the left of the PID should be the process's user name? But that column header is also user, making sure that this is the case, if you do it without the grep, that column actually shows "user"? check cat /etc/passwd | grep user Aug 30 at 14:19
  • no in place of "user," I have my username. Aug 30 at 17:45
  • ahh, ok, so if you make that user owner of those directories does it resolve, if not I would say that the other's suggestions may be correct this is not a file system limitation, it is an application restriction of some sort. Aug 30 at 22:34
  • I did as you said and as @Dordrg instructed, and now it is working fine. Thanks a lot to both of you. Aug 31 at 9:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .