Jump to content
Sign in to follow this  
k00ni

[Klasse] Entpacken von Archiven (tar, zip etc.)

Recommended Posts

Nachfolgend habe ich mal eine Klasse angehangen, die einem erlaubt folgende Archivtypen zu entpacken: .zip, .tar, .gz, .bz2, .tar.gz, .tgz und .tar.bz2. Ich konnte sie leider nicht testen, da auf meinem Server Safe-Mode = On ist. Somit kann man sie nur einsetzen, wenn diese Einstellung in PHP deaktiviert ist. Da ich immer mal ein paar Funktionen benötigte, die mit Archiven umgehen können, habe ich mir entsprechende einfach mal zusammengestellt.


Die Funktionen stammen einerseits aus einem Beitrag auf tutorials.de, sowie einer Klasse aus dem limbo-Projekt (Mambo, nur ohne Datenbank).


Da ich sie wie gesagt noch nicht getestet habe, würde ich mich über eventuelles Feedback freuen.

 

S_last_source_path = $S_source_path;
   }

   // Speichert den zuletzt gesetzten Quellpfad. ------------------------------
   public function set_last_source_path ($S_last_source_path)
   {
       $this->S_last_source_path = $S_last_source_path;
   }

   // Speichert den zuletzt gesetzten Zielpfad. -------------------------------
   public function set_last_target_path ($S_last_target_path)
   {
       $this->S_last_target_path = $S_last_target_path;
   }

   // Ermittelt den Dateinamen des komprimierten Dateiarchivs. ----------------
   function get_uncompressed_filename($S_archive_filename)
   {
       $S_archive_filename_parts = explode(".", $S_archive_filename);

       for ($i=0; $i set_last_source_path($S_source_path);
       $this->set_last_target_path($S_target_path);

       // Archivtyp ermitteln. ------------------------------------------------
       $S_archive_type = $this->get_archive_type( $S_source_path );

       switch($S_archive_type)
       {
           // GZIP. -----------------------------------------------------------
           case 'gzip':
               $this->extract_gzip ( $S_source_path, $S_target_path );
               break;

           // BZIP2. ----------------------------------------------------------
           case 'bzip2':
               $this->extract_bzip2 ( $S_source_path, $S_target_path );
               break;

           // TAR. ------------------------------------------------------------
           case 'tar':
               $this->extract_tar ( $S_source_path );
               break;

           // ZIP. ------------------------------------------------------------
           case 'zip':
               echo "Starte Entpacken des ZIP-Archives.";
               $this->extract_zip ( $S_source_path, $S_target_path );
               break;

           // Nicht unterstützter Archivtyp. ----------------------------------
           default:
               echo "Unbekannter Archivtyp";
               return false;
       }

       return true;
   }

   // Entpackt ein ZIP-Archiv. ------------------------------------------------
   public function extract_zip ( $S_source_path, $S_target_path )
   {
       // Speichert die Parametr.
       $this->set_last_source_path($S_source_path);
       $this->set_last_target_path($S_target_path);

       if(substr($S_target_path, -1) != '/')
       {
           $S_target_path .= '/';
       }

       if(false == is_dir($S_target_path))
       {
           mkdir($S_target_path, 0777);
       }

       $Res_zip_file = fopen($S_source_path, 'rb');

       $I_size = filesize($S_source_path);

       fseek($Res_zip_file, $I_size - 22);

       // End of central dir record
       $A_data = unpack('Vsig/vdisk/vdisk_start/vdisk_entries/ventries/Vsize/'.
                        'Voffset/vcommentsize', fread($Res_zip_file, 22));

       rewind($Res_zip_file);

       for ($i = 0; $i > 11;
               $I_minute  =  ($A_header['mtime'] & 0x07E0) >> 5;
               $I_second  =  ($A_header['mtime'] & 0x001F) * 2;
               $I_year    = (($A_header['mdate'] & 0xFE00) >> 9) + 1980;
               $I_month   =  ($A_header['mdate'] & 0x01E0) >> 5;
               $I_day     =   $A_header['mdate'] & 0x001F;

               $A_header['mtime'] = mktime($I_hour, $I_minute, $I_second,
                                           $I_month, $I_day, $I_year);
           }
           else
           {
               $A_header['mtime'] = time();
           }

           if((substr($A_header['filename'], -1) == '/') OR
              ($A_header['filename']             == '.') OR
              ($A_header['filename']             == '..'))
           {
               if(false === is_dir($S_target_path . $A_header['filename']))
               {
                   // Wenn ein / am Ende ist, führt das bei mkdir zu Problemen,
                   // also dieses ggf. entfernen.
                   if(substr($A_header['filename'], -1) == '/')
                   {
                       $A_header['filename'] = substr ($A_header['filename'], 0,
                                                       strlen ($A_header['filename'])-1);
                   }

                   if (mkdir($S_target_path . $A_header['filename']) === true)
                   {
                       chmod ($S_target_path . $A_header['filename'], 0777);
                   }
               }

               continue;
           }

           $Res_target_file = fopen($S_target_path . $A_header['filename'], 'wb');

           while($A_header['compressed_size'])
           {
               if($A_header['compressed_size'] set_last_source_path($S_source_path);

       $Res_tar_archive = fopen( $S_source_path , "r" );

       $S_datainfo = '';

       $S_data = '';

       while ( feof ( $Res_tar_archive ) === false )
       {
           $S_read_data = fread ( $Res_tar_archive , 512 );

           if ( substr ( $S_read_data, 257, 5 ) == 'ustar' )
           {
               if ( empty ( $S_datainfo ) === false )
               {
                   $I_pos_count = 0;

                   $S_name = '';

                   while ( substr ( $S_datainfo, $I_pos_count, 1) != chr(0) )
                   {
                       $S_name .= substr ( $S_datainfo, $I_pos_count, 1);
                       $I_pos_count++;
                   }

                   if (!empty($S_name))
                   {
                       if ( substr ( $S_name , -1) == '/' )
                       {
                           mkdir ( $S_name );
                       }
                       else
                       {
                           $I_data_size = strlen ( $S_data ) - 1;

                           while ( ( substr ( $S_data, $I_data_size, 1 ) == chr(0) ) AND
                                   ( $I_data_size > -1 ) )
                           {
                               $I_data_size--;
                           }

                           $I_data_size++;

                           $S_filedata = '';

                           for ( $I_data_count = 0; $I_data_count  -1 ) )
                   {
                       $I_data_size--;
                   }

                   $I_data_size++;

                   $S_filedata = '';

                   for ($I_data_count=0; $I_data_count get_uncompressed_filename( $S_target_path ),
                                      "w" );

       fwrite( $S_uncompressed_file , $S_content );

       fclose( $S_uncompressed_file );
   }

   // Entpackt ein GZIP-Archiv. -----------------------------------------------
   public function extract_gzip ( $S_source_path, $S_target_path )
   {
       $S_content = '';

       $Res_gzip_file = gzopen ( $S_source_path , "r" );

       while ( gzeof( $Res_gzip_file ) === false)
       {
           $S_content .= gzread ( $Res_gzip_file , 1 );
       }

       gzclose($Res_gzip_file);

       $Res_uncompressed_file = fopen ( $this->get_uncompressed_filename ( $S_target_path ),
                                        "w" );

       fwrite ( $Res_uncompressed_file, $S_content );

       fclose( $Res_uncompressed_file );
   }
}

?>

Share this post


Link to post
Share on other sites
Guest

tar.bz2 wird also nur entpackt, aber nicht enttart? Richtig? Ab 5.2.0 gibt es übrigens auch eine zip-Bibliothek, die von der zlib mitgebracht wird (also verfügbar, wenn auch gzip verfügbar ist).


Die Ermittlung des Archiv-Typs, genau wie die Ermittlung des entpackten Dateinamens, finde ich nicht sehr gelungen.

Share this post


Link to post
Share on other sites
Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...