- Added support for attachments referencing
- Added stderr capturing for better error reports - Added multiple commands support - Added video macro filter based on flowplayer and ffmpeg
This commit is contained in:
parent
5ea4c736ed
commit
8cfa874772
|
@ -6,12 +6,14 @@ class WikiExternalFilterController < ApplicationController
|
|||
def filter
|
||||
name = params[:name]
|
||||
macro = params[:macro]
|
||||
index = params[:index].to_i
|
||||
filename = params[:filename] ? params[:filename] : name
|
||||
config = load_config
|
||||
cache_key = self.construct_cache_key(macro, name)
|
||||
content = read_fragment cache_key
|
||||
|
||||
if (content)
|
||||
send_data content, :type => config[macro]['content_type'], :disposition => 'inline'
|
||||
send_data content[index], :type => config[macro]['content_type'], :disposition => 'inline', :filename => filename
|
||||
else
|
||||
render_404
|
||||
end
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
require 'digest/sha2'
|
||||
require 'open4'
|
||||
|
||||
module WikiExternalFilterHelper
|
||||
|
||||
|
@ -24,7 +25,7 @@ module WikiExternalFilterHelper
|
|||
['wiki_external_filter', macro, name].join("/")
|
||||
end
|
||||
|
||||
def build(text, macro, info)
|
||||
def build(text, attachments, macro, info)
|
||||
|
||||
name = Digest::SHA256.hexdigest(text)
|
||||
result = {}
|
||||
|
@ -49,14 +50,14 @@ module WikiExternalFilterHelper
|
|||
result[:content_type] = info['content_type']
|
||||
RAILS_DEFAULT_LOGGER.debug "from cache: #{name}"
|
||||
else
|
||||
result = self.build_forced(text, info)
|
||||
result = self.build_forced(text, attachments, info)
|
||||
if result[:status]
|
||||
if expires > 0
|
||||
write_fragment cache_key, result[:content], :expires_in => expires.seconds
|
||||
RAILS_DEFAULT_LOGGER.debug "cache saved: #{name}"
|
||||
end
|
||||
else
|
||||
raise "Error applying external filter: #{result[:content]}"
|
||||
raise "Error applying external filter: stdout is #{result[:content]}, stderr is #{result[:errors]}"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -66,23 +67,42 @@ module WikiExternalFilterHelper
|
|||
return result
|
||||
end
|
||||
|
||||
def build_forced(text, info)
|
||||
def build_forced(text, attachments, info)
|
||||
|
||||
if info['replace_attachments'] and attachments
|
||||
attachments.each do |att|
|
||||
text.gsub!(/#{att.filename.downcase}/i, att.diskfile)
|
||||
end
|
||||
end
|
||||
|
||||
result = {}
|
||||
content = []
|
||||
errors = ""
|
||||
|
||||
RAILS_DEFAULT_LOGGER.debug "executing command: #{info['command']}"
|
||||
commands = info['commands']? info['commands'] : [info['command']]
|
||||
|
||||
content = IO.popen(info['command'], 'r+b') { |f|
|
||||
f.write info[:prolog] if info.key?(:prolog)
|
||||
f.write CGI.unescapeHTML(text)
|
||||
f.write info[:epilog] if info.key?(:epilog)
|
||||
f.close_write
|
||||
f.read
|
||||
commands.each do |command|
|
||||
RAILS_DEFAULT_LOGGER.info "executing command: #{command}"
|
||||
|
||||
c = nil
|
||||
e = nil
|
||||
|
||||
Open4::popen4(command) { |pid, fin, fout, ferr|
|
||||
fin.write info[:prolog] if info.key?(:prolog)
|
||||
fin.write CGI.unescapeHTML(text)
|
||||
fin.write info[:epilog] if info.key?(:epilog)
|
||||
fin.close
|
||||
c, e = [fout.read, ferr.read]
|
||||
}
|
||||
|
||||
RAILS_DEFAULT_LOGGER.info("child status: sig=#{$?.termsig}, exit=#{$?.exitstatus}")
|
||||
RAILS_DEFAULT_LOGGER.debug("child status: sig=#{$?.termsig}, exit=#{$?.exitstatus}")
|
||||
|
||||
content << c
|
||||
errors += e if e
|
||||
end
|
||||
|
||||
result[:content] = content
|
||||
result[:errors] = errors
|
||||
result[:content_type] = info['content_type']
|
||||
result[:source] = text
|
||||
result[:status] = $?.exitstatus == 0
|
||||
|
@ -101,12 +121,12 @@ module WikiExternalFilterHelper
|
|||
end
|
||||
|
||||
class Macro
|
||||
def initialize(view, source, macro, info)
|
||||
def initialize(view, source, attachments, macro, info)
|
||||
@view = view
|
||||
@view.controller.extend(WikiExternalFilterHelper)
|
||||
source.gsub!(/<br \/>/, "")
|
||||
source.gsub!(/<\/?p>/, "")
|
||||
@result = @view.controller.build(source, macro, info)
|
||||
@result = @view.controller.build(source, attachments, macro, info)
|
||||
end
|
||||
|
||||
def render()
|
||||
|
|
|
@ -12,6 +12,15 @@
|
|||
when /\/.*(x|ht)ml/ then
|
||||
%>
|
||||
<div><%= content %></div>
|
||||
<%
|
||||
when /video\/x\-flv/ then
|
||||
require 'RMagick'
|
||||
image = Magick::Image::from_blob(content[0]).first
|
||||
%>
|
||||
<a class='flowplayer-video' href='<%= ActionController::Base.relative_url_root + "/wiki_external_filter/video.flv?name=#{name}" %>' alt='<%= h source %>' style='display:block;width:<%= image.columns %>px;height:<%= image.rows + 24 %>px;background-image:url(<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name, :index => 0) %>);background-repeat:no-repeat'><%= image_tag 'play_large.png', :plugin => 'wiki_external_filter', :style => "display:block;position:relative;left:#{image.columns / 2 - 83 / 2}px;top:#{image.rows / 2 - 83 / 2}px" %></a>
|
||||
<%
|
||||
@flowplayer_used = true
|
||||
%>
|
||||
<%
|
||||
else
|
||||
%>
|
||||
|
@ -24,6 +33,32 @@
|
|||
<br/>
|
||||
<span class='wiki_page'>Goto source: [[<%= wiki_name %>]]</span>
|
||||
</div>
|
||||
<% content_for :header_tags do %>
|
||||
<%
|
||||
content_for :header_tags do
|
||||
%>
|
||||
<%
|
||||
if not @stylesheets_included
|
||||
@stylesheets_included = true
|
||||
%>
|
||||
<%= stylesheet_link_tag "wiki_external_filter.css", :plugin => "wiki_external_filter", :media => :all %>
|
||||
<% end %>
|
||||
<%
|
||||
end
|
||||
%>
|
||||
<%
|
||||
if @flowplayer_used
|
||||
if not @flowplayer_scripts_included
|
||||
@flowplayer_scripts_included = true
|
||||
%>
|
||||
<%= javascript_include_tag 'flowplayer.min.js', :plugin => 'wiki_external_filter' %>
|
||||
<script language="JavaScript">
|
||||
//<![CDATA[
|
||||
window.onload = function () {
|
||||
flowplayer("a.flowplayer-video", "<%= ActionController::Base.relative_url_root + Engines::RailsExtensions::AssetHelpers.plugin_asset_path('wiki_external_filter', 'javascripts', 'flowplayer.swf') %>", { clip: { bufferLength: 1 } });
|
||||
};
|
||||
//]]>
|
||||
</script>
|
||||
<%
|
||||
end
|
||||
end
|
||||
end
|
||||
%>
|
||||
|
|
|
@ -2,24 +2,60 @@
|
|||
case content_type
|
||||
when /image\// then
|
||||
%>
|
||||
<img class='externalfilterinline' src='<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name) %>' alt="<%= h source %>" />
|
||||
<img class='externalfilterinline' src='<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name, :index => 0) %>' alt="<%= h source %>" />
|
||||
<%
|
||||
when /text\/plain/ then
|
||||
%>
|
||||
<pre class='externalfilterinline'><%= h content %></pre>
|
||||
<pre class='externalfilterinline'><%= h content[0] %></pre>
|
||||
<%
|
||||
when /\/.*(x|ht)ml/ then
|
||||
%>
|
||||
<div class='externalfilterinline'><%= content %></div>
|
||||
<div class='externalfilterinline'><%= content[0] %></div>
|
||||
<%
|
||||
when /video\/x\-flv/ then
|
||||
require 'RMagick'
|
||||
image = Magick::Image::from_blob(content[0]).first
|
||||
%>
|
||||
<a class='flowplayer-video externalfilterinline' href='<%= ActionController::Base.relative_url_root + "/wiki_external_filter/video.flv?name=#{name}" %>' alt='<%= h source %>' style='display:block;width:<%= image.columns %>px;height:<%= image.rows + 24 %>px;background-image:url(<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name, :index => 0) %>);background-repeat:no-repeat'><%= image_tag 'play_large.png', :plugin => 'wiki_external_filter', :style => "display:block;position:relative;left:#{image.columns / 2 - 83 / 2}px;top:#{image.rows / 2 - 83 / 2}px" %></a>
|
||||
|
||||
<%
|
||||
@flowplayer_used = true
|
||||
%>
|
||||
<%
|
||||
else
|
||||
%>
|
||||
<object class='externalfilterinline' name='<%= name %>' data='<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name) %>' type='<%= content_type %>' title="<%= h source %>">
|
||||
<embed name='<%= name %>-2' src='<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name) %>' type='<%= content_type %>' title="<%= h source %>" />
|
||||
<object class='externalfilterinline' name='<%= name %>' data='<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name, :index => 0) %>' type='<%= content_type %>' title="<%= h source %>">
|
||||
<embed name='<%= name %>-2' src='<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name, :index => 0) %>' type='<%= content_type %>' title="<%= h source %>" />
|
||||
</object>
|
||||
<%
|
||||
end
|
||||
%>
|
||||
<% content_for :header_tags do %>
|
||||
<%
|
||||
content_for :header_tags do
|
||||
%>
|
||||
<%
|
||||
if not @stylesheets_included
|
||||
@stylesheets_included = true
|
||||
%>
|
||||
<%= stylesheet_link_tag "wiki_external_filter.css", :plugin => "wiki_external_filter", :media => :all %>
|
||||
<% end %>
|
||||
<%
|
||||
end
|
||||
%>
|
||||
<%
|
||||
if @flowplayer_used
|
||||
if not @flowplayer_scripts_included
|
||||
@flowplayer_scripts_included = true
|
||||
%>
|
||||
<%= javascript_include_tag 'flowplayer.min.js', :plugin => 'wiki_external_filter' %>
|
||||
<script language="JavaScript">
|
||||
//<![CDATA[
|
||||
window.onload = function () {
|
||||
flowplayer("a.flowplayer-video", "<%= ActionController::Base.relative_url_root + Engines::RailsExtensions::AssetHelpers.plugin_asset_path('wiki_external_filter', 'javascripts', 'flowplayer.swf') %>", { clip: { bufferLength: 1 } });
|
||||
};
|
||||
//]]>
|
||||
</script>
|
||||
<%
|
||||
end
|
||||
end
|
||||
end
|
||||
%>
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,3 @@
|
|||
ActionController::Routing::Routes.draw do |map|
|
||||
map.connect 'wiki_external_filter/:filename', :controller => 'wiki_external_filter', :action => 'filter', :macro => 'flowplayer', :index => '1', :requirements => { :filename => /\S+\.flv/ }
|
||||
end
|
6
init.rb
6
init.rb
|
@ -18,8 +18,8 @@ Redmine::Plugin.register :wiki_external_filter do
|
|||
Redmine::WikiFormatting::Macros.register do
|
||||
info = config[name]
|
||||
desc info['description']
|
||||
macro name do |wiki_content_obj, args|
|
||||
m = WikiExternalFilterHelper::Macro.new(self, args.to_s, name, info)
|
||||
macro name do |obj, args|
|
||||
m = WikiExternalFilterHelper::Macro.new(self, args.to_s, obj.page.attachments, name, info)
|
||||
m.render
|
||||
end
|
||||
|
||||
|
@ -33,7 +33,7 @@ Redmine::Plugin.register :wiki_external_filter do
|
|||
@included_wiki_pages ||= []
|
||||
raise 'Circular inclusion detected' if @included_wiki_pages.include?(page.title)
|
||||
@included_wiki_pages << page.title
|
||||
m = WikiExternalFilterHelper::Macro.new(self, page.content.text, name, info)
|
||||
m = WikiExternalFilterHelper::Macro.new(self, page.content.text, page.attachments, name, info)
|
||||
@included_wiki_pages.pop
|
||||
m.render_block(args.to_s)
|
||||
end
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
|
||||
connect 'wiki_external_filter/:macro/:name', :controller => 'wiki_external_filter', :action => 'filter', :macro => /\S+/
|
||||
connect 'wiki_external_filter/:filename', :controller => 'wiki_external_filter', :action => 'filter', :macro => 'flowplayer', :index => '1', :requirements => { :filename => /\S+\.flv/ }
|
||||
|
|
Reference in New Issue