From 73e3a8a3f36759a3294e71d227bfb6f2aee9467d Mon Sep 17 00:00:00 2001 From: Reuben Mallaby Date: Mon, 23 Jul 2012 12:30:42 +0200 Subject: [PATCH] Initial commit --- COPYING | 339 +++++++++++ .../redmine_embedded_controller.rb | 152 +++++ app/helpers/redmine_embedded_helper.rb | 35 ++ app/views/redmine_embedded/_upload.html.erb | 9 + app/views/redmine_embedded/index.html.erb | 9 + app/views/settings/_redmine_embedded.html.erb | 22 + assets/javascripts/rcov.js | 18 + assets/stylesheets/doxygen.css | 224 ++++++++ assets/stylesheets/javadoc.css | 23 + assets/stylesheets/rcov.css | 525 ++++++++++++++++++ config/routes.rb | 4 + init.rb | 28 + lib/redmine_embedded.rb | 69 +++ 13 files changed, 1457 insertions(+) create mode 100644 COPYING create mode 100644 app/controllers/redmine_embedded_controller.rb create mode 100644 app/helpers/redmine_embedded_helper.rb create mode 100644 app/views/redmine_embedded/_upload.html.erb create mode 100644 app/views/redmine_embedded/index.html.erb create mode 100644 app/views/settings/_redmine_embedded.html.erb create mode 100644 assets/javascripts/rcov.js create mode 100644 assets/stylesheets/doxygen.css create mode 100644 assets/stylesheets/javadoc.css create mode 100644 assets/stylesheets/rcov.css create mode 100644 config/routes.rb create mode 100644 init.rb create mode 100644 lib/redmine_embedded.rb diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/app/controllers/redmine_embedded_controller.rb b/app/controllers/redmine_embedded_controller.rb new file mode 100644 index 0000000..cf7010b --- /dev/null +++ b/app/controllers/redmine_embedded_controller.rb @@ -0,0 +1,152 @@ +# Redmine - project management software +# Copyright (C) 2008 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. + +require 'iconv' + +class DataFile < ActiveRecord::Base + def self.save(directory, zipname, upload) + path = File.join(directory, zipname) + File.open(path, "wb") { |f| f.write(upload['datafile'].read) } + end +end + +class RedmineEmbeddedController < ApplicationController + class RedmineEmbeddedControllerError < StandardError; end + + unloadable + layout 'base' + before_filter :find_project, :authorize + + def index + file = params[:request_path] + path = get_real_path(file) + if File.directory?(path) + file = get_index_file(path) + target = file || [] + #target << file + # Forces redirect to the index file when the requested path is a directory + # so that relative links in embedded html pages work + redirect_to :request_path => target + return + end + + # Check file extension + raise RedmineEmbeddedControllerError.new('This file can not be viewed (invalid extension).') unless Redmine::Plugins::RedmineEmbedded.valid_extension?(path) + + if Redmine::MimeType.is_type?('image', path) + send_file path, :disposition => 'inline', :type => Redmine::MimeType.of(path) + else + embed_file path + end + + rescue Errno::ENOENT => e + @content = "No documentation found" + @title = "" + render :index + rescue Errno::EACCES => e + # Can not read the file + render_error "Unable to read the file: #{e.message}" + rescue RedmineEmbeddedControllerError => e + render_error e.message + end + + def upload + if params[:upload] + file = params[:upload] + zipname = sanitize_filename(params[:upload]['datafile'].original_filename) + if ["zip"].include?(File.extname(zipname).downcase[1..-1]) + dir = get_project_directory.gsub("/html", "") + if File.directory? dir + `rm -rf #{dir}/*` #clean up any exisiting docs + else + Dir.mkdir dir + end + filename = DataFile.save(dir, zipname, params[:upload]) + Dir.chdir(dir) + `unzip #{zipname}` + redirect_to show_embedded_url(@project), :notice => "Documentation uploaded" + else + render :index, :error => "File must be ZIP format" + end + else + render :index, :error => "No file uploaded" + end + end + + private + + def sanitize_filename(file_name) + # get only the filename, not the whole path (from IE) + just_filename = File.basename(file_name) + # replace all none alphanumeric, underscore or perioids + # with underscore + just_filename.sub(/[^\w\.\-]/,'_') + end + + def find_project + @project = Project.find(params[:id]) + rescue ActiveRecord::RecordNotFound + render_404 + end + + # Return the path to the html root directory for the current project + def get_project_directory + @project_directory ||= Setting.plugin_redmine_embedded['path'].to_s.gsub('{PROJECT}', @project.identifier) + end + + # Returns the absolute path of the requested file + # Parameter is an Array + def get_real_path(path) + real = get_project_directory + real = File.join(real, path) unless path.nil? || path.empty? + dir = File.expand_path(get_project_directory) + real = File.expand_path(real) + raise Errno::ENOENT unless real.starts_with?(dir) && File.exist?(real) + real + end + + # Returns the index file in the given directory + # and raises an exception if none is found + def get_index_file(dir) + indexes = Setting.plugin_redmine_embedded['index'].to_s.split + file = indexes.find {|f| File.exist?(File.join(dir, f))} + raise RedmineEmbeddedControllerError.new("No index file found in #{dir} (#{indexes.join(', ')}).") if file.nil? + file + end + + # Renders a given HTML file + def embed_file(path) + @content = File.read(path) + + # Extract html title from embedded page + if @content =~ %r{([^<]*)}mi + @title = $1.strip + end + + # Keep html body only + @content.gsub!(%r{^.*]*>(.*).*$}mi, '\\1') + + # Re-encode content if needed + source_encoding = Setting.plugin_redmine_embedded['encoding'].to_s + unless source_encoding.blank? + begin; @content = Iconv.new('UTF-8', source_encoding).iconv(@content); rescue; end + end + + @doc_template = Redmine::Plugins::RedmineEmbedded.detect_template_from_path(path) + render :action => 'index' + end +end diff --git a/app/helpers/redmine_embedded_helper.rb b/app/helpers/redmine_embedded_helper.rb new file mode 100644 index 0000000..d827144 --- /dev/null +++ b/app/helpers/redmine_embedded_helper.rb @@ -0,0 +1,35 @@ +# Redmine - project management software +# Copyright (C) 2008 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. + +module RedmineEmbeddedHelper + + # Adds include tags for assets of the given template + def asset_include_tags(template) + + Redmine::Plugins::RedmineEmbedded.assets(template).each { |asset| content_for(:header_tags) { asset_include_tag(asset) } } + end + + private + + def asset_include_tag(asset) + if asset =~ %r{\.js$} + javascript_include_tag(asset, :plugin => 'redmine_embedded') + else + stylesheet_link_tag(asset, :plugin => 'redmine_embedded') + end + end +end diff --git a/app/views/redmine_embedded/_upload.html.erb b/app/views/redmine_embedded/_upload.html.erb new file mode 100644 index 0000000..70e216d --- /dev/null +++ b/app/views/redmine_embedded/_upload.html.erb @@ -0,0 +1,9 @@ +

