Project

General

Profile

Feature #44400 » 0001-Send-PDF-attachments-as-a-download-from-the-download.patch

Go MAEDA, 2026-08-31 11:12

View differences:

app/controllers/attachments_controller.rb
79 79
    end
80 80
    if stale?(:etag => @attachment.digest, :template => false)
81
      # PDFs are sent inline
82 81
      send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
83 82
                                      :type => detect_content_type(@attachment),
84 83
                                      :disposition => disposition(@attachment)
......
313 312
    content_type
314 313
  end
314
  # Attachments are always sent as a download, except when an inline
315
  # disposition is explicitly requested for a PDF compatible file, as done by
316
  # the PDF preview. Other content types must not be sent inline to prevent
317
  # them from being rendered by the browser (e.g. XSS with HTML or SVG files)
315 318
  def disposition(attachment)
316
    if detect_content_type(attachment) == 'application/pdf'
319
    if params[:disposition] == 'inline' && detect_content_type(attachment) == 'application/pdf'
317 320
      'inline'
318 321
    else
319 322
      'attachment'
app/views/attachments/pdf.html.erb
1 1
<%= render :layout => 'layouts/file' do %>
2 2
  <%= render :partial => 'common/pdf',
3
             :locals => {:path => download_named_attachment_path(@attachment, @attachment.filename)} %>
3
             :locals => {:path => download_named_attachment_path(@attachment, @attachment.filename, :disposition => 'inline')} %>
4 4
<% end %>
test/functional/attachments_controller_test.rb
262 262
    assert_response :success
263 263
    assert_equal 'text/html', @response.media_type
264
    path = download_named_attachment_path(attachments(:attachments_023), attachments(:attachments_023).filename)
264
    path = download_named_attachment_path(attachments(:attachments_023), attachments(:attachments_023).filename, :disposition => 'inline')
265 265
    assert_select ".filecontent.pdf object[data='#{path}']"
266 266
    assert_select '.nodata', :text => 'No preview available'
267 267
  end
......
423 423
    assert_select 'div.filecontent.pdf object[type=?]', 'application/pdf'
424 424
  end
425
  def test_download_pdf_compatible_illustrator_file_should_be_sent_inline_as_pdf
425
  def test_download_pdf_compatible_illustrator_file_should_be_sent_as_a_download
426 426
    set_tmp_attachments_directory
427 427
    attachment = Attachment.create!(
428 428
      :file => mock_file_with_options(
......
436 436
    get(:download, :params => {:id => attachment.id})
437 437
    assert_response :success
438
    # Sent as PDF so that browsers display it inline
438
    assert_equal 'application/pdf', @response.media_type
439
    assert_match %r{\Aattachment}, @response.headers['Content-Disposition']
440
  end
441

  
442
  def test_download_pdf_file_with_inline_disposition_param_should_be_sent_inline
443
    @request.session[:user_id] = 2
444
    get(:download, :params => {:id => 23, :disposition => 'inline'})
445
    assert_response :success
439 446
    assert_equal 'application/pdf', @response.media_type
440 447
    assert_match %r{\Ainline}, @response.headers['Content-Disposition']
441 448
  end
449
  def test_download_non_pdf_file_with_inline_disposition_param_should_be_sent_as_a_download
450
    get(:download, :params => {:id => 4, :disposition => 'inline'})
451
    assert_response :success
452
    assert_match %r{\Aattachment}, @response.headers['Content-Disposition']
453
  end
454

  
442 455
  def test_download_version_file_with_issue_tracking_disabled
443 456
    Project.find(1).disable_module! :issue_tracking
444 457
    get(:download, :params => {:id => 9})
(3-3/3)