From 80a7486f95a39ad3fc0946fad17fe51cff01cec6 Mon Sep 17 00:00:00 2001
From: Jean-Philippe Lang <jp_lang@yahoo.fr>
Date: Mon, 9 Jun 2008 18:40:59 +0000
Subject: [PATCH] File viewer for attached text files.

git-svn-id: http://redmine.rubyforge.org/svn/trunk@1520 e93f8b46-1217-0410-a6f0-8f06a7374b81
---
 app/controllers/attachments_controller.rb     |  11 ++--
 app/helpers/application_helper.rb             |   8 +++
 app/helpers/repositories_helper.rb            |   7 ---
 app/models/attachment.rb                      |   4 ++
 app/views/attachments/file.rhtml              |  15 +++++
 test/fixtures/attachments.yml                 |  38 ++++++++++-
 test/fixtures/files/060719210727_archive.zip  | Bin 0 -> 157 bytes
 .../files/060719210727_changeset.diff         |  13 ++++
 test/fixtures/files/060719210727_source.rb    |  10 +++
 .../functional/attachments_controller_test.rb |  59 ++++++++++++++++++
 test/functional/documents_controller_test.rb  |   2 +
 test/functional/issues_controller_test.rb     |   2 +
 test/integration/issues_test.rb               |  18 ++++++
 test/test_helper.rb                           |   6 ++
 14 files changed, 181 insertions(+), 12 deletions(-)
 create mode 100644 app/views/attachments/file.rhtml
 create mode 100644 test/fixtures/files/060719210727_archive.zip
 create mode 100644 test/fixtures/files/060719210727_changeset.diff
 create mode 100644 test/fixtures/files/060719210727_source.rb
 create mode 100644 test/functional/attachments_controller_test.rb

diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb
index cfc15669f..9ea9ac48e 100644
--- a/app/controllers/attachments_controller.rb
+++ b/app/controllers/attachments_controller.rb
@@ -23,7 +23,10 @@ class AttachmentsController < ApplicationController
     if @attachment.is_diff?
       @diff = File.new(@attachment.diskfile, "rb").read
       render :action => 'diff'
-    else
+    elsif @attachment.is_text?
+      @content = File.new(@attachment.diskfile, "rb").read
+      render :action => 'file'
+    elsif
       download
     end
   end
@@ -38,9 +41,9 @@ class AttachmentsController < ApplicationController
 private
   def find_project
     @attachment = Attachment.find(params[:id])
-    render_404 and return false unless File.readable?(@attachment.diskfile)
+    #render_404 and return false unless File.readable?(@attachment.diskfile)
     @project = @attachment.project
-  rescue
-    render_404
+  #rescue
+  #  render_404
   end
 end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 405c5bf44..16904c251 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -15,6 +15,9 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
+require 'coderay'
+require 'coderay/helpers/file_type'
+
 module ApplicationHelper
   include Redmine::WikiFormatting::Macros::Definitions
 
@@ -116,6 +119,11 @@ module ApplicationHelper
     l(:actionview_datehelper_select_month_names).split(',')[month-1]
   end
 
+  def syntax_highlight(name, content)
+    type = CodeRay::FileType[name]
+    type ? CodeRay.scan(content, type).html : h(content)
+  end
+  
   def pagination_links_full(paginator, count=nil, options={})
     page_param = options.delete(:page_param) || :page
     url_param = params.dup
diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb
index 10f6e7396..e94ae2e7f 100644
--- a/app/helpers/repositories_helper.rb
+++ b/app/helpers/repositories_helper.rb
@@ -15,16 +15,9 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-require 'coderay'
-require 'coderay/helpers/file_type'
 require 'iconv'
 
 module RepositoriesHelper
-  def syntax_highlight(name, content)
-    type = CodeRay::FileType[name]
-    type ? CodeRay.scan(content, type).html : h(content)
-  end
-  
   def format_revision(txt)
     txt.to_s[0,8]
   end
diff --git a/app/models/attachment.rb b/app/models/attachment.rb
index 95de4837a..7d6a74ebb 100644
--- a/app/models/attachment.rb
+++ b/app/models/attachment.rb
@@ -88,6 +88,10 @@ class Attachment < ActiveRecord::Base
     self.filename =~ /\.(jpe?g|gif|png)$/i
   end
   
