xyzzy
2023 年 10 月 26 日午後 5:44
1
エンジニアリングユーザーが、一般的ではないファイル拡張子を持つデータファイルを投稿に添付したいと考えています。これらは基本的にプレーンテキストファイルですが、拡張ASCII文字が含まれています。
DiscourseのNGINX設定を更新してこれらのファイルのMIMEメディアタイプを指定しようとしましたが、うまくいきませんでした。2週間前にこの件についてトピック(https://meta.discourse.org/t/how-to-customize-mime-media-type-emitted-for-certain-attachments/282111)を投稿しましたが、まだ回答がありません。NGINXが更新されなくても、不明なファイルタイプはフォールバックMIMEタイプ「application/octet-stream」で提供されます。それは今のところ問題ありません。
しかし、ユーザーがこれらのデータファイルを投稿にアップロード しようとすると(「アップロード」ボタンを使用するか、ドラッグアンドドロップするか)、Discourseから次のようなエラーポップアップが表示されます。
ユーザーがファイルをアップロードすると、Discourseは賢く振る舞い、画像かそれ以外のファイルタイプかを検出しているようです。さらに、この判定はファイルの内容を見て行っているようです(標準のUnixコマンド「file」のように)。これは、Discourseがインラインで表示するか、添付ファイルとして横に配置するかを決定するためだと推測されます。
これらのデータファイルの場合、このチェックは誤ってファイルを画像として識別しています。試しに、これらのデータファイルの一部をUbuntuボックスに置いて「file」コマンドで確認したところ、案の定、「JPEG image data」と識別されました。
Discourseが画像かどうかを検出せずにファイルをアップロードする方法はありますか?つまり、「それが何であれ、インライン表示せずに添付ファイルとしてアップロードしてください」というような方法です。
あるいは、Discourseでzipファイルを許可するように設定し、ユーザーにアップロード前にファイルをzip化するように指示することもできますが、ランダムなzipファイルアップロードをサイトに許可したくはありません。それはセキュリティ上の問題のように思えます。
ご協力ありがとうございます!
Falco
(Falco)
2023 年 10 月 26 日午後 5:47
2
別の回避策は、それらの奇妙なファイル(.bin、.data、または本当に.anythinggoesなど)に拡張子を付けることです。これにより、Discourseはそのファイルをそのままにしておくのに十分です。
xyzzy
2023 年 10 月 26 日午後 5:59
3
迅速なご対応ありがとうございます!しかし、試してみましたが、うまくいきません。Discourse は、画像かどうかを判断するために、拡張子ではなくファイルの内容を確実に調べています。
「いいね!」 1
xyzzy
2023 年 11 月 15 日午後 11:54
4
これについて何か考えはありますか?これはかなり重大なバグのように思えます。
この問題について調査しました。
要するに、あなたのファイルは、この種のファイルと同じシグネチャで始まるため、JPEGとして検出されています。
Discourseでこの動作を修正することは可能ですが、変更が必要です。(最後に参照)
技術的な詳細をいくつか示します。
この問題はここで始まります:
FastImage ライブラリはファイルを開き、タイプとサイズを決定します。
予想どおり、JPEGというタイプが返されます。
JPEGシグネチャ を見ると、次のようになります。
JPEGマーカー
詳細情報:List of file signatures - Wikipedia
JPEG - Wikipedia
常に次のマーカーバイトで始まります:FF D8
サンプルファイルをHexエディタで確認すると、同じように始まっていることがわかります。
次に、FastImageがJPEGをどのように検出するかを見ると、ここで確認できます。
# frozen_string_literal: true
# coding: ASCII-8BIT
# FastImage finds the size or type of an image given its uri.
# It is careful to only fetch and parse as much of the image as is needed to determine the result.
# It does this by using a feature of Net::HTTP that yields strings from the resource being fetched
# as soon as the packets arrive.
#
# No external libraries such as ImageMagick are used here, this is a very lightweight solution to
# finding image information.
#
# FastImage knows about GIF, JPEG, BMP, TIFF, ICO, CUR, PNG, HEIC/HEIF, AVIF, PSD, SVG, WEBP and JXL files.
#
# FastImage can also read files from the local filesystem by supplying the path instead of a uri.
# In this case FastImage reads the file in chunks of 256 bytes until
# it has enough. This is possibly a useful bandwidth-saving feature if the file is on a network
# attached disk rather than truly local.
#
# FastImage will automatically read from any object that responds to :read - for
# instance an IO object if that is passed instead of a URI.
This file has been truncated. show original
ただし、必要なバイトがすべて存在しないため、画像情報を抽出することはできません。
Discourseでこの問題をどのように修正しますか?
FastImageのコードを見ると、渡すことができる便利なオプションがあります。
# frozen_string_literal: true
# coding: ASCII-8BIT
# FastImage finds the size or type of an image given its uri.
# It is careful to only fetch and parse as much of the image as is needed to determine the result.
# It does this by using a feature of Net::HTTP that yields strings from the resource being fetched
# as soon as the packets arrive.
#
# No external libraries such as ImageMagick are used here, this is a very lightweight solution to
# finding image information.
#
# FastImage knows about GIF, JPEG, BMP, TIFF, ICO, CUR, PNG, HEIC/HEIF, AVIF, PSD, SVG, WEBP and JXL files.
#
# FastImage can also read files from the local filesystem by supplying the path instead of a uri.
# In this case FastImage reads the file in chunks of 256 bytes until
# it has enough. This is possibly a useful bandwidth-saving feature if the file is on a network
# attached disk rather than truly local.
#
# FastImage will automatically read from any object that responds to :read - for
# instance an IO object if that is passed instead of a URI.
This file has been truncated. show original
このオプションを使用すると、エラー(SizeNotFound、ImageFetchFailure、CannotParseImage、UnknownImageType、BadImageURI)が発生しても画像情報は返されず、ファイルは画像として検出されなくなります。
@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}")
その後、機能するはずです:
後でPRを作成できます。このオプションの使用は理にかなっています。
「いいね!」 2
xyzzy
2023 年 11 月 21 日午後 10:46
6
素晴らしい!これは驚異的な分析です!ありがとうございます!
いくつか簡単な質問があります。
これらの変更により、ファイルは画像として検出されなくなり、非画像としてアップロードされて投稿の右側に表示されるようになりますか?
私が正しく理解していれば、この変更をローカルのDiscourseインスタンスで行って試すか、または将来のDiscourseリリースに含まれるまでこれを使用することを提案されています。しかし、どのようにすればよいですか?(私は経験豊富なソフトウェア開発者ですが、Dockerの経験は限られており、Rubyの経験はありません。)
調整が必要なFastImageの呼び出しは、models/upload.rbにありますよね?
はい、その通りです。上記のスクリーンショットのように。
修正を提案しているわけではありません。しかし、待てない場合は、その変更をテストできます。
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
cd /var/discourse
nano containers/app.yml (お好みのエディタを使用してください)
以下のカスタムコマンドを末尾(runセクション)に追加します:
- 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)"
その後、再構築します:
./launcher rebuild app
拡張子のないファイルをアップロードする予定であれば、そうだと思います。他の箇所でも同様の変更が必要かどうかは確認していません。
「いいね!」 1
xyzzy
2023 年 11 月 25 日午前 12:39
8
@Arkshine – これらの詳細について、大変ありがとうございました。両方の修正を個別にテストすることができました(それぞれを新しく復元したVMでテストしました)が、どちらも機能しました!
注:
一時的な修正については、変更を有効にするために「./launcher restart app」を実行する必要がありました。
「spec/models/optimized_image_spec.rb」にもFastImage.new()への参照があるようです。これも他のものと同様に更新する必要がありますか?
ご協力いただき、重ねて感謝いたします!
xyzzy
2023 年 11 月 25 日午前 12:48
10
「いいね!」 1
system
(system)
クローズされました:
2023 年 12 月 25 日午前 12:49
11
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.