Clean up embedded messages

This commit is contained in:
Omar Roth 2019-09-18 22:49:00 -04:00
parent bfe9627836
commit 1505d7c12c
No known key found for this signature in database
GPG Key ID: B8254FB7EC3D37F2

View File

@ -59,15 +59,6 @@ struct ProtoBuf::Any
def initialize(@raw : Type) def initialize(@raw : Type)
end end
def self.likely_string?(bytes)
return bytes.all? { |byte| {'\t'.ord, '\n'.ord, '\r'.ord}.includes?(byte) || 0x20 <= byte <= 0x7e }
end
def self.likely_base64?(string)
decoded = URI.unescape(URI.unescape(string))
return decoded.size % 4 == 0 && decoded.match(/[A-Za-z0-9_+\/-]+=*/)
end
def self.parse(io : IO) def self.parse(io : IO)
from_io(io, ignore_exceptions: true) from_io(io, ignore_exceptions: true)
end end
@ -113,24 +104,22 @@ struct ProtoBuf::Any
bytes = Bytes.new(size) bytes = Bytes.new(size)
io.read_fully(bytes) io.read_fully(bytes)
if bytes.empty? value = String.new(bytes)
if value.empty?
value = "" value = ""
elsif value.valid_encoding? && !value.codepoints.any? { |codepoint|
(0x00..0x1f).includes?(codepoint) &&
!{0x09, 0x0a, 0x0d}.includes?(codepoint)
}
begin
value = from_io(IO::Memory.new(Base64.decode(URI.unescape(URI.unescape(value))))).raw
rescue ex
end
else else
if likely_string?(bytes) begin
value = String.new(bytes) value = from_io(IO::Memory.new(bytes)).raw
rescue ex
if likely_base64?(value) value = bytes.to_a
begin
value = from_io(IO::Memory.new(Base64.decode(URI.unescape(URI.unescape(value))))).raw
rescue ex
end
end
else
begin
value = from_io(IO::Memory.new(bytes)).raw
rescue ex
value = bytes.to_a
end
end end
end end
else else
@ -141,9 +130,7 @@ struct ProtoBuf::Any
index += 1 index += 1
end end
rescue ex rescue ex
if !ignore_exceptions raise ex if !ignore_exceptions
raise ex
end
end end
item item
@ -178,17 +165,18 @@ enum OutputType
JsonPretty JsonPretty
end end
input_type = InputType::Hex input_type = InputType::Raw
output_type = OutputType::Json output_type = OutputType::Json
OptionParser.parse! do |parser| OptionParser.parse! do |parser|
parser.banner = <<-'END_USAGE' parser.banner = <<-'END_USAGE'
Usage: protodec [arguments] Usage: protodec [arguments]
Command-line decoder for arbitrary protobuf data. Command-line decoder for arbitrary protobuf data. Reads from standard input.
END_USAGE END_USAGE
parser.on("-d", "--decode", "STDIN is Base64-encoded") { input_type = InputType::Base64 } parser.on("-d", "--decode", "STDIN is Base64-encoded") { input_type = InputType::Base64 }
parser.on("-r", "--raw", "STDIN is raw binary data") { input_type = InputType::Raw } parser.on("-x", "--hex", "STDIN is space-separated hexstring") { input_type = InputType::Hex }
parser.on("-r", "--raw", "STDIN is raw binary data (default)") { input_type = InputType::Raw }
parser.on("-p", "--pretty", "Pretty print output") { output_type = OutputType::JsonPretty } parser.on("-p", "--pretty", "Pretty print output") { output_type = OutputType::JsonPretty }
parser.on("-h", "--help", "Show this help") { puts parser; exit(0) } parser.on("-h", "--help", "Show this help") { puts parser; exit(0) }
end end
@ -196,7 +184,7 @@ end
input = STDIN.gets_to_end input = STDIN.gets_to_end
case input_type case input_type
when InputType::Base64 when InputType::Base64
input = Base64.decode(URI.unescape(URI.unescape(input))) input = Base64.decode(URI.unescape(URI.unescape(input.strip)))
when InputType::Hex when InputType::Hex
array = input.strip.split(/[- ,]+/).map &.to_i(16).to_u8 array = input.strip.split(/[- ,]+/).map &.to_i(16).to_u8
input = Slice.new(array.size) { |i| array[i] } input = Slice.new(array.size) { |i| array[i] }