Discourse: Hochgeladene Datei wird fälschlicherweise als Bild erkannt

Ich habe einige Ingenieure, die einige Datendateien mit ungewöhnlichen Dateierweiterungen an ihre Beiträge anhängen möchten. Es handelt sich im Wesentlichen um reine Textdateien, die jedoch erweiterte ASCII-Zeichen enthalten.

Ich habe versucht, die NGINX-Konfiguration von Discourse zu aktualisieren, um MIME-Medientypen für diese Dateien anzugeben, aber es hat nicht funktioniert. Ich habe vor zwei Wochen ein Thema (How to customize MIME media type emitted for certain attachments?) dazu gepostet, aber bisher keine Antworten erhalten. Selbst wenn NGINX nicht aktualisiert wird, werden unbekannte Dateitypen immer noch mit dem Fallback-MIME-Typ „application/octet-stream“ ausgeliefert. Damit kann ich vorerst leben.

Wenn Benutzer jedoch versuchen, diese Datendateien in einen Beitrag hochzuladen (entweder über die Schaltfläche „Hochladen“ oder per Drag-and-Drop), erhalten sie eine Fehlermeldung von Discourse, ähnlich dieser:

Es scheint, dass Discourse beim Hochladen von Dateien versucht, „schlau“ zu sein und zu erkennen, ob es sich um ein Bild oder einen anderen Dateityp handelt. Darüber hinaus scheint es diese Bestimmung vorzunehmen, indem es die Dateiinhalte betrachtet (ähnlich dem Standard-Unix-Befehl „file“). Ich gehe davon aus, dass Discourse dadurch entscheiden kann, ob es die Datei direkt in den Beitrag einfügt oder als Anhang daneben platziert.

In diesem Fall identifiziert diese Prüfung die Datendateien fälschlicherweise als Bilder. Nur zum Spaß habe ich einige dieser Datendateien auf eine Ubuntu-Box gelegt und sie mit dem Befehl „file“ überprüft, und siehe da, sie wurden als „JPEG image data“ identifiziert.

Gibt es eine Möglichkeit, Dateien hochzuladen, ohne dass Discourse versucht zu erkennen, ob es sich um Bilder handelt? D.h. „Bitte laden Sie diese Datei als Anhang hoch, egal was passiert, fügen Sie sie nicht direkt ein“?

Alternativ könnte ich Discourse so konfigurieren, dass Zip-Dateien zugelassen werden, und den Benutzern sagen, sie sollen ihre Dateien vor dem Hochladen komprimieren, aber ich möchte die Website nicht für zufällige Zip-Datei-Uploads öffnen. Das scheint ein Sicherheitsproblem zu sein.

Vielen Dank im Voraus für jede Hilfe!

Eine weitere Problemumgehung ist die Übernahme einer Erweiterung für diese seltsamen Dateien, wie .bin, .data oder wirklich .anythinggoes, was für Discourse ausreichen sollte, um diese Dateien in Ruhe zu lassen.

Vielen Dank für die schnelle Antwort! Ich habe das jedoch versucht und es funktioniert nicht. Discourse prüft definitiv den Dateiinhalt und nicht die Erweiterung, um festzustellen, ob es sich um ein Bild handelt oder nicht.

1 „Gefällt mir“

Hat jemand Gedanken dazu? Das scheint ein ziemlich bedeutender Fehler zu sein.

Ich habe dieses Problem untersucht.

Kurz gesagt, Ihre Datei wird als JPEG erkannt, da sie mit der gleichen Signatur wie diese Art von Datei beginnt.
Das Beheben dieses Verhaltens in Discourse ist möglich, erfordert jedoch eine Änderung. (siehe unten)


Hier einige technische Details.
Dieses Problem beginnt hier:

Die Bibliothek FastImage öffnet die Datei und bestimmt den Typ und die Größe.
Wie erwartet, gibt sie den Typ JPEG zurück.

Wenn Sie sich die JPEG-Signatur ansehen, sieht sie so aus:

JPEG-Marker

Weitere Informationen: List of file signatures - Wikipedia
JPEG - Wikipedia

Sie beginnt immer mit den folgenden Marker-Bytes: FF D8

Wenn Sie sich Ihre Beispieldatei mit einem Hex-Editor ansehen, werden Sie feststellen, dass sie gleich beginnt.

Wenn Sie sich nun ansehen, wie FastImage ein JPEG erkennt, können Sie hier sehen:

Sie können jedoch keine Bildinformationen extrahieren, da nicht alle erforderlichen Bytes vorhanden sind.

