Extract only specific extensions from a ZIP

2

I'm developing a system where in some part of the client the client can send a ZIP file containing only images.

I'm trying to do this in a way that I can extract from this ZIP only the files that contain image-specific extensions.

I know that in PHP, when we are going to list only one type of extension in a directory, we use the glob function to do this.

Is there any way to do a similar operation with class ZipArchive of PHP?

If someone knows a plugin in Laravel that does something like this, it will be very useful such information.

Note : The ZipArchive :: extractTo () method accepts a second parameter, which is an array of files of white list of the files that will be extracted.

It would be nice if this also worked with a glob brace !

    
asked by anonymous 02.02.2015 / 12:39

2 answers

2

Use the library Extractor , which extracts compressed files and returns a% object of the Finder package, documentation < a href="http://symfony.com/doc/current/components/finder.html"> here .

See the example for your situation:

$temporaryDirectory = new Mmoreram\Extractor\Filesystem\TemporaryDirectory();
$extensionResolver = new Mmoreram\Extractor\Resolver\ExtensionResolver;
$extractor = new Mmoreram\Extractor\Extractor($temporaryDirectory, $extensionResolver);

$finder = $extractor->extractFromFile($uploadFile);

$validMimes = ["image/png", "image/jpg"];

$filter = function(\SplFileInfo $path) {
    $file = new File($path);

    if (in_array($file->getMimeType(), $validMimes)) {
        return true;
    }
};

$validFiles = $finder->files()->filter($filter);
    
02.02.2015 / 18:09
0

Based on the advice given by @RodigoRigotti, I wrote a code to exclude unwanted extension files. The extraction is done to a secure folder, not to give the user direct access to the folder (thus avoiding a PHP injection).

 public function postAjaxUploadZip($id) {   
        $file = Input::file('zip');

        $rules = [
            'zip' => 'required|mimes:zip'
        ];

        $messages = [
            'mimes' => "Extensão de arquivo inválida"
        ];

        $validation = Validator::make(Input::all(), $rules, $messages);


        if ($validation->passes()) {

            try{

                $zip = $file->getRealPath();

                $zipObject =  new ZipArchive;
                if (! $zipObject->open($zip)) {

                    throw new RunTimeException('Não foi possível abrir o arquivo enviado');
                }

                $path = base_path("secure/{$id}");  

                if (! File::isDirectory($path)) {

                    File::makeDirectory($path, 0755);
                }

                // Extrai para uma pasta segura, para o usuário não ter acesso a esses arquivos pelo pasta "public" do Laravel
                $zipObject->extractTo($path);

                // Itera com os arquivos do diretório onde houve a extração

                $files = new FileSystemIterator($path);

                foreach ($files as $file) {

                   $data = [
                      'file' => $file->getRealPath()
                   ];

                   $rules = ['file' => 'mimes:jpg,png,bmp,jpeg'];

                   if (Validator::make($data, $rules)->fails()) {

                      $deletedFiles[] = $file->getFilename();

                   }

                }   

                File::delete($filesToDelete);


            } catch (Exception $e) {

                return Response::json([
                    'error'     => $e->getMessage(),
                    'directory' => $path,
                ]);
            }


            return Response::json([
                'error' => false, 
                'deletedFiles' => $filesToDelete
            ]);

        } else {

            return Response::json(['error' => $validation->messages()]);    
        }
    }

If someone has a better idea, it will be a great help. The less code the better!

    
02.02.2015 / 13:29