|
- # Redmine - project management software
- # Copyright (C) 2006-2013 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.
-
- class AttachmentsController < ApplicationController
- layout "users_base"
-
- before_filter :find_project, :only => [:show, :download, :thumbnail, :destroy, :delete_homework]#, :except => [:upload, :autocomplete]
- before_filter :file_readable, :read_authorize, :only => [:show, :thumbnail]#Modified by young
- before_filter :delete_authorize, :only => [:destroy]
- before_filter :authorize_global, :only => [:upload]
- before_filter :authorize_attachment_download1, :only => [:download]
- before_filter :has_login
- #before_filter :login_without_softapplication, only: [:download]
- accept_api_auth :show, :download, :upload
- require 'iconv'
- include AttachmentsHelper
- include ApplicationHelper
-
- def show
- respond_to do |format|
- format.html {
- if @attachment.is_diff?
- @diff = File.new(@attachment.diskfile, "rb").read
- @diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
- @diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
- # Save diff type as user preference
- if User.current.logged? && @diff_type != User.current.pref[:diff_type]
- User.current.pref[:diff_type] = @diff_type
- User.current.preference.save
- end
- render :action => 'diff'
- elsif @attachment.is_text? && @attachment.filesize <= Setting.file_max_size_displayed.to_i.kilobyte
- @content = File.new(@attachment.diskfile, "rb").read
- # 编码为非 UTF-8先进行间接转码
- # 部分unicode编码不直接支持转为 UTF-8
- # modify by nwb
- if @content.encoding.name != 'UTF-8'
- @content = @content.force_encoding('GBK')
- @content = @content.encode('UTF-8')
- end
- render :action => 'file'
- else
- download
- end
- }
- format.api
- end
- rescue Encoding::InvalidByteSequenceError => e
- render :action => 'file'
- end
-
- def pdf?(file)
- file.downcase.end_with?(".pdf")
- end
-
- def direct_download
- @attachment.increment_download
- send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
- :type => detect_content_type(@attachment),
- :disposition => 'attachment' #inline can open in browser
- end
-
- def direct_download_history
- @attachment_history = AttachmentHistory.find(params[:id])
- @attachment_history.increment_download
- send_file @attachment_history.diskfile_history, :filename => filename_for_content_disposition(@attachment_history.filename),
- :type => detect_content_type(@attachment_history),
- :disposition => 'attachment' #inline can open in browser
- end
-
- def download_history
- @attachment_history = AttachmentHistory.find(params[:id])
- candown = attachment_history_candown @attachment_history
- if candown || User.current.admin? || User.current.id == @attachment_history.author_id
- if stale?(:etag => @attachment_history.digest)
- if params[:preview] == 'true'
- convered_file = @attachment_history.diskfile_history
- #如果本身不是pdf文件,则先寻找是不是已转换化,如果没有则转化
- unless pdf?(convered_file)
- convered_file = File.join(Rails.root, "files", "convered_office", @attachment.disk_filename + ".pdf")
- unless File.exist?(convered_file)
- office = Trustie::Utils::Office.new(@attachment_history.diskfile)
- office.conver(convered_file)
- end
- end
- if File.exist?(convered_file) && pdf?(convered_file)
- send_file convered_file, :type => 'application/pdf; charset=utf-8', :disposition => 'inline'
- else
- direct_download_history
- end
- else
- # 记录用户行为
- record_user_actions(params[:id])
- # 直接下载历史版本
- direct_download_history
- end
- end
- else
- render_403 :message => :notice_not_authorized
- end
- rescue => e
- redirect_to "http://" + (Setting.host_name.to_s) +"/file_not_found.html"
- end
-
- def record_user_actions id
- if params[:action] == "download_history"
- UserActions.create(:action_id => id, :action_type => "AttachmentHistory", :user_id => User.current.id) unless id.nil?
- elsif params[:action] == "download"
- UserActions.create(:action_id => id, :action_type => "Attachment", :user_id => User.current.id) unless id.nil?
- end
- end
-
- def download
- # modify by nwb
- # 下载添加权限设置
- candown = attachment_candown @attachment
- if candown || User.current.admin? || User.current.id == @attachment.author_id
- if stale?(:etag => @attachment.digest)
- if params[:preview] == 'true'
- convered_file = @attachment.diskfile
- #如果本身不是pdf文件,则先寻找是不是已转换化,如果没有则转化
- unless pdf?(convered_file)
- convered_file = File.join(Rails.root, "files", "convered_office", @attachment.disk_filename + ".pdf")
- unless File.exist?(convered_file)
- office = Trustie::Utils::Office.new(@attachment.diskfile)
- office.conver(convered_file)
- end
- end
- if File.exist?(convered_file) && pdf?(convered_file)
- send_file convered_file, :type => 'application/pdf; charset=utf-8', :disposition => 'inline'
- else
- direct_download
- end
- else
- # 记录用户行为
- record_user_actions(params[:id])
- direct_download
- end
- end
- else
- render_403 :message => :notice_not_authorized
- end
- rescue => e
- redirect_to "http://" + (Setting.host_name.to_s) +"/file_not_found.html"
- end
-
- #更新资源文件类型
- def updateType
- @attachment = Attachment.find(params[:attachmentid])
- if @attachment != nil
- @attachment.attachtype = params[:newtype]
- @attachment.save
- render :text =>'success'
- else
- render :text=>'error'
- end
- end
-
- # 更新文件密级
- def updateFileDense
- @attachment = Attachment.find(params[:attachmentid])
- if @attachment != nil
- filedense = params[:newtype].to_s
- # d = Iconv.conv("unicodebig","utf-8",filedense)
- if filedense == "%E5%85%AC%E5%BC%80" #l(:field_is_public)
- @attachment.is_public = 1
- else
- @attachment.is_public = 0
- end
- @attachment.save
- @newfiledense = filedense
- end
- respond_to do |format|
- format.js
- end
- end
-
- def update_file_dense
- @attachment = Attachment.find(params[:attachmentid])
- if @attachment != nil
- filedense = params[:newtype].to_s
- if filedense == "1"
- @attachment.is_public = 1
- else
- @attachment.is_public = 0
- end
- @attachment.save
- @newfiledense = filedense
- end
- respond_to do |format|
- format.js
- end
- end
-
- def thumbnail
- if @attachment.thumbnailable? && thumbnail = @attachment.thumbnail(:size => params[:size])
- if stale?(:etag => thumbnail)
- send_file thumbnail,
- :filename => filename_for_content_disposition(@attachment.filename),
- :type => detect_content_type(@attachment),
- :disposition => 'inline'
- end
- else
- # No thumbnail for the attachment or thumbnail could not be created
- render :nothing => true, :status => 404
- end
- end
-
-
- def upload
- # Make sure that API users get used to set this content type
- # as it won't trigger Rails' automatic parsing of the request body for parameters
- unless request.content_type == 'application/octet-stream'
- render :nothing => true, :status => 406
- return
- end
-
- @attachment = Attachment.new(:file => request.raw_post)
- @attachment.author = User.current
- if !params[:project].nil?
- @attachment.container_type = 'Project'
- @attachment.container_id = params[:project].split("?")[0]
- end
- @attachment.filename = params[:filename].presence || Redmine::Utils.random_hex(16)
- saved = @attachment.save
- respond_to do |format|
- format.js
- format.api {
- if saved
- render :action => 'upload', :status => :created
- else
- render_validation_errors(@attachment)
- end
- }
- end
- end
-
- def upload_attachment_version
- @flag = false
- Attachment.transaction do
- @old_attachment = Attachment.find params[:old_attachment_id]
- #取出当前上传的文件
- @attachment = Attachment.find(params[:attachments ].first[1][:attachment_id])
- #将需要修改的记录保存到历史记录
- @history = AttachmentHistory.new
- @history.attributes = @old_attachment.attributes.dup.except("id")
- @history.attachment_id = params[:old_attachment_id]
- #需要更新版本号,需要拿到原来该文件最大的历史版本号
- @old_history = @old_attachment.attachment_histories.reorder('version desc').first
- @history.version = @old_history.nil? ? 1 : @old_history.version + 1
- @history.save #历史记录保存完毕
- #将最新保存的记录 数据替换到 需要修改的文件记录
- @old_attachment.attributes = @attachment.attributes.dup.except("id","container_id","container_type","is_public","downloads", "quotes")
- @old_attachment.save
- #删除当前记录
- @attachment.delete
- @flag = true
- end
-
- respond_to do |format|
- format.js
- end
- end
-
- def destroy
- if @attachment.container.respond_to?(:init_journal)
- @attachment.container.init_journal(User.current)
- end
- if @attachment.container
- if @attachment.container_type == "Issue"
- @attachment.destroy
- else
- @attachment.container.attachments.delete(@attachment)
- end
- else
- @attachment.destroy
- end
-
- respond_to do |format|
- if !@attachment.container.nil? &&
- (@attachment.container.is_a?(Course) || ((@attachment.container.has_attribute?(:course) || @attachment.container.has_attribute?(:course_id) ) &&
- @attachment.container.course ) || ((@attachment.container.has_attribute?(:board) || @attachment.container.has_attribute?(:board_id)) &&
- @attachment.container.board && @attachment.container.board.course ) || @attachment.container.is_a?(StudentWorksScore) || @attachment.container.is_a?(HomeworkCommon) ||
- @attachment.container.is_a?(StudentWork))
- if @attachment.container.is_a?(News)
- format.html { redirect_to_referer_or news_path(@attachment.container) }
- elsif @attachment.container.is_a?(StudentWorksScore)
- @is_destroy = true unless params[:attachment_id] #根据ID删除页面对应的数据,js刷新页面
- format.js
- elsif @attachment.container.is_a?(HomeworkCommon)
- @is_destroy = true unless params[:attachment_id] #根据ID删除页面对应的数据,js刷新页面
- format.js
- elsif @attachment.container.is_a?(StudentWork)
- @is_destroy = true unless params[:attachment_id] #根据ID删除页面对应的数据,js刷新页面
- format.js
- elsif @attachment.container.is_a?(Message)
- format.html { redirect_to_referer_or new_board_message_path(@attachment.container) }
- elsif @attachment.container.is_a?(BlogComment)
- format.html { redirect_to_referer_or user_blog_blog_comment_path(:user_id=>@attachment.container.author.id,:blog_id=>@attachment.container.blog_id,:id=>@attachment.container.id)}
- elsif @course.nil?
- format.html { redirect_to_referer_or forum_memo_path(@attachment.container.forum, @attachment.container) }
- else
- format.html { redirect_to_referer_or course_path(@course) }
- end
- elsif !@attachment.container.nil? && @attachment.container.is_a?(Softapplication)
- format.html { redirect_to_referer_or softapplications_path(@attachment.container) }
- elsif !@attachment.container.nil? && @attachment.container.is_a?(Bid)
- format.html { redirect_to_referer_or respond_path(@attachment.container) }
- elsif !@attachment.container.nil? && @attachment.container.is_a?(PhoneAppVersion)
- format.html { redirect_to_referer_or mobile_version_path }
- elsif !@attachment.container.nil? && @attachment.container.is_a?(OrgSubfield)
- format.html {redirect_to_referer_or org_subfield_files_path(@attachment.container)}
- elsif !@attachment.container.nil? && @attachment.container.is_a?(OrgDocumentComment)
- format.html {redirect_to_referer_or org_document_comment_path(@attachment.container)}
- else
- if @project.nil?
- format.html { redirect_to_referer_or forum_memo_path(@attachment.container.forum, @attachment.container) }
- else
- format.html { redirect_to_referer_or project_path(@project) }
- end
- end
-
- format.js
- end
- end
-
- def delete_homework
- @bid = @attachment.container.bid
- # Make sure association callbacks are called
- container = @attachment.container
- @attachment.container.attachments.delete(@attachment)
- #if container.attachments.empty?
- #container.delete
- #end
-
- respond_to do |format|
- format.html { redirect_to_referer_or respond_path(@bid) }
- format.js
- end
- end
-
- #删除竞赛作品的附件
- def delete_softapplications
- @attachment = Attachment.find params[:id]
- @softapplication = @attachment.container if @attachment!=nil
- @attachment.container.attachments.delete(@attachment) if @attachment!=nil
- respond_to do |format|
- format.html { redirect_to_referer_or edit_softapplication_path(@softapplication) }
- #format.js
- end
- end
-
- def autocomplete
- # modify by nwb
- if params[:project_id]
- @project = Project.find_by_id(params[:project_id])
- elsif params[:course_id]
- @course = Course.find_by_id(params[:course_id])
- end
-
- respond_to do |format|
- format.js
- end
- end
-
- def add_exist_file_to_project
- classname = params[:class_name]
- class_id = params[:class_id]
- attachments = params[:attachment][:attach]
-
- obj = Object.const_get(classname).find_by_id(class_id)
- attachments.collect do |attach_id|
- ori = Attachment.find_by_id(attach_id)
- next if ori.blank?
- attach_copied_obj = ori.copy
- attach_copied_obj.tag_list.add(ori.tag_list) # tag关联
- attach_copied_obj.container = obj
- attach_copied_obj.created_on = Time.now
- attach_copied_obj.author_id = User.current.id
- if attach_copied_obj.attachtype == nil
- attach_copied_obj.attachtype = 1
- end
- @obj = obj
- @save_flag = attach_copied_obj.save
- @save_message = attach_copied_obj.errors.full_messages
- end
-
- respond_to do |format|
- format.js
- end
- rescue NoMethodError
- @save_flag = false
- @save_message = [] << l(:error_attachment_empty)
- respond_to do |format|
- format.js
- end
- end
-
- def add_exist_file_to_course
- class_id = params[:class_id]
- attachments = params[:attachment][:attach]
-
- obj = Course.find_by_id(class_id)
- attachments.collect do |attach_id|
- ori = Attachment.find_by_id(attach_id)
- next if ori.blank?
- attach_copied_obj = ori.copy
- attach_copied_obj.tag_list.add(ori.tag_list) # tag关联
- attach_copied_obj.container = obj
- attach_copied_obj.created_on = Time.now
- attach_copied_obj.author_id = User.current.id
- if attach_copied_obj.attachtype == nil
- attach_copied_obj.attachtype = 4
- end
- @obj = obj
- @save_flag = attach_copied_obj.save
- @save_message = attach_copied_obj.errors.full_messages
- end
-
- respond_to do |format|
- format.js
- end
- rescue NoMethodError
- @save_flag = false
- @save_message = [] << l(:error_attachment_empty)
- respond_to do |format|
- format.js
- end
- end
-
- def add_exist_file_to_projects
- file = Attachment.find(params[:file_id])
- projects = params[:projects][:project]
- @message = ""
- projects.each do |project|
- c = Project.find(project);
- if project_contains_attachment?(c,file)
- if @message && @message == ""
- @message += l(:label_project_prompt) + c.name + l(:label_contain_resource) + file.filename + l(:label_quote_resource_failed)
- next
- else
- @message += "<br/>" + l(:label_project_prompt) + c.name + l(:label_contain_resource) + file.filename + l(:label_quote_resource_failed)
- next
- end
- end
- attach_copied_obj = file.copy
- attach_copied_obj.tag_list.add(file.tag_list) # tag关联
- attach_copied_obj.container = c
- attach_copied_obj.created_on = Time.now
- attach_copied_obj.author_id = User.current.id
- attach_copied_obj.copy_from = file.copy_from.nil? ? file.id : file.copy_from
- if attach_copied_obj.attachtype == nil
- attach_copied_obj.attachtype = 4
- end
- @obj = c
- @save_flag = attach_copied_obj.save
- @save_message = attach_copied_obj.errors.full_messages
- update_quotes attach_copied_obj
- end
- respond_to do |format|
- format.js
- end
- rescue NoMethodError
- @save_flag = false
- @save_message = [] << l(:label_project_empty_select)
- respond_to do |format|
- format.js
- end
- end
-
- def add_exist_file_to_courses
- file = Attachment.find(params[:file_id])
- courses = params[:courses][:course]
- @message = ""
- courses.each do |course|
- c = Course.find(course);
- if course_contains_attachment?(c,file)
- if @message && @message == ""
- @message += l(:label_course_prompt) + c.name + l(:label_contain_resource) + file.filename + l(:label_quote_resource_failed)
- next
- else
- @message += "<br/>" + l(:label_course_prompt) + c.name + l(:label_contain_resource) + file.filename + l(:label_quote_resource_failed)
- next
- end
- end
- attach_copied_obj = file.copy
- attach_copied_obj.tag_list.add(file.tag_list) # tag关联
- attach_copied_obj.container = c
- attach_copied_obj.created_on = Time.now
- attach_copied_obj.author_id = User.current.id
- attach_copied_obj.copy_from = file.copy_from.nil? ? file.id : file.copy_from
- if attach_copied_obj.attachtype == nil
- attach_copied_obj.attachtype = 4
- end
- @obj = c
- @save_flag = attach_copied_obj.save
- @save_message = attach_copied_obj.errors.full_messages
- update_quotes attach_copied_obj
- end
- respond_to do |format|
- format.js
- end
- rescue NoMethodError
- @save_flag = false
- @save_message = [] << l(:label_course_empty_select)
- respond_to do |format|
- format.js
- end
- end
-
- def add_exist_file_to_org_subfield
- file = Attachment.find(params[:file_id])
- org_subfields = params[:org_subfields][:org_subfield]
- @message = ""
- org_subfields.each do |org_subfield|
- s = OrgSubfield.find(org_subfield)
- if s.attachments.include?file
- if @message && @message == ""
- @message += l(:label_resource_subfield_prompt) + c.name + l(:label_contain_resource) + file.filename + l(:label_quote_resource_failed)
- next
- else
- @message += "<br/>" + l(:label_resource_subfield_prompt) + c.name + l(:label_contain_resource) + file.filename + l(:label_quote_resource_failed)
- next
- end
- end
- attach_copied_obj = file.copy
- attach_copied_obj.tag_list.add(file.tag_list) # tag关联
- attach_copied_obj.container = s
- attach_copied_obj.created_on = Time.now
- attach_copied_obj.author_id = User.current.id
- attach_copied_obj.copy_from = file.copy_from.nil? ? file.id : file.copy_from
- if attach_copied_obj.attachtype == nil
- attach_copied_obj.attachtype = 4
- end
- @obj = s
- @save_flag = attach_copied_obj.save
- @save_message = attach_copied_obj.errors.full_messages
- update_quotes attach_copied_obj
- end
- respond_to do |format|
- format.js
- end
- rescue NoMethodError
- @save_flag = false
- @save_message = [] << l(:label_resource_subfield_empty_select)
- respond_to do |format|
- format.js
- end
- end
-
- def update_quotes attachment
- if attachment.copy_from
- attachments = Attachment.find_by_sql("select * from attachments where copy_from = #{attachment.copy_from} or id = #{attachment.copy_from}")
- else
- attachments = Attachment.find_by_sql("select * from attachments where copy_from = #{attachment.id} or id = #{attachment.copy_from}")
- end
- attachment.quotes = get_qute_number attachment
- attachment.save
- attachments.each do |att|
- att.quotes = attachment.quotes
- att.save
- end
- end
-
- #找到文件的所有的历史版本
- def attachment_versions
- @attachment = Attachment.find(params[:id])
- @attachment_histories = @attachment.attachment_histories
- respond_to do |format|
- format.js
- end
- end
-
- #找到文件的所有的历史版本及当前版本
- def attachment_history_download
- @attachment = Attachment.find(params[:id])
- @attachment_histories = @attachment.attachment_histories
- respond_to do |format|
- format.js
- end
- end
-
- private
- def find_project
- @attachment = Attachment.find(params[:id])
- # Show 404 if the filename in the url is wrong
- # modify by nwb
- raise ActiveRecord::RecordNotFound if params[:filename] && params[:filename] != @attachment.filename
- if @attachment.container_type == 'Course'
- @course = @attachment.course
- elsif !@attachment.container.nil? && (@attachment.container.has_attribute?(:course) || @attachment.container.has_attribute?(:course_id)) && @attachment.container.course
- @course = @attachment.container.course
- elsif !@attachment.container.nil? && ((@attachment.container.has_attribute?(:board) || @attachment.container.has_attribute?(:board_id)) && @attachment.container.board &&
- @attachment.container.board.course)
- @course = @attachment.container.board.course
- else
- unless @attachment.container_type == 'Bid' || @attachment.container_type == 'HomeworkAttach' || @attachment.container_type == 'Memo' || @attachment.container_type == 'Softapplication' || @attachment.container_type == 'PhoneAppVersion' || @attachment.container_type == 'StudentWorksScore'|| @attachment.container_type == 'StudentWork'
- @project = @attachment.project
- end
- end
- rescue ActiveRecord::RecordNotFound
- render_404
- end
-
- # Checks that the file exists and is readable
- def file_readable
- if @attachment.readable?
- true
- else
- logger.error "Cannot send attachment, #{@attachment.diskfile} does not exist or is unreadable."
- render_404
- end
- end
-
- def read_authorize
- if @attachment.container_type == "HomeworkAttach" || @attachment.container_type == 'Bid'
- true
- #User.current.allowed_to?(:view_homework_attaches, @attachment.project) ? true : deny_access
- else
- @attachment.visible? ? true : deny_access
- end
- end
-
- def delete_authorize
- @attachment.deletable? ? true : deny_access
- end
-
- def detect_content_type(attachment)
- content_type = attachment.content_type
- if content_type.blank?
- content_type = Redmine::MimeType.of(attachment.filename)
- end
- content_type.to_s
- end
-
- def login_without_softapplication
- referer = request.headers['Referer']
- require_login unless referer =~ /softapplication/ || @attachment.container_type == "Memo"
- end
-
- def renderTag
- @attachmentNew = Attachment.find(params[:attchmentId])
- respond_to do |format|
- format.js
- end
- end
-
- def has_login
- unless @attachment && @attachment.container_type == "PhoneAppVersion"
- render_403 if !User.current.logged? && !(@attachment.container_type == 'OrgSubfield' && @attachment.container.organization.allow_guest_download) && !(@attachment.container_type == 'OrgDocumentComment' && @attachment.container.organization.allow_guest_download)
- end
- end
- end
|