From 68579954429b98924aab42531dc0d4378fb12630 Mon Sep 17 00:00:00 2001 From: Bart Kamphorst Date: Fri, 2 Nov 2018 14:38:12 +0100 Subject: [PATCH 1/6] Only use ajax for file upload. Prepare for handling of duplicate error. --- lib/gollum/app.rb | 10 +++------ .../javascript/editor/gollum.editor.js.erb | 4 ++-- .../public/gollum/javascript/gollum.js.erb | 22 ++++++++++++++++++- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/lib/gollum/app.rb b/lib/gollum/app.rb index 0da65acd..cc2a5b47 100644 --- a/lib/gollum/app.rb +++ b/lib/gollum/app.rb @@ -180,14 +180,11 @@ module Precious end end + # AJAX calls only post '/upload_file' do wiki = wiki_new - unless wiki.allow_uploads - @message = "File uploads are disabled" - mustache :error - return - end + halt 405 unless wiki.allow_uploads if params[:file] fullname = params[:file][:filename] @@ -224,8 +221,7 @@ module Precious committer.commit redirect to(request.referer) rescue Gollum::DuplicatePageError => e - @message = "Duplicate page: #{e.message}" - mustache :error + halt 409 # Signal conflict end end diff --git a/lib/gollum/public/gollum/javascript/editor/gollum.editor.js.erb b/lib/gollum/public/gollum/javascript/editor/gollum.editor.js.erb index 464e1948..ff758f96 100755 --- a/lib/gollum/public/gollum/javascript/editor/gollum.editor.js.erb +++ b/lib/gollum/public/gollum/javascript/editor/gollum.editor.js.erb @@ -228,8 +228,8 @@ } window.ace_editor.insert(text); }, - error: function(r, textStatus) { - alert('Error uploading file: ' + textStatus); + error: function(r, textStatus, errorThrown) { + alert('Error uploading file: ' + textStatus + ' ' + errorThrown); $editorBody.removeClass('uploading'); } }); diff --git a/lib/gollum/public/gollum/javascript/gollum.js.erb b/lib/gollum/public/gollum/javascript/gollum.js.erb index 173bf27d..33c2883b 100755 --- a/lib/gollum/public/gollum/javascript/gollum.js.erb +++ b/lib/gollum/public/gollum/javascript/gollum.js.erb @@ -158,6 +158,7 @@ $(document).ready(function() { } }; + // ua detection if ($.browser.mozilla) { $('body').addClass('ff'); @@ -187,7 +188,26 @@ $(document).ready(function() { } ], OK: function( res ) { - $('#upload').submit(); + var formData = new FormData($('#upload').get(0)); + var endpoint = $('#upload').attr("action"); + + $.ajax({ + url: endpoint, + type: 'POST', + data: formData, + processData: false, + contentType: false, + success: function(data) { + // File successfully uploaded + }, + error: function(data, textStatus, errorThrown) { + if (data.status == 409) { + alert('This file already exists.'); + } else { + alert('Error uploading file: ' + textStatus + ' ' + errorThrown); + } + } + }); } }); }); From 64c4ee9c058bfc6f7774e7c991941358fc739347 Mon Sep 17 00:00:00 2001 From: Bart Kamphorst Date: Wed, 7 Nov 2018 11:06:25 +0100 Subject: [PATCH 2/6] Improve upload handling (server-side and UI). --- bin/gollum | 2 +- lib/gollum/app.rb | 29 +++++++++++-------- .../javascript/editor/gollum.editor.js.erb | 3 +- .../public/gollum/javascript/gollum.dialog.js | 12 ++++---- .../public/gollum/javascript/gollum.js.erb | 14 ++++++++- .../public/gollum/stylesheets/_layout.scss | 6 ++++ .../public/gollum/stylesheets/dialog.scss | 8 ++++- lib/gollum/templates/layout.mustache | 14 +++++---- lib/gollum/views/create.rb | 4 --- lib/gollum/views/edit.rb | 4 --- lib/gollum/views/layout.rb | 4 +++ lib/gollum/views/page.rb | 4 --- test/test_allow_editing.rb | 4 +-- 13 files changed, 65 insertions(+), 43 deletions(-) diff --git a/bin/gollum b/bin/gollum index 56e8f728..cd4e41e0 100755 --- a/bin/gollum +++ b/bin/gollum @@ -127,7 +127,7 @@ MSG end opts.on("--allow-uploads [MODE]", [:dir, :page], "Enable file uploads.", "If set to 'dir', Gollum will store all uploads in the '/uploads/' directory.", - "If set to 'page', Gollum will store each upload at the currently edited page.") do |mode| + "If set to 'page', Gollum will store uploads per page in '/uploads/[pagename]'.") do |mode| wiki_options[:allow_uploads] = true wiki_options[:per_page_uploads] = true if mode == :page end diff --git a/lib/gollum/app.rb b/lib/gollum/app.rb index cc2a5b47..f790e193 100644 --- a/lib/gollum/app.rb +++ b/lib/gollum/app.rb @@ -84,6 +84,7 @@ module Precious before do settings.wiki_options[:allow_editing] = settings.wiki_options.fetch(:allow_editing, true) @allow_editing = settings.wiki_options[:allow_editing] + @per_page_uploads = settings.wiki_options[:per_page_uploads] forbid unless @allow_editing || request.request_method == "GET" Precious::App.set(:mustache, {:templates => settings.wiki_options[:template_dir]}) if settings.wiki_options[:template_dir] @base_url = url('/', false).chomp('/') @@ -166,7 +167,6 @@ module Precious wikip = wiki_page(params[:splat].first) @name = join_page_name(wikip.name, wikip.ext) @path = wikip.path - @upload_dest = find_upload_dest(@path) wiki = wikip.wiki @allow_uploads = wiki.allow_uploads @@ -182,8 +182,8 @@ module Precious # AJAX calls only post '/upload_file' do + wiki = wiki_new - halt 405 unless wiki.allow_uploads if params[:file] @@ -192,8 +192,21 @@ module Precious end halt 500 unless tempfile.is_a? Tempfile - # Remove page file dir prefix from upload path if necessary -- committer handles this itself - dir = wiki.per_page_uploads ? params[:upload_dest] : ::File.join([wiki.page_file_dir, 'uploads'].compact) + if wiki.per_page_uploads + # remove base_url and gollum/* subpath if necessary + dir = request.referer. + sub(request.base_url, ''). + sub(/.*gollum\/\w+\//, '') + # remove file extension + dir = dir.sub(::File.extname(dir), '') + dir = ::File.join("uploads", dir) + else + # Remove page file dir prefix from upload path if necessary -- committer handles this itself + dir = ::File.join([wiki.page_file_dir, 'uploads'].compact) + end + halt 500 if dir.include?('..') + halt 500 unless Pathname(dir).relative? + ext = ::File.extname(fullname) format = ext.split('.').last || 'txt' filename = ::File.basename(fullname, ext) @@ -304,7 +317,6 @@ module Precious @ext = wikip.ext @path = wikip.path @allow_uploads = wikip.wiki.allow_uploads - @upload_dest = find_upload_dest(@path) page_dir = settings.wiki_options[:page_file_dir].to_s unless page_dir.empty? @@ -496,7 +508,6 @@ module Precious @page = page @name = name @content = page.formatted_data - @upload_dest = find_upload_dest(path) # Extensions and layout data @editable = true @@ -573,11 +584,5 @@ module Precious commit_message end - def find_upload_dest(path) - settings.wiki_options[:allow_uploads] ? - (settings.wiki_options[:per_page_uploads] ? - "#{path}/#{@name}".sub(/^\/\//, '') : 'uploads' - ) : '' - end end end diff --git a/lib/gollum/public/gollum/javascript/editor/gollum.editor.js.erb b/lib/gollum/public/gollum/javascript/editor/gollum.editor.js.erb index ff758f96..d49dd18e 100755 --- a/lib/gollum/public/gollum/javascript/editor/gollum.editor.js.erb +++ b/lib/gollum/public/gollum/javascript/editor/gollum.editor.js.erb @@ -205,9 +205,8 @@ var file = e.dataTransfer.files[0], formData = new FormData(); - formData.append('upload_dest', uploadDest); formData.append('file', file); - + $.ajax({ url: '<%= upload_file_path %>', data: formData, diff --git a/lib/gollum/public/gollum/javascript/gollum.dialog.js b/lib/gollum/public/gollum/javascript/gollum.dialog.js index c7dcba0f..b2e9ec7f 100755 --- a/lib/gollum/public/gollum/javascript/gollum.dialog.js +++ b/lib/gollum/public/gollum/javascript/gollum.dialog.js @@ -105,8 +105,6 @@ html += '
'; - html += ''; html += ''; html += '
'; @@ -125,9 +123,9 @@ title +'' + '
' + body + '
' + '
' + - 'Cancel' + - 'OK' + '
' + ''; @@ -139,9 +137,9 @@ title +'' + '
' + body + '
' + '
' + - 'Cancel' + - 'Cancel' + + '
' + '' + diff --git a/lib/gollum/public/gollum/javascript/gollum.js.erb b/lib/gollum/public/gollum/javascript/gollum.js.erb index 33c2883b..9cf5fc89 100755 --- a/lib/gollum/public/gollum/javascript/gollum.js.erb +++ b/lib/gollum/public/gollum/javascript/gollum.js.erb @@ -177,7 +177,7 @@ $(document).ready(function() { $('#minibutton-upload-page').parent().removeClass('jaws'); $('#minibutton-upload-page').click(function(e) { e.preventDefault(); - + $.GollumDialog.init({ title: 'Upload File', fields: [ @@ -188,6 +188,7 @@ $(document).ready(function() { } ], OK: function( res ) { + $('#wiki-content').addClass('uploading'); var formData = new FormData($('#upload').get(0)); var endpoint = $('#upload').attr("action"); @@ -199,8 +200,10 @@ $(document).ready(function() { contentType: false, success: function(data) { // File successfully uploaded + $('#wiki-content').removeClass('uploading'); }, error: function(data, textStatus, errorThrown) { + $('#wiki-content').removeClass('uploading'); if (data.status == 409) { alert('This file already exists.'); } else { @@ -210,6 +213,15 @@ $(document).ready(function() { }); } }); + $('#gollum-dialog-action-ok').attr('disabled', true); + $('input:file').on('change', function() { + if ($(this).val()) { + news = 'Your uploaded file will be accessible at
/' + uploadDest + '/' + $('input[type=file]').val().split('\\').pop(); + $(".context").html(news); + $('#gollum-dialog-action-ok').attr('disabled', false); + + }; + }); }); } diff --git a/lib/gollum/public/gollum/stylesheets/_layout.scss b/lib/gollum/public/gollum/stylesheets/_layout.scss index b3eb339c..3d91e7c7 100644 --- a/lib/gollum/public/gollum/stylesheets/_layout.scss +++ b/lib/gollum/public/gollum/stylesheets/_layout.scss @@ -20,6 +20,12 @@ height: 1%; overflow: auto; } + + &.uploading { + opacity: 0.5; + } + + } /* @section body */ diff --git a/lib/gollum/public/gollum/stylesheets/dialog.scss b/lib/gollum/public/gollum/stylesheets/dialog.scss index 39108757..715a837d 100644 --- a/lib/gollum/public/gollum/stylesheets/dialog.scss +++ b/lib/gollum/public/gollum/stylesheets/dialog.scss @@ -29,7 +29,7 @@ display: block; } - a.minibutton { + button.minibutton { float: right; margin-right: 0.5em; width: auto; @@ -42,6 +42,12 @@ @include button-base; } + + button.minibutton:disabled { + opacity: 0.65; + cursor: not-allowed; + } + } #gollum-dialog-dialog-inner { diff --git a/lib/gollum/templates/layout.mustache b/lib/gollum/templates/layout.mustache index c972591f..4788ad3f 100644 --- a/lib/gollum/templates/layout.mustache +++ b/lib/gollum/templates/layout.mustache @@ -15,11 +15,15 @@ {{#sprockets_javascript_tag}}app{{/sprockets_javascript_tag}} {{#use_identicon}} diff --git a/lib/gollum/views/create.rb b/lib/gollum/views/create.rb index 4f1bab80..05e78855 100755 --- a/lib/gollum/views/create.rb +++ b/lib/gollum/views/create.rb @@ -21,10 +21,6 @@ module Precious @allow_uploads end - def upload_dest - @upload_dest - end - def format @format ||= find_format.to_s.downcase end diff --git a/lib/gollum/views/edit.rb b/lib/gollum/views/edit.rb index b5579b55..59b5a504 100755 --- a/lib/gollum/views/edit.rb +++ b/lib/gollum/views/edit.rb @@ -64,10 +64,6 @@ module Precious @allow_uploads end - def upload_dest - @upload_dest - end - def format @format = (@page.format || false) if @format.nil? @format.to_s.downcase diff --git a/lib/gollum/views/layout.rb b/lib/gollum/views/layout.rb index 0777c0e5..60a6b0d1 100644 --- a/lib/gollum/views/layout.rb +++ b/lib/gollum/views/layout.rb @@ -43,6 +43,10 @@ module Precious def js # custom js @js end + + def per_page_uploads + @per_page_uploads + end end end diff --git a/lib/gollum/views/page.rb b/lib/gollum/views/page.rb index c7f0c58c..d44fe22f 100644 --- a/lib/gollum/views/page.rb +++ b/lib/gollum/views/page.rb @@ -57,10 +57,6 @@ module Precious @allow_uploads end - def upload_dest - @upload_dest - end - def has_header if @header @header.formatted_data.strip.empty? ? false : true diff --git a/test/test_allow_editing.rb b/test/test_allow_editing.rb index 7c3ab887..0d2a8d35 100644 --- a/test/test_allow_editing.rb +++ b/test/test_allow_editing.rb @@ -32,7 +32,7 @@ context "Precious::Views::Editing" do assert_match /Delete this Page/, last_response.body, "'Delete this Page' link is blocked in page template" assert_match /New/, last_response.body, "'New' button is blocked in page template" - assert_match /Upload/, last_response.body, "'Upload' link is blocked in page template" + assert_match /Upload\b/, last_response.body, "'Upload' link is blocked in page template" assert_match /Rename/, last_response.body, "'Rename' link is blocked in page template" assert_match /Edit/, last_response.body, "'Edit' link is blocked in page template" @@ -56,7 +56,7 @@ context "Precious::Views::Editing" do assert_no_match /Delete this Page/, last_response.body, "'Delete this Page' link not blocked in page template" assert_no_match /New/, last_response.body, "'New' button not blocked in page template" - assert_no_match /Upload/, last_response.body, "'Upload' link not blocked in page template" + assert_no_match /Upload\b/, last_response.body, "'Upload' link not blocked in page template" assert_no_match /Rename/, last_response.body, "'Rename' link not blocked in page template" assert_no_match /Edit/, last_response.body, "'Edit' link not blocked in page template" From 3c4c2a072c15ce67d5ce19b4625d1ac047fbb4e1 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Sat, 10 Nov 2018 17:47:02 +0100 Subject: [PATCH 3/6] Update app.rb (#1346) --- lib/gollum/app.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gollum/app.rb b/lib/gollum/app.rb index 0da65acd..a835d318 100644 --- a/lib/gollum/app.rb +++ b/lib/gollum/app.rb @@ -86,7 +86,7 @@ module Precious @allow_editing = settings.wiki_options[:allow_editing] forbid unless @allow_editing || request.request_method == "GET" Precious::App.set(:mustache, {:templates => settings.wiki_options[:template_dir]}) if settings.wiki_options[:template_dir] - @base_url = url('/', false).chomp('/') + @base_url = url('/', false).chomp('/').force_encoding('utf-8') @page_dir = settings.wiki_options[:page_file_dir].to_s # above will detect base_path when it's used with map in a config.ru settings.wiki_options.merge!({ :base_path => @base_url }) From 104c959bf7695c300d2cfb4aa51548c7cba4ea0b Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Sun, 11 Nov 2018 02:11:21 +0100 Subject: [PATCH 4/6] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 31266ded..02807c15 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,9 @@ Since all markups are rendered by the [github-markup](https://github.com/github/ * Note that Gollum will also need you to install `docutils` for your Python 2. Installation procedure can, again, vary depending on operating system and package manager. * [Textile](http://redcloth.org/hobix.com/textile/quick.html) -- `[sudo] gem install RedCloth` -By default, Gollum ships with the `kramdown` gem to render Markdown. However, you can use any [Markdown renderer supported by github-markup](https://github.com/github/markup/blob/master/lib/github/markup/markdown.rb). The thing to remember is that the first installed renderer from the list will be used. So, for example, `redcarpet` will NOT be used if `github/markdown` is installed. +By default, Gollum ships with the `kramdown` gem to render Markdown. However, you can use any [Markdown renderer supported by github-markup](https://github.com/github/markup/blob/master/lib/github/markup/markdown.rb). The first installed renderer from the list will be used. So, for example, `redcarpet` will NOT be used if `github/markdown` is installed. + +See [here](https://github.com/gollum/gollum/wiki/Custom-rendering-gems) for instructions on how to use custom rendering gems. ## RUNNING From 70bf766cd070719669c1c88b1bad72e2dfd4d013 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Sun, 11 Nov 2018 02:25:29 +0100 Subject: [PATCH 5/6] Update README.md --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 02807c15..c095e555 100644 --- a/README.md +++ b/README.md @@ -81,10 +81,10 @@ Installation examples for individual systems can be seen [here](https://github.c ### Markups Gollum presently ships with support for the following markups: -* [Markdown](http://daringfireball.net/projects/markdown/syntax) +* [Markdown](http://daringfireball.net/projects/markdown/syntax) (see [below](#Markdown-flavors) for more information on Markdown flavors) * [RDoc](http://rdoc.sourceforge.net/) -Since all markups are rendered by the [github-markup](https://github.com/github/markup) gem, you can easily add support for other markups by additional installation: +You can easily activate support for other markups by installing additional renderers (any that are supported by [github-markup](https://github.com/github/markup)): * [AsciiDoc](http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/) -- `[sudo] gem install asciidoctor` * [Creole](http://www.wikicreole.org/wiki/CheatSheet) -- `[sudo] gem install creole` * [MediaWiki](http://www.mediawiki.org/wiki/Help:Formatting) -- `[sudo] gem install wikicloth` @@ -92,12 +92,14 @@ Since all markups are rendered by the [github-markup](https://github.com/github/ * [Pod](http://perldoc.perl.org/perlpod.html) -- requires Perl >= 5.10 (the `perl` command must be available on your command line) * Lower versions should install `Pod::Simple` from CPAN. * [ReStructuredText](http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html) -- requires python >= 2 (the `python2` command must be available on your command line) - * Note that Gollum will also need you to install `docutils` for your Python 2. Installation procedure can, again, vary depending on operating system and package manager. + * Note that Gollum will also need you to install `docutils` for your Python 2. * [Textile](http://redcloth.org/hobix.com/textile/quick.html) -- `[sudo] gem install RedCloth` -By default, Gollum ships with the `kramdown` gem to render Markdown. However, you can use any [Markdown renderer supported by github-markup](https://github.com/github/markup/blob/master/lib/github/markup/markdown.rb). The first installed renderer from the list will be used. So, for example, `redcarpet` will NOT be used if `github/markdown` is installed. +### Markdown flavors -See [here](https://github.com/gollum/gollum/wiki/Custom-rendering-gems) for instructions on how to use custom rendering gems. +By default, Gollum ships with the `kramdown` gem to render Markdown. However, you can use any [Markdown renderer supported by github-markup](https://github.com/github/markup/blob/master/lib/github/markup/markdown.rb). This includes [CommonMark](https://commonmark.org/) support via the `commonmarker` gem. The first installed renderer from the list will be used (e.g., `redcarpet` will NOT be used if `github/markdown` is installed). Just `gem install` the renderer of your choice. + +See [here](https://github.com/gollum/gollum/wiki/Custom-rendering-gems) for instructions on how to use custom rendering gems and set custom options. ## RUNNING From b50872497e75e06a988ff8e0ea155483206a97b4 Mon Sep 17 00:00:00 2001 From: Bart Kamphorst Date: Mon, 12 Nov 2018 11:57:28 +0100 Subject: [PATCH 6/6] Loosen route replacement regex to allow for dashes in routes. --- lib/gollum/app.rb | 2 +- lib/gollum/templates/layout.mustache | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gollum/app.rb b/lib/gollum/app.rb index f790e193..ec14fdfa 100644 --- a/lib/gollum/app.rb +++ b/lib/gollum/app.rb @@ -196,7 +196,7 @@ module Precious # remove base_url and gollum/* subpath if necessary dir = request.referer. sub(request.base_url, ''). - sub(/.*gollum\/\w+\//, '') + sub(/.*gollum\/[-\w]+\//, '') # remove file extension dir = dir.sub(::File.extname(dir), '') dir = ::File.join("uploads", dir) diff --git a/lib/gollum/templates/layout.mustache b/lib/gollum/templates/layout.mustache index 4788ad3f..fca9fa18 100644 --- a/lib/gollum/templates/layout.mustache +++ b/lib/gollum/templates/layout.mustache @@ -19,7 +19,7 @@ var uploadDest = 'uploads'; var perPageUploads = '{{per_page_uploads}}'; if (perPageUploads == 'true') { - uploadDest = uploadDest + window.location.pathname.replace(/.*gollum\/\w+\//, "/").replace(/\.[^/.]+$/, "") + uploadDest = uploadDest + window.location.pathname.replace(/.*gollum\/[-\w]+\//, "/").replace(/\.[^/.]+$/, "") } {{#page}} var pageFullPath = '{{url_path}}';