2

I have a zip file into a directory like this:

drwxr-xr-x 2 salome  salome  4096 Dec 16 17:41 staff.zip

When I unzip the file with ZipArchive class, all the upzipped files are owner by nobody user. Is there a way to avoid this owner change?

  1. I am able to use ftp if it is required (only as salome user).
  2. This script eventually will be shared at multiple hosts, so the idea is keep it as generic as possible.
Mogsdad
  • 44,709
  • 21
  • 151
  • 275
manix
  • 14,537
  • 11
  • 70
  • 107

2 Answers2

2

You might consider extending the zipArchive class and override the extractTo method to also perform a chown() on the files in the directory.

Based on the use case you discussed in the comments, you also might want to consider the use of the Phar archive format. php.net/manual/en/intro.phar.php

Phar's would allow your module submitters to submit a file file of executable PHP code that you would not need to extract at all.

Mike Brant
  • 70,514
  • 10
  • 99
  • 103
  • hmm, this is to deep at first impression. But I will try it. – manix Dec 18 '12 at 00:50
  • Mike, thank you for the answer, but I have no idea how to do that because I have no enought experience. But relax, I am trying it and then I will update you ASAP :) – manix Dec 18 '12 at 01:02
  • @manix I am glad you are willing to try to implement it on your own. If you run into any problems, post back here and I would be happy to give some guidance. – Mike Brant Dec 18 '12 at 01:05
  • @Mike_Brant, I posted an answer that could do something similar what I was expecting, it is not completed and I don't know if it is a good hardcode, but I think thatit could be a good start. Was an odyssey to get it works haha – manix Dec 18 '12 at 16:56
  • It seems very odd to be using FTP to move unzipped files on the same machine you are already working on. It think the issue you were running into was really one of directory and file permissions. Your FTP approach may be a workaround for that, by my guess is that it would be a very fragile solution if tried to be used across a number of different hosts. I guess I would need to understand you use case here to get a feel for what you are actually trying to do and whether you are trying to execute this from command line or via web server. – Mike Brant Dec 18 '12 at 18:35
  • I'm building a php application where the users can upload plugins (zip files). Each plugin can hold php files that must be executables when the plugin is activated. For that reason, when a user upload a plugin, it should have the correct owner in order to unzip its files and execute them with the correct owner. So, I though that `chowner()` or request the FTP details could help me to resolve this. Now, I am sure that is not possible to use `chmod()` and `chowner()` because this application could be installed in other hosts that have too much restrictions. – manix Dec 18 '12 at 20:13
  • @manix If that is your use case, you might want to consider using phar archives. that is pretty much the modern standard for distributing single-file PHP applications. Check out this link... http://php.net/manual/en/intro.phar.php The good thing about phar's is that that are executable from their single file without the need to extract the files in the archive. – Mike Brant Dec 18 '12 at 21:53
  • Mike, looks like a very good alternative! I will test it to see how it works. Thank so much to guide to the right direction! I really apreciate your help. (PS: I think you could update your answer adding your last comment about "phar") – manix Dec 20 '12 at 19:34
0

Ok, I have resolved the problem of nobody user. I will try to explain all my workaround.

@Mike Brant's answer

Mike suggest to me make use of chown() function overriding extractTo() method. Well, before to willing with it, I tested the chown() function standalone constantly it printed the error:

failed to create stream: Permission denied in ...

Looks like chown will not work for the major shared hostings

FTP functions

So, keeping going I though that FTP functions I made a script that works fine, at least for now xD. This is a resume what the script does for one zipped file:

  1. Create a temp file using tmpfile().
  2. Using ftp_fput() to put the temp file in the current directory with the zipped file.
  3. Give write permissions using ftp_site and CHMOD 0777.
  4. Read the zipped file content with $content = $zip->getFromName('zipped-file.txt');.
  5. Put the content to the new file using fputs($fp, $content);.
  6. Close connections

The code below illustrates the complete process

$zip = new ZipArchive;
$ftp_path_to_unzip = '/public_html/ejemplos/php/ftp/upload/';
$local_path_to_unzip = '/home/user/public_html/ejemplos/php/ftp/upload/';

if ($zip->open('test.zip') == TRUE) {
    
    //connect to the ftp server
    $conn_id = ftp_connect('ftp.example.com');
    $login_result = ftp_login($conn_id, 'user', 'password');    
    
    //if the connection is ok, then...
    if ($login_result) {
        
        //iterate each zipped file
        for ($i = 0; $i < $zip->numFiles; $i++) {
            $filename = $zip->getNameIndex($i);
            
            //create a "local" temp file in order to put it "remotely" in the same machine
            $temp = tmpfile();
            
            //create the new file with the same name from the extracted file in question
            ftp_fput($conn_id, $ftp_path_to_unzip . $filename, $temp, FTP_ASCII);
            
            //set write permissions, eventually we will put its content
            ftp_site($conn_id, "CHMOD 0777 " . $ftp_path_to_unzip . $filename);
            
            //open the new file that we have created
            $fp = fopen($local_path_to_unzip . $filename, 'w');
            
            //put the content from zipped file
            $content = $zip->getFromName($filename);
            fputs($fp, $content);
            
            //close the file
            fclose($fp);
            
            //now only the owner can write the file
            ftp_site($conn_id, "CHMOD 0644 " . $ftp_path_to_unzip . $filename);
            
        }
    }
    
    // close the connection and the file handler
    ftp_close($conn_id);
    
    //close the zip file
    $zip->close();
}

This is the firt step to start a more complex customization, because the code above is not able to know if the zipped file is a "directory" or "file".

Community
  • 1
  • 1
manix
  • 14,537
  • 11
  • 70
  • 107