- 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:
root 2010-03-26 13:51:13 +02:00
parent 5ea4c736ed
commit 8cfa874772
14 changed files with 151 additions and 32 deletions

View File

@ -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

View File

@ -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}"
RAILS_DEFAULT_LOGGER.info("child status: sig=#{$?.termsig}, exit=#{$?.exitstatus}")
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.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()

View File

@ -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 %>
<%= stylesheet_link_tag "wiki_external_filter.css", :plugin => "wiki_external_filter", :media => :all %>
<% end %>
<%
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
%>
<%
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
%>

View File

@ -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 %>
<%= stylesheet_link_tag "wiki_external_filter.css", :plugin => "wiki_external_filter", :media => :all %>
<% end %>
<%
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
%>
<%
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.

24
assets/javascripts/flowplayer.min.js vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

3
config/routes.rb Normal file
View File

@ -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

View File

@ -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

View File

@ -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/ }