+  def is_text?
+    Redmine::MimeType.is_type?('text', filename)
+  end
+  
   def is_diff?
     self.filename =~ /\.(patch|diff)$/i
   end
diff --git a/app/views/attachments/file.rhtml b/app/views/attachments/file.rhtml
new file mode 100644
index 000000000..7988d0aed
--- /dev/null
+++ b/app/views/attachments/file.rhtml
@@ -0,0 +1,15 @@
+<h2><%=h @attachment.filename %></h2>
+
+<div class="attachments">
+<p><%= h("#{@attachment.description} - ") unless @attachment.description.blank? %>
+   <span class="author"><%= @attachment.author %>, <%= format_time(@attachment.created_on) %></span></p>
+<p><%= link_to l(:button_download), {:controller => 'attachments', :action => 'download', :id => @attachment } -%>
+   <span class="size">(<%= number_to_human_size @attachment.filesize %>)</span></p>
+
+</div>
+&nbsp;
+<%= render :partial => 'common/file', :locals => {:content => @content, :filename => @attachment.filename} %>
+
+<% content_for :header_tags do -%>
+    <%= stylesheet_link_tag "scm" -%>
+<% end -%>
diff --git a/test/fixtures/attachments.yml b/test/fixtures/attachments.yml
index 162d44720..a73d6b385 100644
--- a/test/fixtures/attachments.yml
+++ b/test/fixtures/attachments.yml
@@ -36,4 +36,40 @@ attachments_003:
   filename: logo.gif
   description: This is a logo
   author_id: 2
