##// END OF EJS Templates
Non-ascii attachement filename fix for IE....
Jean-Philippe Lang -
r1039:941f9bf3dd3b
parent child
Show More
@@ -1,199 +1,204
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class ApplicationController < ActionController::Base
19 19 before_filter :user_setup, :check_if_login_required, :set_localization
20 20 filter_parameter_logging :password
21 21
22 22 REDMINE_SUPPORTED_SCM.each do |scm|
23 23 require_dependency "repository/#{scm.underscore}"
24 24 end
25 25
26 26 def current_role
27 27 @current_role ||= User.current.role_for_project(@project)
28 28 end
29 29
30 30 def user_setup
31 31 # Check the settings cache for each request
32 32 Setting.check_cache
33 33 # Find the current user
34 34 User.current = find_current_user
35 35 end
36 36
37 37 # Returns the current user or nil if no user is logged in
38 38 def find_current_user
39 39 if session[:user_id]
40 40 # existing session
41 41 (User.find_active(session[:user_id]) rescue nil)
42 42 elsif cookies[:autologin] && Setting.autologin?
43 43 # auto-login feature
44 44 User.find_by_autologin_key(cookies[:autologin])
45 45 elsif params[:key] && accept_key_auth_actions.include?(params[:action])
46 46 # RSS key authentication
47 47 User.find_by_rss_key(params[:key])
48 48 end
49 49 end
50 50
51 51 # check if login is globally required to access the application
52 52 def check_if_login_required
53 53 # no check needed if user is already logged in
54 54 return true if User.current.logged?
55 55 require_login if Setting.login_required?
56 56 end
57 57
58 58 def set_localization
59 59 lang = begin
60 60 if !User.current.language.blank? and GLoc.valid_languages.include? User.current.language.to_sym
61 61 User.current.language
62 62 elsif request.env['HTTP_ACCEPT_LANGUAGE']
63 63 accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.split('-').first
64 64 if accept_lang and !accept_lang.empty? and GLoc.valid_languages.include? accept_lang.to_sym
65 65 accept_lang
66 66 end
67 67 end
68 68 rescue
69 69 nil
70 70 end || Setting.default_language
71 71 set_language_if_valid(lang)
72 72 end
73 73
74 74 def require_login
75 75 if !User.current.logged?
76 76 store_location
77 77 redirect_to :controller => "account", :action => "login"
78 78 return false
79 79 end
80 80 true
81 81 end
82 82
83 83 def require_admin
84 84 return unless require_login
85 85 if !User.current.admin?
86 86 render_403
87 87 return false
88 88 end
89 89 true
90 90 end
91 91
92 92 # Authorize the user for the requested action
93 93 def authorize(ctrl = params[:controller], action = params[:action])
94 94 allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project)
95 95 allowed ? true : (User.current.logged? ? render_403 : require_login)
96 96 end
97 97
98 98 # make sure that the user is a member of the project (or admin) if project is private
99 99 # used as a before_filter for actions that do not require any particular permission on the project
100 100 def check_project_privacy
101 101 unless @project.active?
102 102 @project = nil
103 103 render_404
104 104 return false
105 105 end
106 106 return true if @project.is_public? || User.current.member_of?(@project) || User.current.admin?
107 107 User.current.logged? ? render_403 : require_login
108 108 end
109 109
110 110 # store current uri in session.
111 111 # return to this location by calling redirect_back_or_default
112 112 def store_location
113 113 session[:return_to_params] = params
114 114 end
115 115
116 116 # move to the last store_location call or to the passed default one
117 117 def redirect_back_or_default(default)
118 118 if session[:return_to_params].nil?
119 119 redirect_to default
120 120 else
121 121 redirect_to session[:return_to_params]
122 122 session[:return_to_params] = nil
123 123 end
124 124 end
125 125
126 126 def render_403
127 127 @project = nil
128 128 render :template => "common/403", :layout => !request.xhr?, :status => 403
129 129 return false
130 130 end
131 131
132 132 def render_404
133 133 render :template => "common/404", :layout => !request.xhr?, :status => 404
134 134 return false
135 135 end
136 136
137 137 def render_feed(items, options={})
138 138 @items = items || []
139 139 @items.sort! {|x,y| y.event_datetime <=> x.event_datetime }
140 140 @title = options[:title] || Setting.app_title
141 141 render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml'
142 142 end
143 143
144 144 def self.accept_key_auth(*actions)
145 145 actions = actions.flatten.map(&:to_s)
146 146 write_inheritable_attribute('accept_key_auth_actions', actions)
147 147 end
148 148
149 149 def accept_key_auth_actions
150 150 self.class.read_inheritable_attribute('accept_key_auth_actions') || []
151 151 end
152 152
153 153 # TODO: move to model
154 154 def attach_files(obj, files)
155 155 attachments = []
156 156 if files && files.is_a?(Array)
157 157 files.each do |file|
158 158 next unless file.size > 0
159 159 a = Attachment.create(:container => obj, :file => file, :author => User.current)
160 160 attachments << a unless a.new_record?
161 161 end
162 162 end
163 163 attachments
164 164 end
165 165
166 166 # Returns the number of objects that should be displayed
167 167 # on the paginated list
168 168 def per_page_option
169 169 per_page = nil
170 170 if params[:per_page] && Setting.per_page_options_array.include?(params[:per_page].to_s.to_i)
171 171 per_page = params[:per_page].to_s.to_i
172 172 session[:per_page] = per_page
173 173 elsif session[:per_page]
174 174 per_page = session[:per_page]
175 175 else
176 176 per_page = Setting.per_page_options_array.first || 25
177 177 end
178 178 per_page
179 179 end
180 180
181 181 # qvalues http header parser
182 182 # code taken from webrick
183 183 def parse_qvalues(value)
184 184 tmp = []
185 185 if value
186 186 parts = value.split(/,\s*/)
187 187 parts.each {|part|
188 188 if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
189 189 val = m[1]
190 190 q = (m[2] or 1).to_f
191 191 tmp.push([val, q])
192 192 end
193 193 }
194 194 tmp = tmp.sort_by{|val, q| -q}
195 195 tmp.collect!{|val, q| val}
196 196 end
197 197 return tmp
198 198 end
199
200 # Returns a string that can be used as filename value in Content-Disposition header
201 def filename_for_content_disposition(name)
202 request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name
203 end
199 204 end
@@ -1,39 +1,39
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class AttachmentsController < ApplicationController
19 19 layout 'base'
20 20 before_filter :find_project, :check_project_privacy
21 21
22 22 def download
23 23 # images are sent inline
24 send_file @attachment.diskfile, :filename => @attachment.filename,
24 send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
25 25 :type => @attachment.content_type,
26 26 :disposition => (@attachment.image? ? 'inline' : 'attachment')
27 27 rescue
28 28 # in case the disk file was deleted
29 29 render_404
30 30 end
31 31
32 32 private
33 33 def find_project
34 34 @attachment = Attachment.find(params[:id])
35 35 @project = @attachment.project
36 36 rescue
37 37 render_404
38 38 end
39 39 end
@@ -1,99 +1,100
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class DocumentsController < ApplicationController
19 19 layout 'base'
20 20 before_filter :find_project, :only => [:index, :new]
21 21 before_filter :find_document, :except => [:index, :new]
22 22 before_filter :authorize
23 23
24 24 def index
25 25 @sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category'
26 26 documents = @project.documents.find :all, :include => [:attachments, :category]
27 27 case @sort_by
28 28 when 'date'
29 29 @grouped = documents.group_by {|d| d.created_on.to_date }
30 30 when 'title'
31 31 @grouped = documents.group_by {|d| d.title.first.upcase}
32 32 when 'author'
33 33 @grouped = documents.select{|d| d.attachments.any?}.group_by {|d| d.attachments.last.author}
34 34 else
35 35 @grouped = documents.group_by(&:category)
36 36 end
37 37 render :layout => false if request.xhr?
38 38 end
39 39
40 40 def show
41 41 @attachments = @document.attachments.find(:all, :order => "created_on DESC")
42 42 end
43 43
44 44 def new
45 45 @document = @project.documents.build(params[:document])
46 46 if request.post? and @document.save
47 47 attach_files(@document, params[:attachments])
48 48 flash[:notice] = l(:notice_successful_create)
49 49 Mailer.deliver_document_added(@document) if Setting.notified_events.include?('document_added')
50 50 redirect_to :action => 'index', :project_id => @project
51 51 end
52 52 end
53 53
54 54 def edit
55 55 @categories = Enumeration::get_values('DCAT')
56 56 if request.post? and @document.update_attributes(params[:document])
57 57 flash[:notice] = l(:notice_successful_update)
58 58 redirect_to :action => 'show', :id => @document
59 59 end
60 60 end
61 61
62 62 def destroy
63 63 @document.destroy
64 64 redirect_to :controller => 'documents', :action => 'index', :project_id => @project
65 65 end
66 66
67 67 def download
68 68 @attachment = @document.attachments.find(params[:attachment_id])
69 69 @attachment.increment_download
70 send_file @attachment.diskfile, :filename => @attachment.filename, :type => @attachment.content_type
70 send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
71 :type => @attachment.content_type
71 72 rescue
72 73 render_404
73 74 end
74 75
75 76 def add_attachment
76 77 attachments = attach_files(@document, params[:attachments])
77 78 Mailer.deliver_attachments_added(attachments) if !attachments.empty? && Setting.notified_events.include?('document_added')
78 79 redirect_to :action => 'show', :id => @document
79 80 end
80 81
81 82 def destroy_attachment
82 83 @document.attachments.find(params[:attachment_id]).destroy
83 84 redirect_to :action => 'show', :id => @document
84 85 end
85 86
86 87 private
87 88 def find_project
88 89 @project = Project.find(params[:project_id])
89 90 rescue ActiveRecord::RecordNotFound
90 91 render_404
91 92 end
92 93
93 94 def find_document
94 95 @document = Document.find(params[:id])
95 96 @project = @document.project
96 97 rescue ActiveRecord::RecordNotFound
97 98 render_404
98 99 end
99 100 end
@@ -1,70 +1,71
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class VersionsController < ApplicationController
19 19 layout 'base'
20 20 before_filter :find_project, :authorize
21 21
22 22 cache_sweeper :version_sweeper, :only => [ :edit, :destroy ]
23 23
24 24 def show
25 25 end
26 26
27 27 def edit
28 28 if request.post? and @version.update_attributes(params[:version])
29 29 flash[:notice] = l(:notice_successful_update)
30 30 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
31 31 end
32 32 end
33 33
34 34 def destroy
35 35 @version.destroy
36 36 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
37 37 rescue
38 38 flash[:error] = "Unable to delete version"
39 39 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
40 40 end
41 41
42 42 def download
43 43 @attachment = @version.attachments.find(params[:attachment_id])
44 44 @attachment.increment_download
45 send_file @attachment.diskfile, :filename => @attachment.filename, :type => @attachment.content_type
45 send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
46 :type => @attachment.content_type
46 47 rescue
47 48 render_404
48 49 end
49 50
50 51 def destroy_file
51 52 @version.attachments.find(params[:attachment_id]).destroy
52 53 flash[:notice] = l(:notice_successful_delete)
53 54 redirect_to :controller => 'projects', :action => 'list_files', :id => @project
54 55 end
55 56
56 57 def status_by
57 58 respond_to do |format|
58 59 format.html { render :action => 'show' }
59 60 format.js { render(:update) {|page| page.replace_html 'status_by', render_issue_status_by(@version, params[:status_by])} }
60 61 end
61 62 end
62 63
63 64 private
64 65 def find_project
65 66 @version = Version.find(params[:id])
66 67 @project = @version.project
67 68 rescue ActiveRecord::RecordNotFound
68 69 render_404
69 70 end
70 71 end
General Comments 0
You need to be logged in to leave comments. Login now