hotti: FileType (Eigenbau)

hi,

unten der Code. Bei mp3 ohne ID3 Tag bin ich mir nicht ganz sicher, ob das hex pattern fffb oder fffa lautet, wer Lust hat, teste mal ... danke!!

  
<?php  
  
  
// Die Klasse ist leicht erweiterbar:  
// Methode definieren und in $TYPES eintragen, fertig  
class FileType{  
	// Associate type => methods  
	// Möglicherweise gibt es mehrere Funktionen zum Prüfen eines Types  
	private $TYPES = array(  
		'image/gif'          => array('gif'),  
		'image/x-bmp'        => array('bmp'),  
		'application/pdf'    => array('pdf'),  
		'image/x-png'        => array('png'),  
		'image/jpeg'         => array('jpeg'),  
		'application/msword' => array('word97'),  
		'audio/mp3'          => array('id3', 'fffb'),  
		'application/zip'    => array('zip'),  
		'application/x-gzip' => array('gzip'),  
	);  
  
	/* ~~~~~~~~~~~~~~~~~ associated callback methods ~~~~~~~~~~~~~~~~ */  
	private function gzip($type){  
		if(fread($this->FH,2) == pack("H*", '1f8b')) return $type;  
	}  
	private function zip($type){  
		if('PK' != fread($this->FH,2)) return;  
		$s = fread($this->FH,2);  
		if($s == pack("H*", '0304')) return $type;  
	}  
	private function fffb($type){  
		if(fread($this->FH,2) == pack("H*", 'fffb')) return $type;  
	}  
  
	private function id3($type){  
		if(fread($this->FH,3) == 'ID3') return $type;  
	}  
	private function word97($type){  
		if(pack("H*", 'D0Cf11E0A1B11AE10000') == fread($this->FH, 10)){  
			return $type;  
		}  
	}  
	private function jpeg($type){  
		if(fread($this->FH,2) == pack("H*", 'ffd8')) return $type;  
	}  
  
	private function png($type){  
		fseek($this->FH,1,0);  
		if(fread($this->FH,3) == 'PNG') return $type;  
	}  
  
	private function bmp($type){  
		if(fread($this->FH,2) == 'BM') return $type;  
	}  
  
	private function gif($type){  
		if(fread($this->FH,4) == 'GIF8') return $type;  
	}  
  
	private function pdf($type){  
		if(fread($this->FH,5) == '%PDF-') return $type;  
	}  
  
	/* ~~~~~~~~~~~~~~~~~ associated callback methods ~~~~~~~~~~~~~~~~ */  
  
	function __construct($file){  
		// Handle erstellen  
		if(! $this->FH = fopen($file, "r")){  
			throw new Exception("IO-Error: Unable to open File '$file'");  
		}  
	}  
  
	public function type(){  
		$default_type = 'application/octet-stream';  
		foreach($this->TYPES as $type => $methods){  
			// call associated methods  
			foreach($methods as $callback_method){  
				if(! method_exists($this, $callback_method)) return $default_type;  
				fseek($this->FH, 0, 0);  
				if($return_type = $this->$callback_method($type)){  
					return $return_type;  
				}  
			}  
		}  
		return $default_type;  
	}  
} // End class FileType  
  