File Upload

+<%= form_tag(upload_embedded_path(@project), :multipart => true) do -%> +

+ : + <%= file_field "upload", "datafile" %> + <%= submit_tag "Upload" %> +

+<% end -%> +
diff --git a/app/views/redmine_embedded/index.html.erb b/app/views/redmine_embedded/index.html.erb new file mode 100644 index 0000000..37b6811 --- /dev/null +++ b/app/views/redmine_embedded/index.html.erb @@ -0,0 +1,9 @@ +<%= render :partial => "upload" if User.current.allowed_to?(:edit_embedded_doc, @project) -%> + + +<%= @content.html_safe %> + + +<% html_title(@title) if @title %> + +<% asset_include_tags(@doc_template) %> diff --git a/app/views/settings/_redmine_embedded.html.erb b/app/views/settings/_redmine_embedded.html.erb new file mode 100644 index 0000000..2c6bb65 --- /dev/null +++ b/app/views/settings/_redmine_embedded.html.erb @@ -0,0 +1,22 @@ +

+<%= text_field_tag 'settings[path]', @settings['path'], :size => 80 %> +
Use {PROJECT} to include the project identifier in the path

+ +

+<%= text_area_tag 'settings[index]', @settings['index'], :cols => 60, :rows => 3 %> +
Space separated list of index files by priority

