powie.de Tech Forum

PHP und Webdesign => Codeschnipsel => Thema gestartet von: k00ni am 06. März 2008, 21:54:21

Titel: [Klasse] Entpacken von Archiven (tar, zip etc.)
Beitrag von: k00ni am 06. März 2008, 21:54:21
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 );
   }
}
?>
Titel: [Klasse] Entpacken von Archiven (tar, zip etc.)
Beitrag von: am 06. März 2008, 22:20:25
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.