try{  
	$ft = new FileType('d:/tmp/x.mp');  
	echo $ft->type();  
}  
catch(Exception $e){  
	echo $e->getMessage();  
}  
  
  
return;  
?>  

  1. Hallo,

    unten der Code. Bei mp3 ohne ID3 Tag bin ich mir nicht ganz sicher, ob das hex pattern fffb oder fffa lautet

    das hat mit ID3-Tags nichts zu tun, sondern damit, ob CRC-Checksummen verwendet werden oder nicht. Meiner Erfahrung nach verzichten die meisten mp3-Dateien darauf, das entsprechende Bit ist also 0 (Mehr dazu). Die nachfolgenden 4 Bits geben dann die Bitrate an, die übrigens von Frame zu Frame wechseln kann (VBR).

    Ciao,
     Martin

    --
    Keine Sorge, wir finden für jede Lösung ein Problem.
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    1. Hallo,

      unten der Code. Bei mp3 ohne ID3 Tag bin ich mir nicht ganz sicher, ob das hex pattern fffb oder fffa lautet

      das hat mit ID3-Tags nichts zu tun, sondern damit, ob CRC-Checksummen verwendet werden oder nicht. Meiner Erfahrung nach verzichten die meisten mp3-Dateien darauf, das entsprechende Bit ist also 0 (Mehr dazu). Die nachfolgenden 4 Bits geben dann die Bitrate an, die übrigens von Frame zu Frame wechseln kann (VBR).

      Ok, danke. Das Pattern fffa fand ich in einem Perl-Modul, das ist vermutlich nicht oder nicht immer richtig. Ich habe mal auf meine Festplatte gestöbert und doch ein paar mp3 ohne id3 gefunden, die haben alle fffb in den ersten beiden bytes (damit funktioniert mein Code).

      Horst Ohr

      1. Hi,

        [...] und doch ein paar mp3 ohne id3 gefunden

        apropos: Ich suche schon seit langer Zeit ein Tool (bevorzugt Linux-Kommandozeile), mit dem man aus einr mp3-Datei alles rausschneiden kann, was kein Audio-Chunk ist. Also sowohl die ID3-Tags, als auch eingebettete Texte oder andere Daten - was zwar nicht explizit der Spec entspricht, aber prima funktioniert, solange die Sequenz 0xFF, 0xF* nicht auftritt.

        Bisher habe ich nur diverse Tools gefunden, die ID3v2-Tags rauslöschen, in ID3v1-Tags aber einfach nur alle Felder mit Spaces überschreiben. Das will ich nicht - ich will den ganzen Müllblock weg haben!

        Ich war schon mal kurz davor, das Gewünschte selbst zu schreiben, hab's aber bisher noch nicht durchgezogen.

        Ciao,
         Martin

        --
        Bitte komme jemand mit einem *g* zum Wochenende, damit nicht über mich gelacht wird.
          (Gunnar Bittersmann)
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        1. hi,

          Ich war schon mal kurz davor, das Gewünschte selbst zu schreiben, hab's aber bisher noch nicht durchgezogen.

          Klar. Eine Sache für lange Winterabende ;)
                       UND DER IST HOFFENTLICH BALD VORBEI!!!!

          Ne, im Ernst, egal aus welchem Motiv heraus, eine schöne Programmieraufgabe, ich für meinen Teil operiere gerne mit nackten Bytes und würde das mit Perl machen, sowie das Modul IO::String verwenden, wenn temporäre Handles gebraucht werden.

          Hotti

          1. Hallo,

            Ich war schon mal kurz davor, das Gewünschte selbst zu schreiben, hab's aber bisher noch nicht durchgezogen.
            Klar. Eine Sache für lange Winterabende ;)

            ja, oder ein Wochenendprojekt.

            UND DER IST HOFFENTLICH BALD VORBEI!!!!

            Tja, heute ist Frühlingsanfang. Aber draußen konnte ich den Frühling heute immer nur in Häppchen von einer halben, maximal einer Stunde sehen. Dann war erstmal wieder dunkle Bewölkung, Schauer, zwischendurch mal ein bissl Graupel - sogar verhaltenes Donnergrollen habe ich den Tag über mehrmals gehört.

            Ne, im Ernst, egal aus welchem Motiv heraus, eine schöne Programmieraufgabe, ich für meinen Teil operiere gerne mit nackten Bytes ...

            Ich weiß. ;-)

            und würde das mit Perl machen

            Warum habe ich das schon geahnt? ;-)
            Ich würd's eher direkt in C machen. Aber jeder wie's ihm gefällt.

            Ciao,
             Martin

            --
            Realität ist eine Illusion, die durch Unterversorgung des Körpers mit Alkohol entstehen kann.
            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        2. Tach,

          Bisher habe ich nur diverse Tools gefunden, die ID3v2-Tags rauslöschen, in ID3v1-Tags aber einfach nur alle Felder mit Spaces überschreiben. Das will ich nicht - ich will den ganzen Müllblock weg haben!

          id3v2 tut das, alternativ kannst du auch von Hand die letzten 128 Bytes entfernen.

          mfg
          Woodfighter

          1. Hallo Jens,

            Bisher habe ich nur diverse Tools gefunden, die ID3v2-Tags rauslöschen, in ID3v1-Tags aber einfach nur alle Felder mit Spaces überschreiben. Das will ich nicht - ich will den ganzen Müllblock weg haben!
            id3v2 tut das

            -> 404 Not Found  :-(

            alternativ kannst du auch von Hand die letzten 128 Bytes entfernen.

            Ganz so einfach ist es nicht, da dieser Block manchmal auch am Dateianfang steht. Was auch oft vorkommt, ist ein 32 Byte langer "Vorlauf" am Dateianfang, der keinen für mich erkennbaren Zweck hat - man kann ihn ohne Nachteile entfernen.
            Das Rumhantieren mit Hex-Editor ist zwar für Einzelfälle eine Alternative, aber nicht wenn's häufig vorkommt.

            Ciao,
             Martin

            --
            Es existiert kein Weg, "für" etwas zu optimieren, sondern nur gegen alles andere.
              (Cheatah)
            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
            1. Tach,

              id3v2 tut das

              -> 404 Not Found  :-(

              http://id3v2.sourceforge.net/ meinte ich, der Link im Debian-Package ist wohl veraltet.

              alternativ kannst du auch von Hand die letzten 128 Bytes entfernen.

              Ganz so einfach ist es nicht, da dieser Block manchmal auch am Dateianfang steht.

              Ne, ID3v1 ist immer am Dateiende, am Anfang ist entweder ID3v2 oder APE.

              Was auch oft vorkommt, ist ein 32 Byte langer "Vorlauf" am Dateianfang, der keinen für mich erkennbaren Zweck hat - man kann ihn ohne Nachteile entfernen.

              Die interessante Frage ist, warum willst du das ändern?

              mfg
              Woodfighter

              1. Hallo,

                id3v2 tut das
                -> 404 Not Found  :-(
                http://id3v2.sourceforge.net/ meinte ich, der Link im Debian-Package ist wohl veraltet.

                ah, danke. Das geht. Der dort angebotene Link zur Homepage des Projekts verweist aber leider auch auf einen nicht existierenden Server. Zumindest antwortet dort niemand auf HTTP. Das macht es schwer, sich über die Features und Fähigkeiten des Programms zu informieren. An anderer Stelle gibt sourceforge aber doch ein bisschen Auskunft. Das probier ich mal aus, ich kann's mir direkt aus den Paketquellen meiner Distro installieren.

                alternativ kannst du auch von Hand die letzten 128 Bytes entfernen.
                Ganz so einfach ist es nicht, da dieser Block manchmal auch am Dateianfang steht.
                Ne, ID3v1 ist immer am Dateiende, am Anfang ist entweder ID3v2 oder APE.

                Hm. Irgendwelchen Schrott, den ich nicht identifizieren konnte, habe ich auch schon öfter am Dateianfang gesehen. Meistens ein Block von 128 Bytes, deswegen hatte ich auf ID3v1 getippt. APE kannte ich allerdings noch gar nicht - das könnte es natürlich auch gewesen sein. Etwas seltener habe ich auch einen Block mit 32 Nullbytes am Dateianfang gesehen. Wofür das gut sein mag, wissen die Götter ...

                Was auch oft vorkommt, ist ein 32 Byte langer "Vorlauf" am Dateianfang, der keinen für mich erkennbaren Zweck hat - man kann ihn ohne Nachteile entfernen.
                Die interessante Frage ist, warum willst du das ändern?

                Weil Daten, die keine für mich nutzbare Information enthalten, in der Datei nichts verloren haben. Ich bin der Meinung, mp3 ist ein Audio-Format. Also möchte ich in meinen archivierten mp3-Dateien auch ausschließlich Audio haben. Und die Meta-Informationen stehen bei mir in der DB - wesentlich ausführlicher, als es in ID3-Tags sein könnte.

                Noch ein Punkt spricht aus meiner Sicht gegen ID3: Manche Player zeigen beim Abspielen den Titel an, wie er im ID3-Tag hinterlegt ist. Das will ich aber nicht - ich will den echten Dateinamen sehen.

                So long,
                 Martin

                --
                Die Zeit, die man zur Fertigstellung eines Projekts wirklich braucht, ist immer mindestens doppelt so lang wie geplant.
                Wurde dieser Umstand bei der Planung bereits berücksichtigt, gilt das Prinzip der Rekursion.
                Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
              2. Hallo Jens,

                http://id3v2.sourceforge.net/

                habe das heute zum ersten Mal ausprobiert - und tatsächlich, mit dem Schalter -D ist sowohl ID3v1 als auch ID3v2 restlos weg. So habe ich mir das gewünscht. Ob auch nicht-standardkonforme Texteinbettungen entfernt werden, weiß ich noch nicht, aber ich vermute, das darf ich nicht erwarten.

                Danke nochmal für den Hinweis.

                Ciao,
                 Martin

                --
                Paradox ist, wenn jemand eingefleischter Vegetarier ist.
                Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
  2. Moin!

    Und wieder etwas, was es in PHP schon gibt - besser, schöner, ausführlicher...

    http://www.php.net/manual/en/book.fileinfo.php

    - Sven Rautenberg

    1. Moin!

      Und wieder etwas, was es in PHP schon gibt - besser, schöner, ausführlicher...

      http://www.php.net/manual/en/book.fileinfo.php

      Meins ist morgen online und da steht auch, warum das ein Eigenbau ist. Interessant dürfte der Aufbau sein, wegen der Dynamik habe ich auf eine Kontrollstruktur verzichtet und anstelle dessen einen Dispatcher gebaut mit Callbackfunktionen wobei es zu jedem MIME-Typ auch mehrere Callbackfunktionen geben kann.

      Schöne Grüße,
      Horst

      1. Moin!

        Moin!

        Und wieder etwas, was es in PHP schon gibt - besser, schöner, ausführlicher...

        http://www.php.net/manual/en/book.fileinfo.php

        Meins ist morgen online und da steht auch, warum das ein Eigenbau ist. Interessant dürfte der Aufbau sein, wegen der Dynamik habe ich auf eine Kontrollstruktur verzichtet und anstelle dessen einen Dispatcher gebaut mit Callbackfunktionen wobei es zu jedem MIME-Typ auch mehrere Callbackfunktionen geben kann.

          
        vagrant@lucid32:~$ echo "PNG" > test.png  
        vagrant@lucid32:~$ file test.png  
        test.png: ASCII text  
          
        hotti@lucid32:~$ filetype.php test.png  
        image/x-png  
        
        

        q.e.d.

        - Sven Rautenberg

        1. [latex]Mae  govannen![/latex]

          vagrant@lucid32:~$ echo "PNG" > test.png
          vagrant@lucid32:~$ file test.png
          test.png: ASCII text

          hotti@lucid32:~$ filetype.php test.png
          image/x-png

          
          >   
          > q.e.d.  
            
          \*g\* Klappt aber auch bei Zufallsfunden:  
            
          `echo "BMW ist eine deutsche Automarke" > test.txt`{:.language-batch}  
            
          ~~~php
          ft = new FileType('test.txt');  
          echo $ft->type(); //image/x-bmp
          

          Stur lächeln und winken, Männer!
          Kai

          --
          var jQuery = $(hit);
          Wir sind die Schlumpf. Widerschlumpf ist schlumpflos. Wir werden Sie einschlumpfen.
          SelfHTML-Forum-Stylesheet
        2. hi,

          vagrant@lucid32:~$ echo "PNG" > test.png
          vagrant@lucid32:~$ file test.png
          test.png: ASCII text

          hotti@lucid32:~$ filetype.php test.png
          image/x-png

            
          Kein Problem. [hier steht auch, warum das so ist](http://rolfrost.de/proglog.html?d=20130321) und welche Prüfverfahren es, neben einem Magic Scan, sonst noch gibt.  
            
          Hotti
          
  3. Hi,

    public function type(){
    $default_type = 'application/octet-stream';
    foreach($this->TYPES as $type => $methods){
    // call associated methods
    foreach($methods as $callback_method){
    if(! method_exists($this, $callback_method)) return $default_type;

      
    sehr sinnvoll.  
    Wenn für einen Typ keine Methode existiert, wird sofort der default\_type zurückgegeben ...  
      
    Die nachfolgenden Typen werden gar nicht mehr probiert, die könnten ja zutreffend sein und dadurch das Ergebnis verfälschen ;-)  
      
    Zur Qualität der einzelnen Test-Methoden wurde schon genug gesagt ...  
      
    cu,  
    Andreas
    
    -- 
    [Warum nennt sich Andreas hier MudGuard?](http://MudGuard.de/)  
    [O o ostern ...](http://ostereier.andreas-waechter.de/)  
      
    Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.  
    
    
  4. Wieso entwickelst du eigentlich nicht gleich eine eigene Programmiersprache?