debian-mirror-gitlab/lib/gitlab/email/attachment_uploader.rb

69 lines
2.1 KiB
Ruby
Raw Normal View History

2019-02-15 15:39:39 +05:30
# frozen_string_literal: true
2015-09-25 12:07:36 +05:30
module Gitlab
module Email
class AttachmentUploader
attr_accessor :message
def initialize(message)
@message = message
end
2020-03-13 15:44:24 +05:30
def execute(upload_parent:, uploader_class:)
2015-09-25 12:07:36 +05:30
attachments = []
2020-03-13 15:44:24 +05:30
filter_signature_attachments(message).each do |attachment|
2015-09-25 12:07:36 +05:30
tmp = Tempfile.new("gitlab-email-attachment")
begin
2022-05-07 20:08:51 +05:30
content = attachment.body.decoded
File.open(tmp.path, "w+b") { |f| f.write content }
sanitize_exif_if_needed(content, tmp.path)
2015-09-25 12:07:36 +05:30
file = {
tempfile: tmp,
filename: attachment.filename,
content_type: attachment.content_type
}
2020-03-13 15:44:24 +05:30
uploader = UploadService.new(upload_parent, file, uploader_class).execute
2019-02-15 15:39:39 +05:30
attachments << uploader.to_h if uploader
2015-09-25 12:07:36 +05:30
ensure
tmp.close!
end
end
attachments
end
2020-03-13 15:44:24 +05:30
private
# If this is a signed message (e.g. S/MIME or PGP), remove the signature
# from the uploaded attachments
def filter_signature_attachments(message)
attachments = message.attachments
2020-04-22 19:07:51 +05:30
content_type = normalize_mime(message.content_type)
2021-06-08 01:23:25 +05:30
protocol = normalize_mime(message.content_type_parameters&.fetch(:protocol, nil))
2020-03-13 15:44:24 +05:30
2020-04-22 19:07:51 +05:30
if content_type == 'multipart/signed' && protocol
attachments.delete_if { |attachment| protocol == normalize_mime(attachment.content_type) }
2020-03-13 15:44:24 +05:30
end
attachments
end
2020-04-22 19:07:51 +05:30
# normalizes mime-type ignoring case and removing extra data
# also removes potential "x-" prefix from subtype, since some MUAs mix them
# e.g. "application/x-pkcs7-signature" with "application/pkcs7-signature"
def normalize_mime(content_type)
MIME::Type.simplified(content_type, remove_x_prefix: true)
end
2022-05-07 20:08:51 +05:30
# https://gitlab.com/gitlab-org/gitlab/-/issues/239343
def sanitize_exif_if_needed(content, path)
exif_sanitizer = Gitlab::Sanitizers::Exif.new
exif_sanitizer.clean_existing_path(path, content: content, skip_unallowed_types: true)
end
2015-09-25 12:07:36 +05:30
end
end
end