+ +

+<%= text_area_tag 'settings[extensions]', @settings['extensions'], :cols => 60, :rows => 3 %> +
Space separated list of file extensions that can be viewed (case insensitive)

+ +

+<%= select_tag 'settings[template]', options_for_select([''] + Redmine::Plugins::RedmineEmbedded.available_templates, @settings['template']) %>

+ +

+<%= text_field_tag 'settings[encoding]', @settings['encoding'] %> +
Eg. ISO-8859-1
Leave this field empty if HTML files are UTF-8 encoded

+ +

+<%= text_field_tag 'settings[menu]', @settings['menu'], :size => 30 %> +
Clear this field if you don't want to add a tab to the project menu

diff --git a/assets/javascripts/rcov.js b/assets/javascripts/rcov.js new file mode 100644 index 0000000..9d90076 --- /dev/null +++ b/assets/javascripts/rcov.js @@ -0,0 +1,18 @@ +function toggleCode( id ) { + if ( document.getElementById ) + elem = document.getElementById( id ); + else if ( document.all ) + elem = eval( "document.all." + id ); + else + return false; + + elemStyle = elem.style; + + if ( elemStyle.display != "block" ) { + elemStyle.display = "block" + } else { + elemStyle.display = "none" + } + + return true; +} diff --git a/assets/stylesheets/doxygen.css b/assets/stylesheets/doxygen.css new file mode 100644 index 0000000..c5a0d51 --- /dev/null +++ b/assets/stylesheets/doxygen.css @@ -0,0 +1,224 @@ +#content { + font-family: Geneva, Arial, Helvetica, sans-serif; +} +#content h1, h2, h3 {border: 0;} +#content h1 {margin-bottom: 1em;} +#content CAPTION { font-weight: bold } +#content DIV.qindex { + line-height: 120%; + margin-bottom: 1em; +} +#content A.qindex { + text-decoration: none; + font-weight: bold; + padding: 2px; +} +#content A.qindexHL { + text-decoration: underline; + font-weight: bold; + padding: 2px; +} +#content A.el { text-decoration: none; font-weight: bold } +#content A.elRef { font-weight: bold } +#content A.code { text-decoration: none; font-weight: normal; color: #1A419D} +#content A.codeRef { font-weight: normal; color: #1A419D} +#content DL.el { margin-left: -1cm } +#content PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +#content DIV.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + padding: 6px; +} +#content DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } +#content TD.md { background-color: #F4F4FB; font-weight: bold; } +#content TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; } +#content TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; } +#content DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; + font-family: Geneva, Arial, Helvetica, sans-serif; +} +#content DIV.groupText { margin-left: 16px; font-style: italic; font-size: 14px } +#content TD.indexkey { + background-color: #eeeeff; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +#content TD.indexvalue { + background-color: #eeeeff; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +#content TR.memlist { + background-color: #f0f0f0; +} +#content P.formulaDsp { text-align: center; } +#content IMG.formulaDsp { } +#content IMG.formulaInl { vertical-align: middle; } +#content SPAN.keyword { color: #008000 } +#content SPAN.keywordtype { color: #604020 } +#content SPAN.keywordflow { color: #e08000 } +#content SPAN.comment { color: #800000 } +#content SPAN.preprocessor { color: #806020 } +#content SPAN.stringliteral { color: #002080 } +#content SPAN.charliteral { color: #008080 } +#content .mdTable { + border: 1px solid #868686; + background-color: #F4F4FB; +} +#content .mdRow { + padding: 8px 10px; +} +#content .mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 14px; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +#content .mdescRight { + padding: 0px 8px 4px 8px; + font-size: 14px; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +#content .memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-style: solid; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-family: Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; +} +#content .memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-style: solid; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-family: Geneva, Arial, Helvetica, sans-serif; + font-size: 13px; +} +#content .search { color: #003399; font-weight: bold; +} +#content FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +#content INPUT.search { font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #eeeeff; +} +#content TD.tiny { font-size: 75%; +} +#content .tabs ul li a#MSearchClose { + width: 12px; + display: inline-block; + overflow: hidden; + padding: 2px; + height: 12px; + line-height: 12px; +} + +#content .tabs ul li #MSearchField { + width: 120px; + margin: 0; +} + +#content .tabs ul li #MSearchBox { + margin-bottom: -2px; +} + +#content .memitem { + padding: 0; + margin-bottom: 10px; +} +#content .memname { + white-space: nowrap; + font-weight: bold; +} +#content .memproto, .memdoc { + border: 1px solid #84b0c7; +} +#content .memdoc { + padding: 2px 5px; + background-color: #eef3f5; + border-top-width: 0; + -webkit-border-bottom-left-radius: 8px; + -webkit-border-bottom-right-radius: 8px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -moz-border-radius-bottomleft: 8px; + -moz-border-radius-bottomright: 8px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; +} +#content .memproto { + padding: 0; + background-color: #d5e1e8; + font-weight: bold; + -webkit-border-top-left-radius: 8px; + -webkit-border-top-right-radius: 8px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -moz-border-radius-topleft: 8px; + -moz-border-radius-topright: 8px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; +} \ No newline at end of file diff --git a/assets/stylesheets/javadoc.css b/assets/stylesheets/javadoc.css new file mode 100644 index 0000000..f19dd6d --- /dev/null +++ b/assets/stylesheets/javadoc.css @@ -0,0 +1,23 @@ +/* Javadoc style sheet */ + +/* Table colors */ +.TableHeadingColor { background: #eef; } /* Dark mauve */ +.TableHeadingColor th b { font-size: 70%; } +.TableSubHeadingColor { background: #EEEEee; } /* Light mauve */ +.TableRowColor { background: #FFFFFF; } /* White */ + +/* Font used in left-hand frame lists */ +.FrameTitleFont { font-size: 100%; font-family: Helvetica, Arial, sans-serif; color:#000000 } +.FrameHeadingFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } +.FrameItemFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } + +/* Navigation bar fonts and colors */ +.NavBarCell1 { background-color: inherit; } /* Light mauve */ +.NavBarCell1Rev { background-color: inherit; } /* Dark Blue */ +.NavBarFont1 { font-family: Arial, Helvetica, sans-serif;} +.NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; font-style: underline; } + +.NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000; display: none;} +.NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000} + +#content table { border-collapse: collapse; border-color: #ddd; } diff --git a/assets/stylesheets/rcov.css b/assets/stylesheets/rcov.css new file mode 100644 index 0000000..74dfdf1 --- /dev/null +++ b/assets/stylesheets/rcov.css @@ -0,0 +1,525 @@ +span.cross-ref-title { + font-size: 140%; +} +span.cross-ref a { + text-decoration: none; +} +span.cross-ref { + background-color:#f3f7fa; + border: 1px dashed #333; + margin: 1em; + padding: 0.5em; + overflow: hidden; +} +a.crossref-toggle { + text-decoration: none; +} +span.marked0 { + background-color: rgb(185, 210, 200); + display: block; +} +span.marked1 { + background-color: rgb(190, 215, 205); + display: block; +} +span.inferred0 { + background-color: rgb(175, 200, 200); + display: block; +} +span.inferred1 { + background-color: rgb(180, 205, 205); + display: block; +} +span.uncovered0 { + background-color: rgb(225, 110, 110); + display: block; +} +span.uncovered1 { + background-color: rgb(235, 120, 120); + display: block; +} +span.overview { + border-bottom: 8px solid black; +} +div.overview { + border-bottom: 8px solid black; +} +#content div.footer { + font-size: 68%; + margin-top: 1.5em; +} +#content h1, h2, h3, h4, h5, h6 { + margin-bottom: 0.5em; +} +h5 { + margin-top: 0.5em; +} +.hidden { + display: none; +} +div.separator { + height: 10px; +} +/* Commented out for better readability, esp. on IE */ +/* +table tr td, table tr th { + font-size: 68%; +} +td.value table tr td { + font-size: 11px; +} +*/ +table.percent_graph { + height: 12px; + border: #808080 1px solid; + empty-cells: show; +} +table.percent_graph td.covered { + height: 10px; + background: #00f000; +} +table.percent_graph td.uncovered { + height: 10px; + background: #e00000; +} +table.percent_graph td.NA { + height: 10px; + background: #eaeaea; +} +table.report { + border-collapse: collapse; + width: 100%; +} +table.report td.heading { + background: #dcecff; + border: #d0d0d0 1px solid; + font-weight: bold; + text-align: center; +} +table.report td.heading:hover { + background: #c0ffc0; +} +table.report td.text { + border: #d0d0d0 1px solid; +} +table.report td.value, +table.report td.lines_total, +table.report td.lines_code { + text-align: right; + border: #d0d0d0 1px solid; +} +table.report tr.light { + background-color: #f6f7f8; +} +table.report tr.dark { + background-color: #fff; +} +span.run0 { + background-color: rgb(178, 204, 255); + display: block; +} +span.run1 { + background-color: rgb(178, 206, 255); + display: block; +} +span.run2 { + background-color: rgb(178, 209, 255); + display: block; +} +span.run3 { + background-color: rgb(178, 211, 255); + display: block; +} +span.run4 { + background-color: rgb(178, 214, 255); + display: block; +} +span.run5 { + background-color: rgb(178, 218, 255); + display: block; +} +span.run6 { + background-color: rgb(178, 220, 255); + display: block; +} +span.run7 { + background-color: rgb(178, 223, 255); + display: block; +} +span.run8 { + background-color: rgb(178, 225, 255); + display: block; +} +span.run9 { + background-color: rgb(178, 228, 255); + display: block; +} +span.run10 { + background-color: rgb(178, 232, 255); + display: block; +} +span.run11 { + background-color: rgb(178, 234, 255); + display: block; +} +span.run12 { + background-color: rgb(178, 237, 255); + display: block; +} +span.run13 { + background-color: rgb(178, 239, 255); + display: block; +} +span.run14 { + background-color: rgb(178, 242, 255); + display: block; +} +span.run15 { + background-color: rgb(178, 246, 255); + display: block; +} +span.run16 { + background-color: rgb(178, 248, 255); + display: block; +} +span.run17 { + background-color: rgb(178, 251, 255); + display: block; +} +span.run18 { + background-color: rgb(178, 253, 255); + display: block; +} +span.run19 { + background-color: rgb(178, 255, 253); + display: block; +} +span.run20 { + background-color: rgb(178, 255, 249); + display: block; +} +span.run21 { + background-color: rgb(178, 255, 247); + display: block; +} +span.run22 { + background-color: rgb(178, 255, 244); + display: block; +} +span.run23 { + background-color: rgb(178, 255, 242); + display: block; +} +span.run24 { + background-color: rgb(178, 255, 239); + display: block; +} +span.run25 { + background-color: rgb(178, 255, 235); + display: block; +} +span.run26 { + background-color: rgb(178, 255, 233); + display: block; +} +span.run27 { + background-color: rgb(178, 255, 230); + display: block; +} +span.run28 { + background-color: rgb(178, 255, 228); + display: block; +} +span.run29 { + background-color: rgb(178, 255, 225); + display: block; +} +span.run30 { + background-color: rgb(178, 255, 221); + display: block; +} +span.run31 { + background-color: rgb(178, 255, 219); + display: block; +} +span.run32 { + background-color: rgb(178, 255, 216); + display: block; +} +span.run33 { + background-color: rgb(178, 255, 214); + display: block; +} +span.run34 { + background-color: rgb(178, 255, 211); + display: block; +} +span.run35 { + background-color: rgb(178, 255, 207); + display: block; +} +span.run36 { + background-color: rgb(178, 255, 205); + display: block; +} +span.run37 { + background-color: rgb(178, 255, 202); + display: block; +} +span.run38 { + background-color: rgb(178, 255, 200); + display: block; +} +span.run39 { + background-color: rgb(178, 255, 197); + display: block; +} +span.run40 { + background-color: rgb(178, 255, 193); + display: block; +} +span.run41 { + background-color: rgb(178, 255, 191); + display: block; +} +span.run42 { + background-color: rgb(178, 255, 188); + display: block; +} +span.run43 { + background-color: rgb(178, 255, 186); + display: block; +} +span.run44 { + background-color: rgb(178, 255, 183); + display: block; +} +span.run45 { + background-color: rgb(178, 255, 179); + display: block; +} +span.run46 { + background-color: rgb(179, 255, 178); + display: block; +} +span.run47 { + background-color: rgb(182, 255, 178); + display: block; +} +span.run48 { + background-color: rgb(184, 255, 178); + display: block; +} +span.run49 { + background-color: rgb(187, 255, 178); + display: block; +} +span.run50 { + background-color: rgb(191, 255, 178); + display: block; +} +span.run51 { + background-color: rgb(193, 255, 178); + display: block; +} +span.run52 { + background-color: rgb(196, 255, 178); + display: block; +} +span.run53 { + background-color: rgb(198, 255, 178); + display: block; +} +span.run54 { + background-color: rgb(201, 255, 178); + display: block; +} +span.run55 { + background-color: rgb(205, 255, 178); + display: block; +} +span.run56 { + background-color: rgb(207, 255, 178); + display: block; +} +span.run57 { + background-color: rgb(210, 255, 178); + display: block; +} +span.run58 { + background-color: rgb(212, 255, 178); + display: block; +} +span.run59 { + background-color: rgb(215, 255, 178); + display: block; +} +span.run60 { + background-color: rgb(219, 255, 178); + display: block; +} +span.run61 { + background-color: rgb(221, 255, 178); + display: block; +} +span.run62 { + background-color: rgb(224, 255, 178); + display: block; +} +span.run63 { + background-color: rgb(226, 255, 178); + display: block; +} +span.run64 { + background-color: rgb(229, 255, 178); + display: block; +} +span.run65 { + background-color: rgb(233, 255, 178); + display: block; +} +span.run66 { + background-color: rgb(235, 255, 178); + display: block; +} +span.run67 { + background-color: rgb(238, 255, 178); + display: block; +} +span.run68 { + background-color: rgb(240, 255, 178); + display: block; +} +span.run69 { + background-color: rgb(243, 255, 178); + display: block; +} +span.run70 { + background-color: rgb(247, 255, 178); + display: block; +} +span.run71 { + background-color: rgb(249, 255, 178); + display: block; +} +span.run72 { + background-color: rgb(252, 255, 178); + display: block; +} +span.run73 { + background-color: rgb(255, 255, 178); + display: block; +} +span.run74 { + background-color: rgb(255, 252, 178); + display: block; +} +span.run75 { + background-color: rgb(255, 248, 178); + display: block; +} +span.run76 { + background-color: rgb(255, 246, 178); + display: block; +} +span.run77 { + background-color: rgb(255, 243, 178); + display: block; +} +span.run78 { + background-color: rgb(255, 240, 178); + display: block; +} +span.run79 { + background-color: rgb(255, 238, 178); + display: block; +} +span.run80 { + background-color: rgb(255, 234, 178); + display: block; +} +span.run81 { + background-color: rgb(255, 232, 178); + display: block; +} +span.run82 { + background-color: rgb(255, 229, 178); + display: block; +} +span.run83 { + background-color: rgb(255, 226, 178); + display: block; +} +span.run84 { + background-color: rgb(255, 224, 178); + display: block; +} +span.run85 { + background-color: rgb(255, 220, 178); + display: block; +} +span.run86 { + background-color: rgb(255, 218, 178); + display: block; +} +span.run87 { + background-color: rgb(255, 215, 178); + display: block; +} +span.run88 { + background-color: rgb(255, 212, 178); + display: block; +} +span.run89 { + background-color: rgb(255, 210, 178); + display: block; +} +span.run90 { + background-color: rgb(255, 206, 178); + display: block; +} +span.run91 { + background-color: rgb(255, 204, 178); + display: block; +} +span.run92 { + background-color: rgb(255, 201, 178); + display: block; +} +span.run93 { + background-color: rgb(255, 198, 178); + display: block; +} +span.run94 { + background-color: rgb(255, 196, 178); + display: block; +} +span.run95 { + background-color: rgb(255, 192, 178); + display: block; +} +span.run96 { + background-color: rgb(255, 189, 178); + display: block; +} +span.run97 { + background-color: rgb(255, 187, 178); + display: block; +} +span.run98 { + background-color: rgb(255, 184, 178); + display: block; +} +span.run99 { + background-color: rgb(255, 182, 178); + display: block; +} +span.run100 { + background-color: rgb(255, 178, 178); + display: block; +} +pre { + white-space: pre-wrap; /* CSS2.1 compliant */ + white-space: -moz-pre-wrap; /* Mozilla-based browsers */ + white-space: -o-pre-wrap; /* Opera 7+ */ +} diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 0000000..79cc93e --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,4 @@ +RedmineApp::Application.routes.draw do + post "/projects/:id/embedded/upload", :to => "redmine_embedded#upload", :as => :upload_embedded + get 'projects/:id/embedded(/*request_path(.:format))', :to => "redmine_embedded#index", :as => :show_embedded +end diff --git a/init.rb b/init.rb new file mode 100644 index 0000000..f1a4bd5 --- /dev/null +++ b/init.rb @@ -0,0 +1,28 @@ +require 'redmine' +require 'redmine_embedded' + +Redmine::Plugin.register :redmine_embedded do + name 'Redmine Embedded Documentation' + author 'Jean-Philippe Lang, Reuben Mallaby' + description 'Embed various documentations in your projects' + version '0.0.2' + settings :partial => 'settings/redmine_embedded', + :default => { 'path' => '/var/doc/{PROJECT}/html', + 'index' => 'main.html overview-summary.html index.html', + 'extensions' => 'html png gif', + 'template' => '', + 'encoding' => '', + 'menu' => 'Embedded' } + project_module :redmine_embedded do + permission :view_embedded_doc, {:redmine_embedded => :index} + permission :edit_embedded_doc, {:redmine_embedded => :upload} + end + menu :project_menu, :redmine_embedded, + { + :controller => "redmine_embedded", + :action => "index" + }, + :caption => Proc.new { Setting.plugin_redmine_embedded['menu'] }, + :if => Proc.new { !Setting.plugin_redmine_embedded['menu'].blank? } +end + diff --git a/lib/redmine_embedded.rb b/lib/redmine_embedded.rb new file mode 100644 index 0000000..f37583b --- /dev/null +++ b/lib/redmine_embedded.rb @@ -0,0 +1,69 @@ +# Redmine - project management software +# Copyright (C) 2008 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. + +module Redmine + module Plugins + module RedmineEmbedded + class << self + + # Returns an Array of available templates + def available_templates + assets_by_template.keys.sort + end + + # Returns the assets for a given template + def assets(template) + assets_by_template.has_key?(template) ? assets_by_template[template] : [] + end + + def detect_template_from_path(path) + t = path.to_s.split(%r{[/\\]}) & available_templates + t.empty? ? Setting.plugin_redmine_embedded['template'].to_s : t.first + end + + def valid_extension?(path) + extensions = Setting.plugin_redmine_embedded['extensions'].to_s.split.each(&:downcase) + extensions.include?(File.extname(path).downcase[1..-1]) + end + + private + + # A Hash of available assets by template + def assets_by_template + @@assets_by_template ||= scan_assets + end + + # Scans assets directory for templates + # and returns a Hash of available assets by template + def scan_assets + a = Hash.new {|h,k| h[k] = [] } + Dir.glob(File.join(File.dirname(__FILE__), '../assets/*/*.{css,js}')).each do |asset| + asset = File.basename(asset) + template = asset.gsub(%r{\.(js|css)$}, '') + a[template] << asset + end + a + end + end + end + end +end + +class << RedmineApp::Application;self;end.class_eval do + define_method :clear!, lambda {} +end +