Skip to content

Commit

Permalink
wip: Fix Reline ASCII-8BIT <-> UTF-8 issues
Browse files Browse the repository at this point in the history
  • Loading branch information
sjanusz-r7 committed Sep 30, 2024
1 parent 953f6c1 commit bea0973
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 4 deletions.
4 changes: 2 additions & 2 deletions lib/msf/ui/console/driver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def initialize(prompt = DefaultPrompt, prompt_char = DefaultPromptChar, opts = {
# Initialize the user interface to use a different input and output
# handle if one is supplied
input = opts['LocalInput']
input ||= Rex::Ui::Text::Input::Stdio.new
input ||= Rex::Ui::Text::Input::Utf8Stdio.new

if !opts['Readline']
input.disable_readline
Expand All @@ -118,7 +118,7 @@ def initialize(prompt = DefaultPrompt, prompt_char = DefaultPromptChar, opts = {
output = opts['LocalOutput']
end
else
output = Rex::Ui::Text::Output::Stdio.new
output = Rex::Ui::Text::Output::Utf8Stdio.new
end

init_ui(input, output)
Expand Down
1 change: 1 addition & 0 deletions lib/rex/ui/text/input/readline.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ def pgets
::Reline::HISTORY.pop if (line and line.empty?)
ensure
Thread.current.priority = orig || 0
output.prompting(false)
end

line
Expand Down
22 changes: 22 additions & 0 deletions lib/rex/ui/text/input/utf8_buffer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# -*- coding: binary -*-

require 'rex/ui/text/input/utf8_common'

module Rex
module Ui
module Text

require 'rex/io/stream_abstraction'

###
#
# This class implements input against a socket.
#
###
class Input::Utf8Buffer < Rex::Ui::Text::Input::Buffer

end

end
end
end
28 changes: 28 additions & 0 deletions lib/rex/ui/text/input/utf8_common.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# -*- coding: binary -*-

module Rex
module Ui
module Text
class Input::Utf8Common
def self.with_utf8_encoding(&block)
external_encoding_on_entry = ::Encoding.default_external
::Encoding.default_external = ::Encoding::UTF_8

internal_encoding_on_entry = ::Encoding.default_internal
::Encoding.default_internal = ::Encoding::UTF_8

begin
return block.call
rescue StandardError => e
puts 'Input'
puts caller
elog('Failed to call block with UTF8 encoding', error: e)
ensure
::Encoding.default_external = external_encoding_on_entry
::Encoding.default_internal = internal_encoding_on_entry
end
end
end
end
end
end
31 changes: 31 additions & 0 deletions lib/rex/ui/text/input/utf8_readline.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# -*- coding: binary -*-

require 'rex/ui/text/input/utf8_common'

module Rex
module Ui
module Text

###
#
# This class implements standard input using Reline against
# standard input, and forces UTF8 encoding. It supports tab completion.
#
###
class Input::Utf8Readline < Input::Readline

def initialize(tab_complete_proc = nil)
super
puts 'Created new Readline object'
end

def pgets
Rex::Ui::Text::Input::Utf8Common.with_utf8_encoding do
super
end
end
end
end

end
end
20 changes: 20 additions & 0 deletions lib/rex/ui/text/input/utf8_socket.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: binary -*-

require 'rex/ui/text/input/utf8_common'

module Rex
module Ui
module Text

###
#
# This class implements input against a socket.
#
###
class Input::Utf8Socket < Rex::Ui::Text::Input::Socket

end

end
end
end
20 changes: 20 additions & 0 deletions lib/rex/ui/text/input/utf8_stdio.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: binary -*-

require 'rex/ui/text/input/utf8_common'

module Rex
module Ui
module Text

###
#
# This class implements input against standard in.
#
###
class Input::Utf8Stdio < Rex::Ui::Text::Input::Stdio

end

end
end
end
28 changes: 28 additions & 0 deletions lib/rex/ui/text/output/utf8_common.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# -*- coding: binary -*-

module Rex
module Ui
module Text
class Output::Utf8Common
def self.with_utf8_encoding(&block)
external_encoding_on_entry = ::Encoding.default_external
::Encoding.default_external = ::Encoding::UTF_8

internal_encoding_on_entry = ::Encoding.default_internal
::Encoding.default_internal = ::Encoding::UTF_8

begin
return block.call
rescue StandardError => e
puts 'Output'
puts caller
elog('Failed to call block with UTF8 encoding', error: e)
ensure
::Encoding.default_external = external_encoding_on_entry
::Encoding.default_internal = internal_encoding_on_entry
end
end
end
end
end
end
32 changes: 32 additions & 0 deletions lib/rex/ui/text/output/utf8_stdio.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# -*- coding: binary -*-

require 'rex/ui/text/output/utf8_common'

module Rex
module Ui
module Text

###
#
# This class implements output against standard out.
#
###
class Output::Utf8Stdio < Rex::Ui::Text::Output::Stdio

def print_line(msg = '')
Output::Utf8Common.with_utf8_encoding do
super
end
end

def print_raw(msg = '')
Output::Utf8Common.with_utf8_encoding do
super
end
end
end

end
end
end

18 changes: 16 additions & 2 deletions lib/rex/ui/text/shell.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: binary -*-
require 'rex/text/color'
require 'rex/ui/text/input/utf8_readline'

module Rex
module Ui
Expand Down Expand Up @@ -67,9 +68,13 @@ def init_tab_complete
if (self.input and self.input.supports_readline)
# Unless cont_flag because there's no tab complete for continuation lines
tab_complete_lambda = proc do |str, preposing = nil, postposing = nil|
next tab_complete(str, opts: { preposing: preposing, postposing: postposing }).map { |result| result[preposing.to_s.length..] } unless cont_flag
values = tab_complete(str, opts: { preposing: preposing, postposing: postposing }).map { |result| result[preposing.to_s.length..] } unless cont_flag

encoded_values = self.input.class.name.include?('Utf8') ? values&.map { |val| val.encode('UTF-8') } : values

next encoded_values if encoded_values
end
self.input = Input::Readline.new(tab_complete_lambda)
self.input = Input::Utf8Readline.new(tab_complete_lambda)
self.input.output = self.output
end
end
Expand Down Expand Up @@ -523,6 +528,15 @@ def try_exec(command)

attr_writer :cont_flag # :nodoc:

def with_error_handling(proc)
proc do |*args|
proc.call(*args)
rescue StandardError => e
elog("tab_complete_proc has failed with args #{args}", error: e)
[]
end
end

end

end end end

0 comments on commit bea0973

Please sign in to comment.