diff --git a/Rakefile b/Rakefile index 1394ee96..ee0eb223 100644 --- a/Rakefile +++ b/Rakefile @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- task :default => %w(test:spec) def shrink_js(t) @@ -70,7 +69,7 @@ end desc 'Generate documentation' task :doc => 'doc/api/index.html' file 'doc/api/index.html' => FileList['**/*.rb'] do |f| - sh "rdoc -o doc/api --title 'Ōlelo Source Documentation' --inline-source --format=html #{f.prerequisites.join(' ')}" + sh "rdoc -o doc/api --title 'Olelo Source Documentation' --inline-source --format=html #{f.prerequisites.join(' ')}" end namespace :notes do diff --git a/config.ru b/config.ru index 54536081..4a037387 100755 --- a/config.ru +++ b/config.ru @@ -1,5 +1,4 @@ #!/usr/bin/env rackup -# -*- coding: utf-8 -*- path = ::File.expand_path(::File.dirname(__FILE__)) $: << ::File.join(path, 'lib') @@ -70,6 +69,12 @@ end use Rack::MethodOverride use Rack::CommonLogger, LoggerOutput.new(logger) + +if ''.respond_to? :encoding + require 'rack/force_encoding' + use Rack::ForceEncoding +end + run Olelo::Application.new(nil, :logger => logger) logger.info "Olelo started in #{timer.stop.elapsed_ms}ms (#{Olelo::Config.production? ? 'Production' : 'Development'} mode)" diff --git a/lib/olelo.rb b/lib/olelo.rb index 533da02a..9b5be861 100644 --- a/lib/olelo.rb +++ b/lib/olelo.rb @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - require 'logger' require 'cgi' require 'digest/md5' diff --git a/lib/olelo/application.rb b/lib/olelo/application.rb index 1c1279c4..81d3d7c9 100644 --- a/lib/olelo/application.rb +++ b/lib/olelo/application.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- module Olelo # Main class of the application class Application diff --git a/lib/olelo/attributeeditor.rb b/lib/olelo/attributeeditor.rb index 9ec50e01..d88153dd 100644 --- a/lib/olelo/attributeeditor.rb +++ b/lib/olelo/attributeeditor.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- module Olelo module AttributeEditor def self.included(base) diff --git a/lib/olelo/config.rb b/lib/olelo/config.rb index 88a25215..d4000ff1 100644 --- a/lib/olelo/config.rb +++ b/lib/olelo/config.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- module Olelo class Config include Enumerable diff --git a/lib/olelo/extensions.rb b/lib/olelo/extensions.rb index f78c46b5..78ac57be 100644 --- a/lib/olelo/extensions.rb +++ b/lib/olelo/extensions.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- class Module # Generate accessor method with question mark def attr_reader?(*attrs) @@ -133,6 +132,21 @@ def try(name, *args) end class String + # Check if string is valid text encoding + if ''.respond_to?(:encoding) + def valid_text_encoding? + Encoding.compatible?('', self) + end + else + require 'iconv' + def valid_text_encoding? + Iconv.conv('utf-8', 'utf-8', self) + true + rescue + false + end + end + # Unindent string def unindent result = '' @@ -171,11 +185,6 @@ def cleanpath names.join('/') end - # Truncate string and add omission - def truncate(max, omission = '...') - (length > max ? self[0...max] + omission : self) - end - # Concatenate path components def /(name) "#{self}/#{name}".cleanpath diff --git a/lib/olelo/fs.rb b/lib/olelo/fs.rb index e845ebd0..313d3871 100644 --- a/lib/olelo/fs.rb +++ b/lib/olelo/fs.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- module Olelo class DirectoryFS def initialize(dir) diff --git a/lib/olelo/helper.rb b/lib/olelo/helper.rb index aa22b765..a8a56d1a 100644 --- a/lib/olelo/helper.rb +++ b/lib/olelo/helper.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- module Olelo module BlockHelper def blocks @@ -46,8 +45,8 @@ def pagination(path, last_page, page_nr, opts = {}) if last_page > 0 li = [] if page_nr > 0 - li << %{«} - li << %{} + li << %{«} + li << %{} end min = page_nr - 3 max = page_nr + 3 @@ -58,7 +57,7 @@ def pagination(path, last_page, page_nr, opts = {}) end max = [max, last_page].min min = [min, 0].max - li << '…' if min != 0 + li << '…' if min != 0 (min..max).each do |i| if i == page_nr li << %{#{i + 1}} @@ -66,10 +65,10 @@ def pagination(path, last_page, page_nr, opts = {}) li << %{#{i + 1}} end end - li << '…' if max != last_page + li << '…' if max != last_page if page_nr < last_page - li << %{} - li << %{»} + li << %{} + li << %{»} end '' end @@ -121,18 +120,13 @@ def action_path(path, action) end def edit_content(page) - return params[:content] if params[:content] - if page.content.respond_to?(:encoding) - return :error_binary.t(:page => page.title, :type => "#{page.mime.comment} (#{page.mime})") if page.content.encoding != __ENCODING__ + if params[:content] + params[:content] + elsif !page.content.valid_text_encoding? + :error_binary.t(:page => page.title, :type => "#{page.mime.comment} (#{page.mime})") else - begin - require 'iconv' - Iconv.conv('utf-8', 'utf-8', page.content) - rescue - return :error_binary.t(:page => page.title, :type => "#{page.mime.comment} (#{page.mime})") - end + params[:pos] ? page.content[params[:pos].to_i, params[:len].to_i].to_s : page.content end - params[:pos] ? page.content[params[:pos].to_i, params[:len].to_i].to_s : page.content end end diff --git a/lib/olelo/hooks.rb b/lib/olelo/hooks.rb index cdf883b8..efea57e2 100644 --- a/lib/olelo/hooks.rb +++ b/lib/olelo/hooks.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- module Olelo module Hooks def self.included(base) diff --git a/lib/olelo/i18n.rb b/lib/olelo/i18n.rb index ae9a05d2..cf4d6b6a 100644 --- a/lib/olelo/i18n.rb +++ b/lib/olelo/i18n.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- module Olelo module I18n @locale = nil diff --git a/lib/olelo/page.rb b/lib/olelo/page.rb index 0e57d558..1abdf914 100644 --- a/lib/olelo/page.rb +++ b/lib/olelo/page.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- module Olelo class Version attr_reader :id, :author, :date, :comment, :parents diff --git a/lib/olelo/patch.rb b/lib/olelo/patch.rb index 56da5e56..21d96e22 100644 --- a/lib/olelo/patch.rb +++ b/lib/olelo/patch.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- module Olelo class PatchParser include Util diff --git a/lib/olelo/plugin.rb b/lib/olelo/plugin.rb index 0253b4c2..7a9da7b4 100644 --- a/lib/olelo/plugin.rb +++ b/lib/olelo/plugin.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- module Olelo # Olelo plugin system class Plugin diff --git a/lib/olelo/routing.rb b/lib/olelo/routing.rb index be6c3241..47e3f345 100644 --- a/lib/olelo/routing.rb +++ b/lib/olelo/routing.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- module Olelo module Routing def self.included(base) @@ -18,17 +17,12 @@ def call!(env) @response = Rack::Response.new @params = @original_params = @request.params.with_indifferent_access - # Interpret everything as utf-8 - if ''.respond_to? :encoding - encode(@env) - encode(@params) - end - catch(:forward) do with_hooks(:request) { perform! } status, header, body = response.finish return [status, header, request.head? ? [] : body] end + @app ? @app.call(env) : error!(NotFound.new(@request.path_info)) end @@ -50,25 +44,6 @@ def forward private - # Interpret everything as utf-8 - def encode(x) - case x - when Hash - x.each { |k,v| x[k] = encode(v) } - when Array - x.each_with_index {|v,i| x[i] = encode(v) } - when String - if x.encoding != __ENCODING__ - x = x.dup if x.frozen? - x.force_encoding(__ENCODING__) - else - x - end - else - x - end - end - def error!(ex) response.status = Rack::Utils.status_code(ex.try(:status) || :internal_server_error) response.body = [ex.message] diff --git a/lib/olelo/templates.rb b/lib/olelo/templates.rb index bed4aa87..a91c8993 100644 --- a/lib/olelo/templates.rb +++ b/lib/olelo/templates.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- module Olelo module Templates HAML_OPTIONS = { :format => :xhtml, :attr_wrapper => '"', :ugly => true, :escape_html => true } diff --git a/lib/olelo/timer.rb b/lib/olelo/timer.rb index c8b3e8a2..87992543 100644 --- a/lib/olelo/timer.rb +++ b/lib/olelo/timer.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- module Olelo class Timer def initialize diff --git a/lib/olelo/user.rb b/lib/olelo/user.rb index f6b36f3d..3941d8c7 100644 --- a/lib/olelo/user.rb +++ b/lib/olelo/user.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- module Olelo class AuthenticationError < RuntimeError end diff --git a/lib/olelo/util.rb b/lib/olelo/util.rb index 0a47c7b8..b0ac2eb4 100644 --- a/lib/olelo/util.rb +++ b/lib/olelo/util.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- module Olelo class NotFound < NameError def initialize(id) @@ -64,32 +63,39 @@ def check # Like CGI.escape but escapes space not as + def escape(s) + s = s.to_s s.gsub(/([^a-zA-Z0-9_.-]+)/) do '%' + $1.unpack('H2' * $1.bytesize).join('%').upcase end end # Like CGI.unescape but does not unescape + - def unescape(s) - if s.respond_to? :encoding + if ''.respond_to? :encoding + def unescape(s) + s = s.to_s enc = s.encoding s.gsub(/((?:%[0-9a-fA-F]{2})+)/) do [$1.delete('%')].pack('H*').force_encoding(enc) end - else - s.gsub(/((?:%[0-9a-fA-F]{2})+)/) do + end + else + def unescape(s) + s.to_s.gsub(/((?:%[0-9a-fA-F]{2})+)/) do [$1.delete('%')].pack('H*') end end end - def unescape_backslash(s) - if s.respond_to? :encoding + if ''.respond_to? :encoding + def unescape_backslash(s) + s = s.to_s enc = s.encoding s.gsub(/\\([0-7]{3})/) { $1.to_i(8).chr.force_encoding(enc) }. gsub(/\\x([\da-f]{2})/i) { $1.to_i(16).chr.force_encoding(enc) } - else - s.gsub(/\\([0-7]{3})/) { $1.to_i(8).chr }. + end + else + def unescape_backslash(s) + s.to_s.gsub(/\\([0-7]{3})/) { $1.to_i(8).chr }. gsub(/\\x([\da-f]{2})/i) { $1.to_i(16).chr } end end @@ -125,5 +131,24 @@ def build_query(params) end end.join('&') end + + # Truncate string and add omission + if ''.respond_to?(:encoding) + def truncate(s, max, omission = '...') + s = s.to_s + (s.length > max ? s[0...max] + omission : s) + end + else + def truncate(s, max, omission = '...') + s = s.to_s + if s.length > max + max += 1 until max >= s.length || s[0...max].valid_text_encoding? + s[0...max] + omission + else + s + end + end + end + end end diff --git a/lib/rack/degrade_mime_type.rb b/lib/rack/degrade_mime_type.rb index 57632b54..3870a59d 100644 --- a/lib/rack/degrade_mime_type.rb +++ b/lib/rack/degrade_mime_type.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- module Rack class DegradeMimeType def initialize(app) diff --git a/lib/rack/force_encoding.rb b/lib/rack/force_encoding.rb new file mode 100644 index 00000000..7bcba1bf --- /dev/null +++ b/lib/rack/force_encoding.rb @@ -0,0 +1,39 @@ +module Rack + class ForceEncoding + def initialize(app, encoding = Encoding::UTF_8) + @app = app + @encoding = encoding + end + + def call(env) + request = Rack::Request.new(env) + encode(env) + encode(request.params) + @app.call(env) + end + + private + + def encode(x) + case x + when Hash + x.each { |k,v| x[k] = encode(v) } + when Array + x.each_with_index {|v,i| x[i] = encode(v) } + when String + # Try to force encoding and revert to old encoding if this doesn't work + encoding = x.encoding + if encoding != @encoding + x = x.dup if x.frozen? + x.force_encoding(@encoding) + x.force_encoding(encoding) if !x.valid_encoding? + x + else + x + end + else + x + end + end + end +end diff --git a/lib/rack/patches.rb b/lib/rack/patches.rb index 2724f285..fcf504c0 100644 --- a/lib/rack/patches.rb +++ b/lib/rack/patches.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- require 'rack' require 'rack/session/abstract/id' require 'socket' diff --git a/plugins/editor/enhanced_edit.rb b/plugins/editor/enhanced_edit.rb index 1f07767c..83775b8d 100644 --- a/plugins/editor/enhanced_edit.rb +++ b/plugins/editor/enhanced_edit.rb @@ -47,7 +47,7 @@ class Olelo::Application # Read in binary mode and fix encoding afterwards patch = IO.popen("diff -u '#{original.path}' '#{new.path}'", 'rb') {|io| io.read } - patch.force_encoding(__ENCODING__) if patch.respond_to? :force_encoding + patch.force_encoding(Encoding::UTF_8) if patch.respond_to? :force_encoding @patch = PatchParser.parse(patch, PatchFormatter.new).html halt render(:edit) diff --git a/plugins/engine/tree.rb b/plugins/engine/tree.rb index d1eb2fc2..bd0d46db 100644 --- a/plugins/engine/tree.rb +++ b/plugins/engine/tree.rb @@ -36,8 +36,8 @@ def output(context) %td.link %a{:href=>page_path(child), :class => classes}= child.name %td!= date(child.version.date) - %td= child.version.author.name.truncate(30) - %td= child.version.comment.truncate(30) + %td= truncate(child.version.author.name, 30) + %td= truncate(child.version.comment, 30) %td.actions %a.action-edit{:href=>action_path(child, :edit), :title => :edit.t}= :edit.t %a.action-history{:href=>action_path(child, :history), :title => :history.t}= :history.t diff --git a/plugins/repository/git/grep.rb b/plugins/repository/git/grep.rb index 7c7fedb2..1f03ac25 100644 --- a/plugins/repository/git/grep.rb +++ b/plugins/repository/git/grep.rb @@ -37,7 +37,7 @@ class Olelo::Application path.pop if Repository.instance.reserved_name?(path.last) path = path.join('/') page = Page.find!(path) - @matches[path] = [page.content.truncate(500)] if page.mime.text? + @matches[path] = [truncate(page.content, 500)] if page.mime.text? end rescue => ex logger.error ex @@ -56,7 +56,7 @@ class Olelo::Application private def emphasize(s) - escape_html(s.truncate(500)).gsub(/(#{params[:pattern]})/i, '\1') + escape_html(truncate(s, 500)).gsub(/(#{params[:pattern]})/i, '\1') end end diff --git a/plugins/repository/git/repository.rb b/plugins/repository/git/repository.rb index 45cced64..371e77a5 100644 --- a/plugins/repository/git/repository.rb +++ b/plugins/repository/git/repository.rb @@ -86,9 +86,11 @@ def load_content(page) object = object[CONTENT_FILE] if object.type == :tree if object content = object.data + # Try to force utf-8 encoding and revert to old encoding if this doesn't work if content.respond_to? :force_encoding - content.force_encoding(__ENCODING__) - content.force_encoding(Encoding::BINARY) if !content.valid_encoding? + encoding = content.encoding + content.force_encoding(Encoding::UTF_8) + content.force_encoding(encoding) if !content.valid_encoding? end content else diff --git a/test/olelo_util_test.rb b/test/olelo_util_test.rb index 03722606..077de1c9 100644 --- a/test/olelo_util_test.rb +++ b/test/olelo_util_test.rb @@ -49,4 +49,9 @@ it 'should have #build_query' do Olelo::Util.build_query(:a => 1, :b => [1, 2, 3]).should.equal 'a=1&b=1&b=2&b=3' end + + it 'should have #truncate' do + Olelo::Util.truncate('Annabel Lee It was many and many a year ago', 11).should.equal 'Annabel Lee...' + Olelo::Util.truncate('In a kingdom by the sea', 39).should.equal 'In a kingdom by the sea' + end end diff --git a/test/request_test.rb b/test/request_test.rb index c19f7778..6656c00b 100644 --- a/test/request_test.rb +++ b/test/request_test.rb @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- require 'helper' +require 'rack/force_encoding' Rack::MockRequest::DEFAULT_ENV['REMOTE_ADDR'] = 'localhorst' @@ -62,6 +63,10 @@ class Bacon::Context logger = Logger.new(File.join(@app_path, 'test.log')) @app = Rack::Builder.new do + if ''.respond_to? :encoding + require 'rack/force_encoding' + use Rack::ForceEncoding + end run Olelo::Application.new(nil, :logger => logger) end diff --git a/test/string_extensions_test.rb b/test/string_extensions_test.rb index 1220e484..a7516284 100644 --- a/test/string_extensions_test.rb +++ b/test/string_extensions_test.rb @@ -24,11 +24,6 @@ '1///2'.cleanpath.should.equal '1/2' end - it 'should have #truncate' do - 'Annabel Lee It was many and many a year ago'.truncate(11).should.equal 'Annabel Lee...' - 'In a kingdom by the sea'.truncate(39).should.equal 'In a kingdom by the sea' - end - it 'should have #/' do (''/'').should.equal '' ('//a/b///'/'').should.equal 'a/b' diff --git a/views/history.haml b/views/history.haml index 86279b6c..d97fb629 100644 --- a/views/history.haml +++ b/views/history.haml @@ -13,10 +13,10 @@ - @history.each do |version| %tr{:id =>"version-#{version}"} %td - %a{:href => page_path(page, :version => version)}= version.comment.truncate(50) + %a{:href => page_path(page, :version => version)}= truncate(version.comment, 50) ( %a{:href => absolute_path(page.path/'changes'/version) }<>= :changes.t ) - %td= version.author.name.truncate(30) + %td= truncate(version.author.name, 30) %td!= date version.date != pagination(action_path(page, 'history'), @last_page, @page_nr) diff --git a/views/layout.haml b/views/layout.haml index cade7bd2..e24fc505 100644 --- a/views/layout.haml +++ b/views/layout.haml @@ -29,6 +29,6 @@ != footer .noprint.powered_by Powered by - %a(href='http://github.com/minad/olelo') Ōlelo + %a(href='http://github.com/minad/olelo') Ōlelo | #{timer.stop.elapsed_ms}ms %script(src='#{absolute_path "static/script.js?10"}' type='text/javascript')