socialforge/app/controllers/attachments_controller.rb

674 lines
25 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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")
# 如果附件描述被修改,则保存附件
unless params[:description] == @attachment.description
@old_attachment.description = params[:description]
end
@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 == 'Syllabus' || @attachment.container_type == 'Bid' || @attachment.container_type == 'Organization' || @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 == "Organization").nil?
unless (@attachment && @attachment.container_type == "PhoneAppVersion").nil?
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
end