-  
\ No newline at end of file
+attachments_004: 
+  created_on: 2006-07-19 21:07:27 +02:00
+  container_type: Issue
+  container_id: 3
+  downloads: 0
+  disk_filename: 060719210727_source.rb
+  digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
+  id: 4
+  filesize: 153
+  filename: source.rb
+  author_id: 2
+  description: This is a Ruby source file
+  content_type: application/x-ruby
+attachments_005: 
+  created_on: 2006-07-19 21:07:27 +02:00
+  container_type: Issue
+  container_id: 3
+  downloads: 0
+  disk_filename: 060719210727_changeset.diff
+  digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
+  id: 5
+  filesize: 687
+  filename: changeset.diff
+  author_id: 2
+  content_type: text/x-diff
+attachments_006: 
+  created_on: 2006-07-19 21:07:27 +02:00
+  container_type: Issue
+  container_id: 3
+  downloads: 0
+  disk_filename: 060719210727_archive.zip
+  digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
+  id: 6
+  filesize: 157
+  filename: archive.zip
+  author_id: 2
+  content_type: application/octet-stream
diff --git a/test/fixtures/files/060719210727_archive.zip b/test/fixtures/files/060719210727_archive.zip
new file mode 100644
index 0000000000000000000000000000000000000000..5467885d4b28eedd531d78c32380ffd3e69eded0
GIT binary patch
literal 157
zcmWIWW@Zs#U|`^2Fv$%vtB#e4Q3mo<fS3n}OHzwV(lT>W^-3yAv`?PU31e8~(mLr%
zmr(1LGjl>(xBO9Rz0@@4&k>OY35A}93<2JZOd<@pjRTs<z{sG$u&oiqLN+|Wo0SbB
N%gA5_WcY$O3;?$FB(nej

literal 0
HcmV?d00001

diff --git a/test/fixtures/files/060719210727_changeset.diff b/test/fixtures/files/060719210727_changeset.diff
new file mode 100644
index 000000000..af2c2068d
--- /dev/null
+++ b/test/fixtures/files/060719210727_changeset.diff
@@ -0,0 +1,13 @@
+Index: trunk/app/controllers/issues_controller.rb
+===================================================================
+--- trunk/app/controllers/issues_controller.rb	(r‚vision 1483)
++++ trunk/app/controllers/issues_controller.rb	(r‚vision 1484)
+@@ -149,7 +149,7 @@
+         attach_files(@issue, params[:attachments])
+         flash[:notice] = l(:notice_successful_create)
+         Mailer.deliver_issue_add(@issue) if Setting.notified_events.include?('issue_added')
+-        redirect_to :controller => 'issues', :action => 'show', :id => @issue,  :project_id => @project
++        redirect_to :controller => 'issues', :action => 'show', :id => @issue
+         return
+       end		
+     end	
diff --git a/test/fixtures/files/060719210727_source.rb b/test/fixtures/files/060719210727_source.rb
new file mode 100644
index 000000000..dccb59165
--- /dev/null
+++ b/test/fixtures/files/060719210727_source.rb
@@ -0,0 +1,10 @@
+# The Greeter class
+class Greeter
+  def initialize(name)
+    @name = name.capitalize
+  end
+
+  def salute
+    puts "Hello #{@name}!" 
+  end
+end
diff --git a/test/functional/attachments_controller_test.rb b/test/functional/attachments_controller_test.rb
new file mode 100644
index 000000000..d088c0b0f
--- /dev/null
+++ b/test/functional/attachments_controller_test.rb
@@ -0,0 +1,59 @@
+# redMine - project management software
+# Copyright (C) 2006-2008  Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+require File.dirname(__FILE__) + '/../test_helper'
+require 'attachments_controller'
+
+# Re-raise errors caught by the controller.
+class AttachmentsController; def rescue_action(e) raise e end; end
+
+
+class AttachmentsControllerTest < Test::Unit::TestCase
+  fixtures :users, :projects, :issues, :attachments
+  
+  def setup
+    @controller = AttachmentsController.new
+    @request    = ActionController::TestRequest.new
+    @response   = ActionController::TestResponse.new
+    Attachment.storage_path = "#{RAILS_ROOT}/test/fixtures/files"
+    User.current = nil
+  end
+  
+  def test_show_diff
+    get :show, :id => 5
+    assert_response :success
+    assert_template 'diff'
+  end
+  
+  def test_show_text_file
+    get :show, :id => 4
+    assert_response :success
+    assert_template 'file'
+  end
+  
+  def test_show_other
+    get :show, :id => 6
+    assert_response :success
+    assert_equal 'application/octet-stream', @response.content_type
+  end
+  
+  def test_download_text_file
+    get :download, :id => 4
+    assert_response :success
+    assert_equal 'application/x-ruby', @response.content_type
+  end
+end
diff --git a/test/functional/documents_controller_test.rb b/test/functional/documents_controller_test.rb
index f150a5b7a..7c1f0213a 100644
--- a/test/functional/documents_controller_test.rb
+++ b/test/functional/documents_controller_test.rb
@@ -40,6 +40,8 @@ class DocumentsControllerTest < Test::Unit::TestCase
   
   def test_new_with_one_attachment
     @request.session[:user_id] = 2
+    set_tmp_attachments_directory
+    
     post :new, :project_id => 'ecookbook',
                :document => { :title => 'DocumentsControllerTest#test_post_new',
                               :description => 'This is a new document',
diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb
index 582c27d9b..32d2a7f41 100644
--- a/test/functional/issues_controller_test.rb
+++ b/test/functional/issues_controller_test.rb
@@ -361,6 +361,8 @@ class IssuesControllerTest < Test::Unit::TestCase
   end
   
   def test_post_edit_with_attachment_only
+    set_tmp_attachments_directory
+    
     # anonymous user
     post :edit,
          :id => 1,
diff --git a/test/integration/issues_test.rb b/test/integration/issues_test.rb
index b9e21719c..1b57ba8f8 100644
--- a/test/integration/issues_test.rb
+++ b/test/integration/issues_test.rb
@@ -1,3 +1,20 @@
+# redMine - project management software
+# Copyright (C) 2006-2008  Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
 require "#{File.dirname(__FILE__)}/../test_helper"
 
 class IssuesTest < ActionController::IntegrationTest
@@ -47,6 +64,7 @@ class IssuesTest < ActionController::IntegrationTest
   # add then remove 2 attachments to an issue
   def test_issue_attachements
     log_user('jsmith', 'jsmith')
+    set_tmp_attachments_directory
 
     post 'issues/edit/1',
          :notes => 'Some notes',
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 61670318a..150b063e8 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -57,6 +57,12 @@ class Test::Unit::TestCase
   def test_uploaded_file(name, mime)
     ActionController::TestUploadedFile.new(Test::Unit::TestCase.fixture_path + "/files/#{name}", mime)
   end
+  
+  # Use a temporary directory for attachment related tests
+  def set_tmp_attachments_directory
+    Dir.mkdir "#{RAILS_ROOT}/tmp/test/attachments" unless File.directory?("#{RAILS_ROOT}/tmp/test/attachments")
+    Attachment.storage_path = "#{RAILS_ROOT}/tmp/test/attachments"
+  end
 end
 
 
-- 
GitLab