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

Begonnen von k00ni, 06. März 2008, 21:54:21

Vorheriges Thema - Nächstes Thema

k00ni

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 );
   }
}
?>

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.

all your base are belong to us / Discord