From be5a54d67dd4b46f86183682e3d2bcadebeb12da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Mon, 29 Feb 2016 22:39:24 +0100 Subject: [PATCH] FEATURE: new 'allow_all_attachments_for_group_messages' site setting --- app/models/upload.rb | 11 ++++++-- config/locales/server.en.yml | 2 ++ config/site_settings.yml | 2 +- lib/email/receiver.rb | 25 +++++++++++++++--- lib/validators/upload_validator.rb | 2 ++ spec/components/email/receiver_spec.rb | 6 +++++ spec/fixtures/emails/attached_rb_file.eml | 31 +++++++++++++++++++++++ 7 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 spec/fixtures/emails/attached_rb_file.eml diff --git a/app/models/upload.rb b/app/models/upload.rb index 060cf187ab0..8d2c0ffeb98 100644 --- a/app/models/upload.rb +++ b/app/models/upload.rb @@ -14,6 +14,8 @@ class Upload < ActiveRecord::Base has_many :optimized_images, dependent: :destroy + attr_accessor :is_attachment_for_group_message + validates_presence_of :filesize validates_presence_of :original_filename @@ -62,8 +64,9 @@ class Upload < ActiveRecord::Base # options # - content_type - # - origin - # - image_type + # - origin (url) + # - image_type ("avatar", "profile_background", "card_background") + # - is_attachment_for_group_message (boolean) def self.create_for(user_id, file, filename, filesize, options = {}) DistributedMutex.synchronize("upload_#{user_id}_#{filename}") do # do some work on images @@ -141,6 +144,10 @@ class Upload < ActiveRecord::Base upload.height = height upload.origin = options[:origin][0...1000] if options[:origin] + if options[:is_attachment_for_group_message] + upload.is_attachment_for_group_message = true + end + if is_dimensionless_image?(filename, upload.width, upload.height) upload.errors.add(:base, I18n.t("upload.images.size_not_found")) return upload diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 1a4fa4ec2ab..093fd5449a0 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -1001,6 +1001,8 @@ en: default_opengraph_image_url: "URL of the default opengraph image." + allow_all_attachments_for_group_messages: "Allow all email attachments for group messages." + enable_flash_video_onebox: "Enable embedding of swf and flv (Adobe Flash) links in oneboxes. WARNING: may introduce security risks." default_invitee_trust_level: "Default trust level (0-4) for invited users." diff --git a/config/site_settings.yml b/config/site_settings.yml index 9657a80997e..15e68c30706 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -617,8 +617,8 @@ files: client: true regex: '^((https?:)?\/)?\/.+[^\/]' shadowed_by_global: true - default_opengraph_image_url: '' + allow_all_attachments_for_group_messages: false trust: default_trust_level: diff --git a/lib/email/receiver.rb b/lib/email/receiver.rb index f094631da22..fa7f81b912c 100644 --- a/lib/email/receiver.rb +++ b/lib/email/receiver.rb @@ -72,20 +72,35 @@ module Email case destination[:type] when :group group = destination[:obj] - create_topic(user: user, raw: body, title: subject, archetype: Archetype.private_message, target_group_names: [group.name], skip_validations: true) + create_topic(user: user, + raw: body, + title: subject, + archetype: Archetype.private_message, + target_group_names: [group.name], + is_group_message: true, + skip_validations: true) + when :category category = destination[:obj] raise StrangersNotAllowedError if user.staged? && !category.email_in_allow_strangers raise InsufficientTrustLevelError if !user.has_trust_level?(SiteSetting.email_in_min_trust) - create_topic(user: user, raw: body, title: subject, category: category.id, skip_validations: user.staged?) + create_topic(user: user, + raw: body, + title: subject, + category: category.id, + skip_validations: user.staged?) + when :reply email_log = destination[:obj] raise ReplyUserNotMatchingError if email_log.user_id != user.id - create_reply(user: user, raw: body, post: email_log.post, topic: email_log.post.topic) + create_reply(user: user, + raw: body, + post: email_log.post, + topic: email_log.post.topic) end end end @@ -271,6 +286,7 @@ module Email else options[:topic_id] = options[:post].try(:topic_id) options[:reply_to_post_number] = options[:post].try(:post_number) + options[:is_group_message] = options[:topic].private_message? && options[:topic].allowed_groups.exists? create_post_with_attachments(options) end end @@ -291,7 +307,8 @@ module Email # read attachment File.open(tmp.path, "w+b") { |f| f.write attachment.body.decoded } # create the upload for the user - upload = Upload.create_for(options[:user].id, tmp, attachment.filename, tmp.size) + opts = { is_attachment_for_group_message: options[:is_group_message] } + upload = Upload.create_for(options[:user].id, tmp, attachment.filename, tmp.size, opts) if upload && upload.errors.empty? # try to inline images if attachment.content_type.start_with?("image/") && options[:raw][/\[image: .+ \d+\]/] diff --git a/lib/validators/upload_validator.rb b/lib/validators/upload_validator.rb index 985fe928d9a..b200fc16c32 100644 --- a/lib/validators/upload_validator.rb +++ b/lib/validators/upload_validator.rb @@ -5,6 +5,8 @@ module Validators; end class Validators::UploadValidator < ActiveModel::Validator def validate(upload) + return true if upload.is_attachment_for_group_message && SiteSetting.allow_all_attachments_for_group_messages + extension = File.extname(upload.original_filename)[1..-1] || "" if is_authorized?(upload, extension) diff --git a/spec/components/email/receiver_spec.rb b/spec/components/email/receiver_spec.rb index bdb42a0a22b..734276c6a71 100644 --- a/spec/components/email/receiver_spec.rb +++ b/spec/components/email/receiver_spec.rb @@ -271,6 +271,12 @@ describe Email::Receiver do expect { process(:email_reply_4) }.to change { topic.posts.count } end + it "supports any kind of attachments when 'allow_all_attachments_for_group_messages' is enabled" do + SiteSetting.allow_all_attachments_for_group_messages = true + expect { process(:attached_rb_file) }.to change(Topic, :count) + expect(Post.last.raw).to match(/discourse\.rb/) + end + end context "new topic in a category" do diff --git a/spec/fixtures/emails/attached_rb_file.eml b/spec/fixtures/emails/attached_rb_file.eml new file mode 100644 index 00000000000..960b3e6d676 --- /dev/null +++ b/spec/fixtures/emails/attached_rb_file.eml @@ -0,0 +1,31 @@ +Return-Path: +From: Foo Bar +To: team@bar.com +Date: Mon, 29 Feb 2016 21:54:01 +0100 +Message-ID: <56d4afe991ed0_3ab83fdf94441a20677f0@HAL.lan.mail> +Subject: Email with .rb file attached +Mime-Version: 1.0 +Content-Type: multipart/mixed; + boundary="--==_mimepart_56d4afe991d17_3ab83fdf94441a206765"; + charset=UTF-8 +Content-Transfer-Encoding: 7bit + + +----==_mimepart_56d4afe991d17_3ab83fdf94441a206765 +Content-Type: text/plain; + charset=UTF-8 +Content-Transfer-Encoding: 7bit + +Please find the source code of Discourse attached. +----==_mimepart_56d4afe991d17_3ab83fdf94441a206765 +Content-Type: application/x-ruby; + charset=UTF-8; + filename=discourse.rb +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; + filename=discourse.rb +Content-ID: <56d4afe992cb6_3ab83fdf94441a20678c3@HAL.lan.mail> + +cHV0cyAiSGVsbG8gRGlzY291cnNlIgo= + +----==_mimepart_56d4afe991d17_3ab83fdf94441a206765--