Wie beheben wir dieses Problem in Discourse?
Wenn Sie sich den FastImage-Code ansehen, gibt es eine nützliche Option, die Sie übergeben können.

Durch die Verwendung dieser Option gibt jeder Fehler ( SizeNotFound, ImageFetchFailure, CannotParseImage, UnknownImageType, BadImageURI) keine Bildinformationen zurück; und Ihre Datei wird nicht als Bild erkannt.

@image_info =
begin
   FastImage.new(@file, :raise_on_failure => true)
rescue StandardError
   nil
end
...
is_image ||= @image_info && FileHelper.is_supported_image?("test.#{@image_info.type}")

Dann kann es jetzt funktionieren:

Ich kann später einen PR erstellen. Die Verwendung dieser Option ist hier sinnvoll. :+1:

2 „Gefällt mir“

Wow! Das ist eine phänomenale Analyse! Danke!

Ein paar kurze Fragen:

  1. Werden Dateien mit diesen Änderungen nicht mehr als Bilder erkannt und wie Nicht-Bilder hochgeladen und rechts neben dem Beitrag angezeigt?

  2. Wenn ich das richtig verstehe, schlägst du vor, diese Anpassungen in meiner lokalen Discourse-Instanz vorzunehmen, um dies auszuprobieren und/oder bis es in einer zukünftigen Discourse-Version enthalten ist, zu nutzen. Aber wie mache ich das? (Ich bin ein erfahrener Softwareentwickler, habe aber nur begrenzte Erfahrung mit Docker und keine mit Ruby.)

  3. Der FastImage-Aufruf, der angepasst werden müsste, befindet sich in models/upload.rb, richtig?

  1. Ja, das stimmt – wie in meinem Screenshot oben.

  2. Ich schlage nicht vor, dass Sie die Änderung vornehmen. Wenn Sie jedoch nicht warten können, könnten Sie diese Änderung sicherlich testen.

  • Für eine temporäre Änderung (nach dem Neuerstellen nicht mehr vorhanden):
cd /var/discourse
./launcher enter app
sed -i "s/FastImage.new(@file)/FastImage.new(@file, :raise_on_failure=true)/" lib/upload_creator.rb
sed -i "s/FastImage.new(original_path)/FastImage.new(original_path, :raise_on_failure=true)/" app/models/upload.rb
exit
  • Für eine dauerhafte Änderung (bleibt nach dem Neuerstellen erhalten):
cd /var/discourse
nano containers/app.yml  (verwenden Sie Ihren bevorzugten Editor)

Fügen Sie die folgenden benutzerdefinierten Befehle am Ende (run-Abschnitt) hinzu:

  - replace:
      filename: "/var/www/discourse/lib/upload_creator.rb"
      from: "FastImage.new(@file)"
      to: "FastImage.new(@file, :raise_on_failure=true)"
  - replace:
      filename: "/var/www/discourse/app/models/upload.rb"
      from: "FastImage.new(original_path)"
      to: "FastImage.new(original_path, :raise_on_failure=true)"

Bauen Sie dann neu:

./launcher rebuild app
  1. Ich schätze schon, wenn Sie planen, Dateien ohne Erweiterungen hochzuladen. Ich habe nicht geprüft, ob andere Vorkommen die gleiche Änderung erforderten.
1 „Gefällt mir“

@Arkshine – Vielen Dank für diese Details. Ich konnte beide Korrekturen separat testen (jede auf einer frisch wiederhergestellten VM) und beide haben funktioniert!

Hinweise:

  1. Für die temporäre Korrektur musste ich „./launcher restart app“ ausführen, damit die Änderungen wirksam werden.

  2. Es sieht so aus, als ob „spec/models/optimized_image_spec.rb“ auch eine Referenz auf FastImage.new() enthält. Muss diese wie die anderen auch aktualisiert werden?

Vielen Dank nochmals für Ihre Hilfe!

Ich freue mich, dass es funktioniert. :slight_smile:

  1. Dies dient nur zu Testzwecken, Sie müssen sich also keine Sorgen machen.

Großartig! Danke! Jetzt, da ich das in meiner Entwicklungsumgebung getestet habe, werde ich es in die Test- und Produktionsumgebungen bereitstellen.

Übrigens, wenn Sie Zeit haben, würde ich gerne Ihre Meinung zu einem verwandten Problem hören (How to customize MIME media type emitted for certain attachments?).

1 „Gefällt mir“

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.